Exemplo n.º 1
0
 def test_absolute_time_converter_utc_string(self):
     """
     absolute_time_converter_utc_string tests
     """
     self.assertTrue(
         orekit_utils.absolute_time_converter_utc_manual(
             2020, 12, 2).isEqualTo(
                 orekit_utils.absolute_time_converter_utc_string(
                     '2020-12-02T00:00:00.000')))
     self.assertTrue(
         orekit_utils.absolute_time_converter_utc_manual(
             2020, 12, 2, 3).isEqualTo(
                 orekit_utils.absolute_time_converter_utc_string(
                     '2020-12-02T03:00:00.000')))
     self.assertTrue(
         orekit_utils.absolute_time_converter_utc_manual(
             2020, 12, 2, 3, 12).isEqualTo(
                 orekit_utils.absolute_time_converter_utc_string(
                     '2020-12-02T03:12:00.000')))
     self.assertTrue(
         orekit_utils.absolute_time_converter_utc_manual(
             2020, 12, 2, 3, 12, 13).isEqualTo(
                 orekit_utils.absolute_time_converter_utc_string(
                     '2020-12-02T03:12:13.000')))
     self.assertTrue(
         orekit_utils.absolute_time_converter_utc_manual(
             2020, 12, 2, 3, 12, 13.2).isEqualTo(
                 orekit_utils.absolute_time_converter_utc_string(
                     '2020-12-02T03:12:13.200')))
Exemplo n.º 2
0
    def calculate_position(self, generic, duration, step_count=None):
        """ 
        Updates position of the satellite for some number of time steps into the future,
        and update the packet to contain Cartesian coordinates

        Args:
            generic (string JSON): CZML boilerplate, from the configuration in config-service
            duration (float): the duration of time after start that the user wishes to display, in seconds
            step_count (int): number of positions to include in the packet. Note - Cesium has 5th-order Lagrangian interpolation. 300.0 sec is fine
        """
        # Default step count defined in terms of duration
        generic = deepcopy(generic)

        if step_count == None:
            step_count = int(duration / 300)

        step_size = float(duration / step_count)
        stop = orekit_utils.absolute_time_converter_utc_string(
            self.start).shiftedBy(float(duration)).toString()
        start = ISO8601_UTC(self.start)
        stop = ISO8601_UTC(stop)

        validate_datetime(start)
        validate_datetime(stop)

        self.packet["availability"] = f"{start}/{stop}"
        self.packet["position"]["epoch"] = start

        prop = orekit_utils.analytical_propagator(self.orbit)
        positions = []
        for i in range(step_count):
            orekit_time = orekit_utils.absolute_time_converter_utc_string(
                start).shiftedBy(i * float(step_size))
            pos = prop.getPVCoordinates(orekit_time, prop.getFrame())
            pos = list(pos.position.toArray())
            pos.insert(0, i * float(step_size))
            positions.extend(pos)
        self.packet["position"]["cartesian"] = positions

        # TODO
        lead_trail_time = orekit_utils.absolute_time_converter_utc_string(
            start).shiftedBy(generic["lead_and_trail"]).toString()
        lead_trail_time = ISO8601_UTC(lead_trail_time)

        validate_datetime(lead_trail_time)

        interval = f"{start}/{lead_trail_time}"

        lead_and_trail = ["leadTime", "trailTime"]

        for lt in lead_and_trail:
            self.packet["path"][lt].append({})
            self.packet["path"][lt][0]["interval"] = interval
            self.packet["path"][lt][0]["epoch"] = start
            self.packet["path"][lt][0]["number"] = [
                0, generic["lead_and_trail_number"],
                generic["lead_and_trail_number"], 0
            ]
Exemplo n.º 3
0
    def update_packet(self, duration):
        """ 
        Update the packet attributre

        Args:
            duration (float): the duration of time after start that the user wishes to display, in seconds. This should be a big number if the user doesn't want it to disappear.
        """
        
        start = self.start
        orbit = self.sat_orbit
        grstn_latitude = self.grstn_location["latitude"]
        grstn_longitude = self.grstn_location["longitude"]
        grstn_altitude = self.grstn_location["altitude"]
        
        start_orekit = orekit_utils.absolute_time_converter_utc_string(start)
        stop_orekit = orekit_utils.absolute_time_converter_utc_string(start).shiftedBy(float(duration))
        
        prop = orekit_utils.analytical_propagator(orbit)
        eclipses = orekit_utils.get_ground_passes(prop, grstn_latitude, grstn_longitude, grstn_altitude, start_orekit, stop_orekit, ploting_param=False)
        
        if len(eclipses):
            self.packet["polyline"]["show"].append({})
            
            if not eclipses[0]['start']:
                eclipses[0]['start'] = start_orekit
            first_end = ISO8601_UTC(eclipses[0]['start'].toString())
            validate_datetime(first_end)
            
            self.packet["polyline"]["show"][0]["interval"] = f"0000-01-01T00:00:00/{first_end}"
            self.packet["polyline"]["show"][0]["boolean"] = False
            
            for i,d in enumerate(eclipses):
                show = {}
                start_vis = ISO8601_UTC(d['start'].toString())
                stop_vis = ISO8601_UTC(d['stop'].toString())
                
                validate_datetime(start_vis)
                validate_datetime(stop_vis)
                
                visible_interval = f"{start_vis}/{stop_vis}"
                show["interval"] = visible_interval
                show["boolean"] = True
                self.packet["polyline"]["show"].append(show)
                self.packet["availability"].append(visible_interval)
                
                # only add the period after if it is with the stop time
                if i + 1 < len(eclipses):
                    dont_show = {}
                    last_interval_start = ISO8601_UTC(eclipses[i]['stop'].toString())
                    last_interval_stop = ISO8601_UTC(eclipses[i+1]['start'].toString())
                    
                    validate_datetime(last_interval_start)
                    validate_datetime(last_interval_stop)
                    
                    dont_show["interval"] = f"{last_interval_start}/{last_interval_stop}"
                    dont_show["boolean"] = False
                    self.packet["polyline"]["show"].append(dont_show)
Exemplo n.º 4
0
    def update_orbit(self, orbit):
        """ 
        Generate a new orbit packet, with duration as specified in the constructor.

        Args:
            orbit (dict): A nested python dictionary with orbital parameters.
        """
        new_date = orekit_utils.absolute_time_converter_utc_string(orbit["orbit_update_date"])
        old_date = orekit_utils.absolute_time_converter_utc_string(self.orbit["orbit_update_date"])
        if new_date.isAfter(old_date):
            self.sat_orbit = orbit
Exemplo n.º 5
0
    def __init__(self, generic, name, start, duration, location):
        """ 
        Construct a ground station packet.

        Args:
            generic (string JSON): CZML boilerplate, from the configuration in config-service
            name (string): the name of the ground station the user wishes want to display
            start (string): the current time (from which the user wishes to display)
            duration (float): the duration of time after start that the user wishes to display, in seconds. This should be a big number if the user doesn't want it to disappear.
            location (dict): dictionary containing float latitude, longitude, and altitude of the ground station
        """
        generic = deepcopy(generic)

        latitude = location["latitude"]
        longitude = location["longitude"]
        altitude = location["altitude"]
        
        self.start = start
        stop = orekit_utils.absolute_time_converter_utc_string(start).shiftedBy(float(duration)).toString()
        start = ISO8601_UTC(start)
        stop = ISO8601_UTC(stop)
        
        validate_datetime(start)
        validate_datetime(stop)
        
        _name = name.replace(" ", "_")
        
        self.packet = generic["grstn"]
        self.packet["id"] = f"Facility/{_name}"
        self.packet["name"] = _name
        self.packet["availability"] = f"{start}/{stop}"
        self.packet["position"]["cartographicDegrees"] = [float(longitude), float(latitude), float(altitude)]
        self.packet["label"]["text"] = name
Exemplo n.º 6
0
    def __init__(self, generic, start, duration):
        """
        Generate the initial CZML packets from boilerplate

        Args:
            generic (string JSON): CZML boilerplate, from the configuration in config-service
            start (string): the current time (from which the user wishes to display)
            duration ([type]): the duration of time after start that the user wishes to display, in seconds
        """
        generic = deepcopy(generic)

        stop = orekit_utils.absolute_time_converter_utc_string(
            start).shiftedBy(float(duration)).toString()
        start = ISO8601_UTC(start)
        stop = ISO8601_UTC(stop)

        validate_datetime(start)
        validate_datetime(stop)
        timestep = generic["timestep"]
        real_time = generic["real_time"]
        speed = int(timestep / real_time)
        generic1 = generic["generic_1"]
        generic1["clock"]["interval"] = f"{start}/{stop}"
        generic1["clock"]["currentTime"] = f"{start}"
        generic1["clock"]["multiplier"] = speed

        generic2 = generic["generic_2"]
        self.list = [generic1, generic2]
Exemplo n.º 7
0
    def test_keplerian_orbit(self):
        """
        keplerian_orbit test
        """
        parameters = {
                    "eccentricity": 0.0008641,
                    "semimajor_axis": 6801395.04,
                    "inclination": radians(87.0),
                    "perigee_argument": radians(20.0),
                    "right_ascension_of_ascending_node":radians(10.0),
                    "anomaly": radians(0.0),
                    "anomaly_type": "TRUE",
                    "orbit_update_date":'2021-12-02T00:00:00.000',
                    "frame": "EME"}
        k_orbit = keplerian_orbit(parameters)

        eccentricity = parameters["eccentricity"]
        semimajor_axis = parameters["semimajor_axis"]
        inclination = parameters["inclination"]
        perigee_argument = parameters["perigee_argument"]
        right_ascension_of_ascending_node = parameters["right_ascension_of_ascending_node"]
        true_anomaly = parameters["anomaly"]
        orbit_update_date = parameters["orbit_update_date"]
        epochDate = absolute_time_converter_utc_string(orbit_update_date)
        frame = orekit_utils.string_to_frame(parameters["frame"])

        self.assertTrue(KeplerianOrbit(semimajor_axis, eccentricity, inclination, perigee_argument,
                                    right_ascension_of_ascending_node,
                                    true_anomaly, PositionAngle.TRUE,
                                    frame, epochDate,
                                    Constants.WGS84_EARTH_MU).toString() == k_orbit.toString())
Exemplo n.º 8
0
    def test_get_keplerian_parameters(self):
        """
        get_keplerian_parameters test
        """
        parameters = {
                    "eccentricity": 0.0008641,
                    "semimajor_axis": 6801395.04,
                    "inclination": radians(87.0),
                    "perigee_argument": radians(20.0),
                    "right_ascension_of_ascending_node": radians(10.0),
                    "anomaly": radians(0.0),
                    "anomaly_type": "TRUE",
                    "orbit_update_date":'2021-12-02T00:00:00.000',
                    "frame": "EME"}

        propagator_1 = analytical_propagator(parameters)
        orbit = keplerian_orbit(parameters)

        new_state = SpacecraftState(orbit)
        new_parameters = orekit_utils.get_keplerian_parameters(new_state)

        propagator_2 = keplerian_orbit(new_parameters)
        new_time = absolute_time_converter_utc_string('2021-12-05T00:00:00.000')

        distance = orekit_utils.find_sat_distance(propagator_1, propagator_2, new_time)
        # parameters value change but define same orbit
        self.assertTrue(distance <= 0.000001)
Exemplo n.º 9
0
    def test_analytical_propagator(self):
        """
        analytical_propagator test
        """
        parameters = {
            "eccentricity": 0.0008641,
            "semimajor_axis": 6801395.04,
            "inclination": radians(87.0),
            "perigee_argument": radians(20.0),
            "right_ascension_of_ascending_node": radians(10.0),
            "anomaly": radians(0.0),
            "anomaly_type": "TRUE",
            "orbit_update_date": '2021-12-02T00:00:00.000',
            "frame": "EME"
        }
        k_orbit = keplerian_orbit(parameters)
        test1 = analytical_propagator(parameters)
        test2 = KeplerianPropagator(keplerian_orbit(parameters),
                                    Constants.WGS84_EARTH_MU)
        time1 = orekit_utils.absolute_time_converter_utc_string(
            '2022-01-02T00:00:00.000')

        self.assertTrue(
            test1.getPVCoordinates(time1, FramesFactory.getEME2000()).toString(
            ) == test2.getPVCoordinates(time1,
                                        FramesFactory.getEME2000()).toString())
Exemplo n.º 10
0
 def test_str_tle_propagator(self):
     tle_line1 = "1 25544U 98067A   20174.66385417  .00000447  00000-0  16048-4 0  9992"
     tle_line2 = "2 25544  51.6446 321.3575 0002606  75.8243 105.9183 15.49453790232862"
     propagator_1 = orekit_utils.str_tle_propagator(tle_line1, tle_line2)
     TLE = orekit_utils.convert_tle_string_to_TLE(tle_line1, tle_line2)
     propagator_2 = TLEPropagator.selectExtrapolator(TLE)
     time = absolute_time_converter_utc_string('2020-12-02T00:00:00.000')
     self.assertTrue(propagator_1.propagate(time).getOrbit().toString() == propagator_2.propagate(time).getOrbit().toString())
Exemplo n.º 11
0
    def __init__(self, generic, name, start, duration, orbit):
        """
        Generate a standard CZML packet for displaying a satellite in Cesium, with configuration
        specified in "generic" argument

        Args:
            generic (string JSON): CZML boilerplate, from the configuration in config-service
            name (string): the name of the satellite the user wishes want to display
            start (string): the current time (from which the user wishes to display)
            duration (float): the duration of time after start that the user wishes to display, in seconds
            orbit (dict): dict containing the satellites keplerian orbital elements
        """

        generic = deepcopy(generic)
        # need to save before it is converted to a different format
        self.start = start
        stop = orekit_utils.absolute_time_converter_utc_string(
            start).shiftedBy(float(duration)).toString()

        start = ISO8601_UTC(start)
        stop = ISO8601_UTC(stop)

        validate_datetime(start)
        validate_datetime(stop)

        self.orbit = orbit
        self.name = name
        packet = {}
        _name = name.replace(" ", "_")
        self._name = name
        packet['id'] = f"Satellite/{_name}"
        packet['name'] = _name

        billboard = generic["billboard"]
        label = generic["label"]
        path = generic["path"]
        position = generic["position"]
        satellite_description = generic["satellite_description"]

        # set availability from the current date/time until a very long time in the future
        availability = f"{start}/{stop}"
        packet['availability'] = availability
        packet['description'] = satellite_description
        packet['billboard'] = billboard
        packet['label'] = label

        # record the correct name
        packet['label']['text'] = name

        # record the templates for updating later
        packet["path"] = path
        packet["position"] = position

        # make path viewable in correct time range
        #TODO edit this
        packet["path"]["show"][0]["interval"] = availability

        self.packet = packet
Exemplo n.º 12
0
    def produce_links(self, save=False, new_shared_storage = None):
        """
        

        Args:
            save (bool, optional): Wether or not the packets should be saved. Defaults to True.
            new_shared_storage (dictionary, optional): A new dictionary containing satellite orbits,
            iot sensors, and groundstation to be used. Defaults to None.

        Returns:
            list: list of all of the inter satellite link packets
        """
        if new_shared_storage == None:
            shared_storage = self.shared_storage
        else:
            shared_storage = new_shared_storage
        satellite_links = self.satellite_links
        packet_links = []
        # for each element in the satellite links set make a packet
        for i in satellite_links:
            # find the names
            cubesat_a = i[i.find('/')+1:i.find('-')]
            cubesat_b = i[i.rfind('/')+1:]

            # create a orbit propagator for both satellites
            csat_a_prop = orekit_utils.analytical_propagator(shared_storage["swarm"][cubesat_a]["orbit"])
            csat_b_prop = orekit_utils.analytical_propagator(shared_storage["swarm"][cubesat_b]["orbit"])

            # create a list of times when the satellites can see each other
            start_time = orekit_utils.absolute_time_converter_utc_string(shared_storage["time"])            
            windows_array = orekit_utils.visible_above_horizon(csat_a_prop, csat_b_prop, start_time, self.duration)

            # create a list of times when the satellites can see and not see each other
            n_windows_array = self.process_time_window(windows_array)

            # create a list of objects when the satellite links can be shown for cesium
            show = self.create_show(n_windows_array)

            # create a list of times when the satellites can see and not see each other for cesium
            availability = self.create_availability(show)

            references = [i[:i.find("-to-")]+'#position', i[i.find("-to-") + 4:]+'#position']

            # Construct the packet with a generic link packet and data created above
            packet = deepcopy(self.shared_storage["generic"]["general_link"])
            packet["id"] = i
            packet["name"] = cubesat_a +" to " + cubesat_b
            packet["availability"] = availability
            packet["description"] = "<h1>Blah blah blah</h1>"   
            packet["polyline"]["show"] = show
            packet["polyline"]["positions"]["references"] = references
            packet_links.append(packet)
        # save as json if 
        if save:
            with open('data.json', 'w') as outfile:
                json.dump(packet_links, outfile)
        self.packets = packet_links
        return packet_links
Exemplo n.º 13
0
    def test_moving_body_pointing_law(self):
        """
        moving_body_pointing_law test
        """
        parameters = {
            "eccentricity": 0.0008641,
            "semimajor_axis": 6801395.04,
            "inclination": 87.0,
            "perigee_argument": 20.0,
            "right_ascension_of_ascending_node": 10.0,
            "anomaly": radians(0.0),
            "anomaly_type": "TRUE",
            "orbit_update_date": '2021-12-02T00:00:00.000',
            "frame": "EME"
        }
        parameters1 = {
            "eccentricity": 0.0008641,
            "semimajor_axis": 6801395.04,
            "inclination": 87.0,
            "perigee_argument": 10.0,
            "right_ascension_of_ascending_node": 10.0,
            "anomaly": radians(0.0),
            "anomaly_type": "TRUE",
            "orbit_update_date": '2021-12-02T00:00:00.000',
            "frame": "EME"
        }

        orbit_propagator_1 = analytical_propagator(parameters1)
        orbit_propagator_2 = analytical_propagator(parameters1)
        parameters["frame"] = orekit_utils.frame_to_string(
            orbit_propagator_1.getFrame())

        time_to_propagate = orekit_utils.absolute_time_converter_utc_string(
            '2022-05-02T00:00:00.000')
        orbit_to_track_propagator = analytical_propagator(parameters)

        test1 = CelestialBodyPointed(FramesFactory.getEME2000(),
                                     orbit_to_track_propagator,
                                     Vector3D.PLUS_K, Vector3D.PLUS_K,
                                     Vector3D.MINUS_J)
        test2 = moving_body_pointing_law(orbit_to_track_propagator, parameters)

        orbit_propagator_1.setAttitudeProvider(test1)
        orbit_propagator_2.setAttitudeProvider(test2)
        state_1 = orbit_propagator_1.propagate(time_to_propagate)
        state_2 = orbit_propagator_2.propagate(time_to_propagate)
        self.assertTrue((state_1.getAttitude().getSpin().toString() ==
                         state_2.getAttitude().getSpin().toString()))
Exemplo n.º 14
0
    def test_find_sat_distance(self):
        """
        find_distance tests: test some well known distances and zero cases
        """
        tle_line1 = "1 25544U 98067A   20174.66385417  .00000447  00000-0  16048-4 0  9992"
        tle_line2 = "2 25544  51.6446 321.3575 0002606  75.8243 105.9183 15.49453790232862"
        tle2_line1 = "1 44235U 19029A   20178.58335648  .01685877  00000-0  31131-1 0  9991"
        tle2_line2 = "2 44235  52.9995 164.3403 0009519 291.6111 354.0622 15.45232749 61668"

        prop1 = orekit_utils.str_tle_propagator(tle_line1, tle_line2)
        prop2 = orekit_utils.str_tle_propagator(tle2_line1, tle2_line2)

        time = orekit_utils.absolute_time_converter_utc_string('2020-12-02T00:00:00.000')

        self.assertEqual(orekit_utils.find_sat_distance(prop1,prop2,time),orekit_utils.find_sat_distance(prop1,prop2,time))
        self.assertEqual(orekit_utils.find_sat_distance(prop1,prop1,time),0.)
        self.assertEqual(orekit_utils.find_sat_distance(prop2,prop2,time),0.)
Exemplo n.º 15
0
    def test_ground_pointing_law(self):
        """
        ground_pointing_law test
        """
        parameters = {"latitude": 12.0, "altitude": 2343.0, "longitude": 12.0}
        parameters1 = {
            "eccentricity": 0.0008641,
            "semimajor_axis": 6801395.04,
            "inclination": 87.0,
            "perigee_argument": 10.0,
            "right_ascension_of_ascending_node": 10.0,
            "anomaly": radians(0.0),
            "anomaly_type": "TRUE",
            "orbit_update_date": '2021-12-02T00:00:00.000',
            "frame": "EME"
        }

        orbit_propagator_1 = analytical_propagator(parameters1)
        orbit_propagator_2 = analytical_propagator(parameters1)
        parameters["frame"] = orekit_utils.frame_to_string(
            orbit_propagator_1.getFrame())

        ITRF = FramesFactory.getITRF(IERSConventions.IERS_2010, True)
        target = GeodeticPoint(parameters["latitude"], parameters["longitude"],
                               parameters["altitude"])
        attitude_provider = ground_pointing_law(parameters)
        attitude_provider_1 = TargetPointing(
            FramesFactory.getEME2000(), target,
            OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
                             Constants.WGS84_EARTH_FLATTENING, ITRF))

        orbit_propagator_1.setAttitudeProvider(attitude_provider)
        orbit_propagator_2.setAttitudeProvider(attitude_provider_1)

        time_to_propagate = orekit_utils.absolute_time_converter_utc_string(
            '2022-05-02T00:00:00.000')
        state_1 = orbit_propagator_1.propagate(time_to_propagate)
        state_2 = orbit_propagator_2.propagate(time_to_propagate)

        self.assertTrue((state_1.getAttitude().getSpin().toString() ==
                         state_2.getAttitude().getSpin().toString()))
Exemplo n.º 16
0
    def test_attitude_provider_constructor(self):
        """
        attitude_provider_constructor test
        """
        moving_body = "moving_body_tracking"
        moving_body_param = {
                    "eccentricity": 0.0008641,
                    "semimajor_axis": 6801395.04,
                    "inclination": 87.0,
                    "perigee_argument": 10.0,
                    "right_ascension_of_ascending_node": 10.0,
                    "anomaly": 0.0,
                    "anomaly_type": "TRUE",
                    "orbit_update_date":"2021-12-02T00:00:00.000",
                    "frame": "EME"}

        orbit_params = {
                    "eccentricity": 0.0008641,
                    "semimajor_axis": 6801395.04,
                    "inclination": 87.0,
                    "perigee_argument": 20.0,
                    "right_ascension_of_ascending_node": 10.0,
                    "anomaly": 0.0,
                    "anomaly_type": "TRUE",
                    "orbit_update_date":'2021-12-02T00:00:00.000',
                    "frame": "EME"}

        orbit_propagator_1 = analytical_propagator(orbit_params)
        orbit_propagator_2 = analytical_propagator(orbit_params)

        attitude_m_body = attitude_provider_constructor(moving_body, moving_body_param)
        attitude_m_body_1 = moving_body_pointing_law(analytical_propagator(moving_body_param),moving_body_param)

        orbit_propagator_1.setAttitudeProvider(attitude_m_body)
        orbit_propagator_2.setAttitudeProvider(attitude_m_body_1)

        time_to_propagate = orekit_utils.absolute_time_converter_utc_string('2022-05-02T00:00:00.000')

        state_1 = orbit_propagator_1.propagate(time_to_propagate)
        state_2 = orbit_propagator_2.propagate(time_to_propagate)

        self.assertTrue((state_1.getAttitude().getSpin().toString() == state_2.getAttitude().getSpin().toString()))

        ground = "ground_tracking"
        ground_param = {
            "latitude": 12.0,
            "altitude": 2343.0,
            "longitude":12.0
            }
        parameters = {
                    "eccentricity": 0.0008641,
                    "semimajor_axis": 6801395.04,
                    "inclination": 87.0,
                    "perigee_argument": 10.0,
                    "right_ascension_of_ascending_node": 10.0,
                    "anomaly": radians(0.0),
                    "anomaly_type": "TRUE",
                    "orbit_update_date":'2021-12-02T00:00:00.000',
                    "frame": "EME"}

        orbit_propagator_1 = analytical_propagator(parameters)
        orbit_propagator_2 = analytical_propagator(parameters)
        ground_param["frame"] = orekit_utils.frame_to_string(orbit_propagator_1.getFrame())

        attitude_provider_1 = attitude_provider_constructor(ground, ground_param)
        attitude_provider_2 = ground_pointing_law(ground_param)

        orbit_propagator_1.setAttitudeProvider(attitude_provider_1)
        orbit_propagator_2.setAttitudeProvider(attitude_provider_2)

        time_to_propagate = orekit_utils.absolute_time_converter_utc_string('2022-05-02T00:00:00.000')
        state_1 = orbit_propagator_1.propagate(time_to_propagate)
        state_2 = orbit_propagator_2.propagate(time_to_propagate)

        self.assertTrue((state_1.getAttitude().getSpin().toString() == state_2.getAttitude().getSpin().toString()))
Exemplo n.º 17
0
async def simulation_timepulse_propagate(message, nats_handler, shared_storage,
                                         logger):
    """
    Propagates the satellites current orbit and attitude

    Args:
        message (natsmessage): message
            message.data dictionary with structure as described in message_structure.json
            message.data["time"] is the time update
        nats_handler (natsHandler): distributes callbacks according to the message subject
        shared_storage: dictionary containing information on on the entire swarm, the time, and the particular satellites phonebook
    """
    # Distance that will prevent satellites from communicating
    max_range = shared_storage["range"]

    # Updating time
    shared_storage["time"] = message.data["time"]

    cubesat_id = nats_handler.sender_id

    #  Making a propagator for satellite running this service
    self_orbit_propagator = orekit_utils.analytical_propagator(
        shared_storage["swarm"][cubesat_id]["orbit"])

    # Each satellite's state will be upated and the phonebook will be updated
    for satellite in shared_storage["swarm"]:
        # Info about each satellite state is accessed to propagate orbit and attitude
        orbit_propagator = orekit_utils.analytical_propagator(
            shared_storage["swarm"][satellite]["orbit"])
        attitude = shared_storage["swarm"][satellite]["orbit"]["attitude"]
        attitude_param = dict()
        frame = shared_storage["swarm"][satellite]["orbit"]["frame"]

        # Info about satellite attitude is accessed
        if attitude in shared_storage["swarm"]:
            attitude_provider_type = orekit_utils.utils.MOVING_BODY_TRACKING
            attitude_param = shared_storage["swarm"][attitude]["orbit"]

        elif attitude in shared_storage["grstns"]:
            attitude_provider_type = orekit_utils.utils.GROUND_TRACKING
            attitude_param = shared_storage["grstns"][attitude]["location"]

        elif attitude in shared_storage["iots"]:
            attitude_provider_type = orekit_utils.utils.GROUND_TRACKING
            attitude_param = shared_storage["iots"][attitude]["location"]

        elif attitude == orekit_utils.utils.NADIR_TRACKING:
            attitude_provider_type = attitude
        else:
            raise Exception("attitude unknown")

        # storing/updating reference frame
        attitude_param["frame"] = frame

        # constructing a attitude provider from info gathered above
        attitude_provider = orekit_utils.attitude_provider_constructor(
            attitude_provider_type, attitude_param)

        # the orbit propagator and attitude provider are consolidated
        orbit_propagator.setAttitudeProvider(attitude_provider)

        time = orekit_utils.absolute_time_converter_utc_string(
            shared_storage["time"])

        # new satellite state containg attitude and orbit info
        new_state = orbit_propagator.propagate(time)

        # the shared storage is updated as necessary
        shared_storage["swarm"][satellite][
            "orbit"] = orekit_utils.get_keplerian_parameters(new_state)
        shared_storage["swarm"][satellite]["orbit"].update({"frame": frame})
        shared_storage["swarm"][satellite]["orbit"].update(
            {"attitude": attitude})
        shared_storage["swarm"][satellite][
            "last_update_time"] = shared_storage["time"]

        # Checking if the satellites target is in view and upating shared storage accordingly
        if attitude_provider_type == orekit_utils.utils.GROUND_TRACKING:
            shared_storage["swarm"][satellite][
                "target_in_view"] = orekit_utils.check_iot_in_range(
                    orbit_propagator, attitude_param["latitude"],
                    attitude_param["longitude"], attitude_param["altitude"],
                    time)
        elif attitude_provider_type == orekit_utils.utils.NADIR_TRACKING:
            shared_storage["swarm"][satellite]["target_in_view"] = True

        elif attitude_provider_type == orekit_utils.utils.MOVING_BODY_TRACKING:
            tracked_propagator = orekit_utils.analytical_propagator(
                attitude_param)
            shared_storage["swarm"][satellite][
                "target_in_view"] = orekit_utils.visible_above_horizon(
                    orbit_propagator, tracked_propagator, time)
        else:
            raise Exception("attitude_provider unknown")

        # Updating phonebook based on the location of the satellites
        if satellite != cubesat_id:
            cur_orbit_propagator = orekit_utils.analytical_propagator(
                shared_storage["swarm"][satellite]["orbit"])

            time = orekit_utils.absolute_time_converter_utc_string(
                shared_storage["time"])

            distance = orekit_utils.find_sat_distance(self_orbit_propagator,
                                                      cur_orbit_propagator,
                                                      time)

            if distance < max_range and orekit_utils.visible_above_horizon(
                    self_orbit_propagator, cur_orbit_propagator, time):
                shared_storage["sat_phonebook"][satellite] = True
            else:
                shared_storage["sat_phonebook"][satellite] = False

    # Message contaning data on the updated state of a satellite is sent for each sent
    for sat_id in shared_storage["swarm"]:
        msg = nats_handler.create_message(
            {"state": {
                sat_id: shared_storage["swarm"][sat_id]
            }}, MessageSchemas.STATE_MESSAGE)
        subject = "state"
        await nats_handler.send_message(subject, msg)

    # The satellites updated phonebook is sent
    sat_phonebook_message = nats_handler.create_message(
        shared_storage["sat_phonebook"], MessageSchemas.PHONEBOOK_MESSAGE)
    await nats_handler.send_message("internal.phonebook",
                                    sat_phonebook_message)

    # IOT PHONEBOOK UPDATER
    for iot_id in shared_storage["iots"]:
        latitude = shared_storage["iots"][iot_id]["location"]["latitude"]
        longitude = shared_storage["iots"][iot_id]["location"]["longitude"]
        altitude = shared_storage["iots"][iot_id]["location"]["altitude"]

        if orekit_utils.check_iot_in_range(
                self_orbit_propagator, latitude, longitude, altitude,
                orekit_utils.absolute_time_converter_utc_string(
                    shared_storage["time"])):
            shared_storage["iot_phonebook"][iot_id] = True
        else:
            shared_storage["iot_phonebook"][iot_id] = False
    # Sending updated phonebook
    iot_phonebook_message = nats_handler.create_message(
        shared_storage["iot_phonebook"], MessageSchemas.PHONEBOOK_MESSAGE)
    await nats_handler.send_message("internal.iot_phonebook",
                                    iot_phonebook_message)

    #Groundstation Phonebook Updater
    for ground_id in shared_storage["grstns"]:
        latitude = shared_storage["grstns"][ground_id]["location"]["latitude"]
        longitude = shared_storage["grstns"][ground_id]["location"][
            "longitude"]
        altitude = shared_storage["grstns"][ground_id]["location"]["altitude"]
        if orekit_utils.check_iot_in_range(
                self_orbit_propagator, latitude, longitude, altitude,
                orekit_utils.absolute_time_converter_utc_string(
                    shared_storage["time"])):
            shared_storage["grstn_phonebook"][ground_id] = True
        else:
            shared_storage["grstn_phonebook"][ground_id] = False
    # Sending updated phonebook
    grstn_phonebook_message = nats_handler.create_message(
        shared_storage["grstn_phonebook"], MessageSchemas.PHONEBOOK_MESSAGE)
    await nats_handler.send_message("internal.grnst_phonebook",
                                    grstn_phonebook_message)
Exemplo n.º 18
0
    async def test_simulation_timepulse_propagate(self):
        """
        Test the simulation_timepulse_propagate() callback
        """
        # Creating variables that will be used as arguments for the callback
        logger = FakeLogger()
        loop = asyncio.get_running_loop()
        nats = FakeNatsHandler("cubesat_1",
                               "4222",
                               loop=loop,
                               user="******",
                               password="******")
        await nats.connect()

        # opening a file that contains a sample shared storage
        f = open("test_orbits_config.json")
        shared_storage = json.load(f)

        # Testing the callback across mulitple timesteps
        for i in range(10, 59):
            # creating sample data
            data = {
                "sender_ID": "cubesat_2",
                "time_sent": "2021-12-05T00:" + str(i) + ":00.000",
                "data": {
                    "time": "2021-12-05T00:" + str(i) + ":00.000"
                }
            }

            orbit_1 = shared_storage["swarm"]["cubesat_1"]["orbit"]
            orbit_2 = shared_storage["swarm"]["cubesat_2"]["orbit"]

            attitude_provider_1 = {
                "type":
                "moving_body_tracking",
                "parameters":
                shared_storage["swarm"][shared_storage["swarm"]["cubesat_1"]
                                        ["orbit"]["attitude"]]["orbit"]
            }
            attitude_provider_2 = {
                "type":
                "moving_body_tracking",
                "parameters":
                shared_storage["swarm"][shared_storage["swarm"]["cubesat_2"]
                                        ["orbit"]["attitude"]]["orbit"]
            }

            message = Message.decode_json(data,
                                          MessageSchemas.TIMESTEP_MESSAGE)
            await orbit_service.simulation_timepulse_propagate(
                message, nats, shared_storage, logger)

            time = absolute_time_converter_utc_string(data["data"]["time"])

            # Creating propagators and attitude provider from orbit configuration of satellites
            propagator_1 = orekit_utils.analytical_propagator(orbit_1)
            propagator_2 = orekit_utils.analytical_propagator(orbit_2)
            attitude_provider_1 = orekit_utils.attitude_provider_constructor(
                attitude_provider_1["type"], attitude_provider_1["parameters"])
            attitude_provider_2 = orekit_utils.attitude_provider_constructor(
                attitude_provider_2["type"], attitude_provider_2["parameters"])

            # Setting attitude and propagating the orbit
            propagator_1.setAttitudeProvider(attitude_provider_1)
            propagator_2.setAttitudeProvider(attitude_provider_2)
            state_1 = propagator_1.propagate(time)
            state_2 = propagator_2.propagate(time)

            # Updating param
            cubesat_1_param = orekit_utils.get_keplerian_parameters(state_1)
            cubesat_1_param.update({"attitude": "cubesat_2"})
            cubesat_1_param.update({"frame": "EME"})
            cubesat_2_param = orekit_utils.get_keplerian_parameters(state_2)
            cubesat_2_param.update({"attitude": "cubesat_1"})
            cubesat_2_param.update({"frame": "EME"})

            # Checking to see if simulation_timestep_propagate updated params correctly
            self.assertTrue(shared_storage["swarm"]["cubesat_1"]["orbit"] ==
                            cubesat_1_param)
            self.assertTrue(shared_storage["swarm"]["cubesat_2"]["orbit"] ==
                            cubesat_2_param)
            self.assertTrue(shared_storage["swarm"]["cubesat_1"]["orbit"]
                            ["attitude"] == "cubesat_2")
            self.assertTrue(shared_storage["swarm"]["cubesat_2"]["orbit"]
                            ["attitude"] == "cubesat_1")
            print(shared_storage["swarm"]["cubesat_1"]["target_in_view"])
            print(shared_storage["swarm"]["cubesat_2"]["target_in_view"])
            # Making sure that phonebook gets updated properly
            if i <= 48:
                self.assertTrue(shared_storage["sat_phonebook"]["cubesat_2"])
                self.assertTrue(
                    shared_storage["swarm"]["cubesat_2"]["target_in_view"])
            else:
                self.assertFalse(shared_storage["sat_phonebook"]["cubesat_2"])
                self.assertFalse(
                    shared_storage["swarm"]["cubesat_2"]["target_in_view"])