def test_generate_opm_with_defaults(self): o = OpmParams({'epoch': 'foo', 'state_vector': [1, 2, 3, 4, 5, 6]}) expected_opm = """CCSDS_OPM_VERS = 2.0 ORIGINATOR = ADAM_User COMMENT Cartesian coordinate system OBJECT_NAME = dummy OBJECT_ID = 001 CENTER_NAME = SUN REF_FRAME = ITRF-97 TIME_SYSTEM = UTC EPOCH = foo X = 1 Y = 2 Z = 3 X_DOT = 4 Y_DOT = 5 Z_DOT = 6 MASS = 1000 SOLAR_RAD_AREA = 20 SOLAR_RAD_COEFF = 1 DRAG_AREA = 20 DRAG_COEFF = 2.2""" # Remove the CREATION_DATE stamp since that varies. opm = "\n".join([ line for line in o.generate_opm().splitlines() if not line.startswith('CREATION_DATE') ]) self.maxDiff = None # Otherwise if the next line fails, we can't see the diff self.assertEqual(expected_opm, opm)
def test_generate_opm_with_defaults(self): o = OpmParams({'epoch': 'foo', 'state_vector': [1, 2, 3, 4, 5, 6]}) expected_opm = """CCSDS_OPM_VERS = 2.0 ORIGINATOR = ADAM_User COMMENT Cartesian coordinate system OBJECT_NAME = dummy OBJECT_ID = 001 CENTER_NAME = SUN REF_FRAME = ICRF TIME_SYSTEM = UTC EPOCH = foo X = 1 Y = 2 Z = 3 X_DOT = 4 Y_DOT = 5 Z_DOT = 6 MASS = 1000.0 SOLAR_RAD_AREA = 20.0 SOLAR_RAD_COEFF = 1.0 DRAG_AREA = 20.0 DRAG_COEFF = 2.2""" opm = OpmParamsTest.remove_non_static_fields(o.generate_opm()) self.maxDiff = None # Otherwise if the next line fails, we can't see the diff self.assertEqual(expected_opm, opm)
def make_cartesian_and_keplerian_batches(self, start_time_str, end_time_str): keplerian_elements = { 'semi_major_axis_km': 3.1307289138037175E8, 'eccentricity': 0.5355029800000188, 'inclination_deg': 23.439676743246295, 'ra_of_asc_node_deg': 359.9942693176405, 'arg_of_pericenter_deg': 328.5584374618295, 'true_anomaly_deg': -127.01778914927144, 'gm': 1.327124400419394E11 } cartesian_state_vector = [ -3.0653634150102222e8, -1.1097955684640282e8, -4.8129706422527283e7, # x, y, z 15.7598552764090590, -10.5875673291958420, -4.5896734328869746 # dx, dy, dZ ] propagation_params = PropagationParams({ 'start_time': start_time_str, 'end_time': end_time_str, 'project_uuid': self.working_project.get_uuid(), 'description': 'Created by test at ' + start_time_str }) opm_params_templ = { 'epoch': start_time_str, # state_vector or keplerian_elements will be set later. 'mass': 500.5, 'solar_rad_area': 25.2, 'solar_rad_coeff': 1.2, 'drag_area': 33.3, 'drag_coeff': 2.5 } cartesian_opm_params = opm_params_templ.copy() cartesian_opm_params['state_vector'] = cartesian_state_vector keplerian_opm_params = opm_params_templ.copy() keplerian_opm_params['keplerian_elements'] = keplerian_elements cartesian = Batch(propagation_params, OpmParams(cartesian_opm_params)) keplerian = Batch(propagation_params, OpmParams(keplerian_opm_params)) return cartesian, keplerian
def _new_batch_propagation(self): now = datetime.datetime.utcnow() later = now + datetime.timedelta(10 * 365) propagation_params = PropagationParams({ 'start_time': now.isoformat() + 'Z', 'end_time': later.isoformat() + 'Z', 'step_size': 60 * 60, # 1 hour. 'description': 'Created by test at ' + str(now) + 'Z' }) state_vec = [ 130347560.13690618, -74407287.6018632, -35247598.541470632, 23.935241263310683, 27.146279819258538, 10.346605942591514 ] opm_params = OpmParams({ 'epoch': now.isoformat() + 'Z', 'state_vector': state_vec, 'mass': 500.5, 'solar_rad_area': 25.2, 'solar_rad_coeff': 1.2, 'drag_area': 33.3, 'drag_coeff': 2.5, 'originator': 'Test', 'object_name': 'TestObj', 'object_id': 'TestObjId', }) return BatchPropagation(propagation_params, opm_params)
def new_targeted_propagation(self, initial_maneuver): start = '2013-05-25T00:00:02.000000Z' end = '2018-04-25T03:06:14.200000Z' propagation_params = PropagationParams({ 'start_time': start, 'end_time': end, 'project_uuid': self.working_project.get_uuid(), 'description': 'Created by test at ' + start }) state_vec = [ -1.4914794358536252e+8, 1.0582106861692128e+8, 6.0492834101479955e+7, -11.2528789273597756, -22.3258231726462242, -9.7271222877710155 ] opm_params = OpmParams({ 'epoch': start, 'state_vector': state_vec, 'initial_maneuver': initial_maneuver, }) return TargetedPropagation( propagation_params, opm_params, TargetingParams({ 'target_distance_from_earth': 1.0e4, 'tolerance': 1.0 }))
def make_batch(self, state_vec, start_time, end_time): start_time_str = start_time.isoformat() + 'Z' end_time_str = end_time.isoformat() + 'Z' propagation_params = PropagationParams({ 'start_time': start_time_str, 'end_time': end_time_str, 'step_size': 0, 'project_uuid': self.working_project.get_uuid(), 'description': 'Created by test at ' + start_time_str }) opm_params = OpmParams({ 'epoch': start_time_str, 'state_vector': state_vec, 'mass': 500.5, 'solar_rad_area': 25.2, 'solar_rad_coeff': 1.2, 'drag_area': 33.3, 'drag_coeff': 2.5, 'originator': 'Test', 'object_name': 'TestObj', 'object_id': 'TestObjId', }) return Batch(propagation_params, opm_params)
def test_access(self): projects_module = self.service.get_projects_module() permissions_module = self.service.get_permissions_module() groups_module = self.service.get_groups_module() # Only prod has a public project. projects = projects_module.get_projects() if self.config.get_environment() == "prod": self.assertEqual(1, len(projects)) self.assertEqual("public", projects[0].get_name()) else: self.assertEqual(0, len(projects)) print("Skipping check for public objects.") # Can't add a project to public project. public_project = "00000000-0000-0000-0000-000000000001" with (self.assertRaises(RuntimeError)): projects_module.new_project(public_project, "", "") # Can't run a batch in the public project. batches_module = self.service.get_batches_module() dummy_propagation_params = PropagationParams({ 'start_time': 'AAA', 'end_time': 'BBB', 'project_uuid': 'CCC' }) dummy_opm_params = OpmParams({ 'epoch': 'DDD', 'state_vector': [1, 2, 3, 4, 5, 6] }) with (self.assertRaises(RuntimeError)): batches_module.new_batch(dummy_propagation_params, dummy_opm_params) # Anon should have no permissions. permissions = permissions_module.get_my_permissions() self.assertEqual(1, len(permissions)) self.assertEqual(0, len(permissions[""])) # And anon is in no groups. groups = groups_module.get_my_memberships() self.assertEqual(0, len(groups)) # Therefore anon can grant no permissions. with (self.assertRaises(RuntimeError)): permissions_module.grant_user_permission( "*****@*****.**", Permission("READ", "PROJECT", public_project)) # And can add/modify no groups. with (self.assertRaises(RuntimeError)): groups_module.new_group("", "") all_group = "00000000-0000-0000-0000-000000000001" with (self.assertRaises(RuntimeError)): groups_module.add_user_to_group("*****@*****.**", all_group) # Not even allowed to see the members of the magic all group. with (self.assertRaises(RuntimeError)): groups_module.get_group_members(all_group)
def test_submit_batch(self, service): keplerian_elements = { 'semi_major_axis_km': 448793612, 'eccentricity': 0.1, 'inclination_deg': 90, 'ra_of_asc_node_deg': 91, 'arg_of_pericenter_deg': 92, 'true_anomaly_deg': 93, 'gm': 132712440041.9394 } keplerian_sigma = { 'semi_major_axis': 100, 'eccentricity': 0.001, 'inclination': 1, 'ra_of_asc_node': 2, 'arg_of_pericenter': 3, 'true_anomaly': 4, } # state_vec = [130347560.13690618, # -74407287.6018632, # -35247598.541470632, # 23.935241263310683, # 27.146279819258538, # 10.346605942591514] # sigma_vec = {'x': 1000, # 'y': 1001, # 'z': 1002, # 'x_dot': 10, # 'y_dot': 11, # 'z_dot': 12} draws = 5 propagation_params = PropagationParams({ 'start_time': '2017-10-04T00:00:00Z', # propagation start time in ISO format 'end_time': '2017-10-11T00:00:00Z', # propagation end time in ISO format 'project_uuid': service.workspace, 'keplerianSigma': keplerian_sigma, 'monteCarloDraws': draws, 'propagationType': 'MONTE_CARLO', 'description': 'Integration Test Run', 'stopOnImpact': True, 'step_size': 86400, 'stopOnCloseApproach': False, 'stopOnImpactDistanceMeters': 500000, 'closeApproachRadiusFromTargetMeters': 7000000000 }) opm_params = OpmParams({ 'epoch': '2017-10-04T00:00:00Z', 'keplerian_elements': keplerian_elements, }) response = service.processing_service.execute_batch_propagation( service.workspace, propagation_params, opm_params) assert response.job_id() is not None
def new_batch_propagation(self): now = datetime.datetime.utcnow() later = now + datetime.timedelta(10 * 365) propagation_params = PropagationParams({ 'start_time': now.isoformat() + 'Z', 'end_time': later.isoformat() + 'Z', 'step_size': 60 * 60, # 1 hour. 'description': 'Created by test at ' + str(now) + 'Z' }) state_vec = [ 130347560.13690618, -74407287.6018632, -35247598.541470632, 23.935241263310683, 27.146279819258538, 10.346605942591514 ] opm_params = OpmParams({ 'epoch': now.isoformat() + 'Z', 'state_vector': state_vec, # Comment out state_vector and uncomment this to try with keplerian elements instead. # 'keplerian_elements': { # 'semi_major_axis_km': 3.1307289138037175E8, # 'eccentricity': 0.5355029800000188, # 'inclination_deg': 23.439676743246295, # 'ra_of_asc_node_deg': 359.9942693176405, # 'arg_of_pericenter_deg': 328.5584374618295, # 'true_anomaly_deg': -127.01778914927144, # 'gm': 1.327124400419394E11 # }, 'mass': 500.5, 'solar_rad_area': 25.2, 'solar_rad_coeff': 1.2, 'drag_area': 33.3, 'drag_coeff': 2.5, 'originator': 'Test', 'object_name': 'TestObj', 'object_id': 'TestObjId', # Uncomment this to try a hypercube propagation. # Lower triangular covariance matrix (21 elements in a list) # 'covariance': [ # 3.331349476038534e-04, # 4.618927349220216e-04, 6.782421679971363e-04, # -3.070007847730449e-04, -4.221234189514228e-04, 3.231931992380369e-04, # -3.349365033922630e-07, -4.686084221046758e-07, 2.484949578400095e-07, 4.296022805587290e-10, # NOQA (we want to keep the visual triangle) # -2.211832501084875e-07, -2.864186892102733e-07, 1.798098699846038e-07, 2.608899201686016e-10, 1.767514756338532e-10, # NOQA # -3.041346050686871e-07, -4.989496988610662e-07, 3.540310904497689e-07, 1.869263192954590e-10, 1.008862586240695e-10, 6.224444338635500e-10], # NOQA # 'perturbation': 3, # 'hypercube': 'FACES', }) return BatchPropagation(propagation_params, opm_params)
def test_sun_ememe(self, service, working_project): start_time_str = "2000-01-01T11:58:55.816Z" end_time_str = "2009-07-21T21:55:08.813Z" sun_ememe_state_vec = [ -306536346.18024945, -120966638.54521248, -12981.069369263947, 15.759854830195243, -11.539570959741736, 0.0005481049628786039 ] propagation_params = PropagationParams({ 'start_time': start_time_str, 'end_time': end_time_str, 'step_size': 86400, 'project_uuid': working_project.get_uuid(), 'description': 'Created by test at ' + start_time_str }) opm_params = OpmParams({ 'epoch': start_time_str, 'state_vector': sun_ememe_state_vec, 'center_name': 'SUN', 'ref_frame': 'EMEME2000', }) batch = Batch(propagation_params, opm_params) runner = BatchRunManager(service.get_batches_module(), [batch]) runner.run() end_state = batch.get_results().get_end_state_vector() # The output state is expected to be in ICRF. expected_end_state = [ 73978163.61069362, -121822760.05571477, -52811158.83249758, 31.71000343989318, 29.9657246374751, .6754531613947713 ] # These values are in EMEME. The resulting ephemeris is not expected to match these values. # expected_end_state = [73978158.47632701, -132777272.5255892, 5015.073123970032, # 31.710003506237434, 27.761693311026138, -11.299967713192564] difference = np.subtract(expected_end_state, end_state) print("Difference is %s" % difference) print("End state: %s" % end_state) npt.assert_allclose(difference[0:3], [0, 0, 0], rtol=0, atol=.02) npt.assert_allclose(difference[3:6], [0, 0, 0], rtol=0, atol=.00002) # The returned ephemeris will be in Sun-centered ICRF, not EMEME. My best guess is that # the ephemeris file doesn't support all reference frames, so if it encounters one that # isn't supported, it'll choose a similar one. ephem = batch.get_results().get_parts()[-1].get_ephemeris() assert "ICRF" in ephem assert "EMEME" not in ephem
def propagate_states(state_vectors, epoch_time, end_time): """Propagate states from one time to another Assume state epoch is the same as integration start time Args: sate_vectors (list of lists) - list of lists with 6 elements [rx, ry, rz, vx, vy, vz] [km, km/s] epoch_time (datetime.datetime) - epoch of state (UTC datetime) end_time (datetime.datetime) - time at which to end the simulation (UTC datetime) Returns: end_state_vectors (list of lists) - states at end of integration [rx, ry, rz, vx, vy, vz] [km, km/s] """ # Convert times to strings epoch_time_str = batch_time_string_from_datetime(epoch_time) start_time_str = epoch_time_str end_time_str = batch_time_string_from_datetime(end_time) print("Propagating %i states to propagate from %s to %s" % (len(state_vectors), start_time_str, end_time_str)) url = "https://pro-equinox-162418.appspot.com/_ah/api/adam/v1" rest = RestRequests(url) batches_module = Batches(rest) # Create batches from statevectors batches = [] propagation_params = PropagationParams({ 'start_time': start_time_str, 'end_time': end_time_str, 'project_uuid': 'ffffffff-ffff-ffff-ffff-ffffffffffff' }) for state_vector in state_vectors: opm_params = OpmParams({ 'epoch': start_time_str, 'state_vector': state_vector }) batches.append(Batch(propagation_params, opm_params)) # submit batches and wait till they finish running BatchRunManager(batches_module, batches).run() # Get final states end_state_vectors = [] for batch in batches: end_state_vectors.append(batch.get_results().get_end_state_vector()) return end_state_vectors
def test_config_in_use_pins_project(self): # Config management isn't very common, doesn't merit direct addition to service. configs = PropagatorConfigs(self.service.rest) projects = self.service.get_projects_module() project = self.service.new_working_project() project1 = projects.new_project(project.get_uuid(), "", "") self.assertIsNotNone(project1) project2 = projects.new_project(project.get_uuid(), "", "") self.assertIsNotNone(project2) print("Added child projects to working project: " + "[" + project1.get_uuid() + ", " + project2.get_uuid() + "]") config = configs.new_config({ 'project': project1.get_uuid(), 'description': 'test config' }) self.assertEqual(project1.get_uuid(), config.get_project()) batch = Batch( PropagationParams({ 'start_time': '2017-10-04T00:00:00Z', 'end_time': '2017-10-05T00:00:00Z', 'project_uuid': project2.get_uuid(), 'propagator_uuid': config.get_uuid() }), OpmParams({ 'epoch': '2017-10-04T00:00:00Z', 'state_vector': [ 130347560.13690618, -74407287.6018632, -35247598.541470632, 23.935241263310683, 27.146279819258538, 10.346605942591514 ] })) BatchRunManager(self.service.get_batches_module(), [batch]).run() # Attempt to delete the project with the config in it. It should refuse because the # config is still in use by the batch. with self.assertRaises(RuntimeError): projects.delete_project(project1.get_uuid()) # Then delete the batch. After that, the project with the config in it should # delete no problem. self.service.batches.delete_batch(batch.get_uuid()) projects.delete_project(project1.get_uuid()) # Clean up the batch holder project. projects.delete_project(project2.get_uuid())
def new_hypercube_batch(self, hypercube): now = datetime.datetime.utcnow() later = now + datetime.timedelta(365 * 10) # 10 years propagation_params = PropagationParams({ 'start_time': now.isoformat() + 'Z', 'end_time': later.isoformat() + 'Z', 'step_size': 0, 'project_uuid': self.working_project.get_uuid(), 'description': 'Created by test at ' + str(now) + 'Z' }) state_vec = [130347560.13690618, -74407287.6018632, -35247598.541470632, 23.935241263310683, 27.146279819258538, 10.346605942591514] opm_params = OpmParams({ 'epoch': now.isoformat() + 'Z', 'state_vector': state_vec, 'mass': 500.5, 'solar_rad_area': 25.2, 'solar_rad_coeff': 1.2, 'drag_area': 33.3, 'drag_coeff': 2.5, 'originator': 'Test', 'object_name': 'TestObj', 'object_id': 'TestObjId', # Lower triangular covariance matrix (21 elements in a list) 'covariance': [ 3.331349476038534e-04, 4.618927349220216e-04, 6.782421679971363e-04, -3.070007847730449e-04, -4.221234189514228e-04, 3.231931992380369e-04, -3.349365033922630e-07, -4.686084221046758e-07, 2.484949578400095e-07, 4.296022805587290e-10, # NOQA (we want to keep the visual triangle) -2.211832501084875e-07, -2.864186892102733e-07, 1.798098699846038e-07, 2.608899201686016e-10, 1.767514756338532e-10, # NOQA -3.041346050686871e-07, -4.989496988610662e-07, 3.540310904497689e-07, 1.869263192954590e-10, 1.008862586240695e-10, 6.224444338635500e-10], # NOQA 'perturbation': 3, 'hypercube': hypercube, }) return Batch(propagation_params, opm_params)
def test_icrf(self, service, working_project): start_time_str = "2000-01-01T11:58:55.816Z" end_time_str = "2009-07-21T21:55:08.813Z" sun_icrf_state_vec = [ -306536341.5010222, -110979556.84640282, -48129706.42252728, 15.75985527640906, -10.587567329195842, -4.589673432886975 ] propagation_params = PropagationParams({ 'start_time': start_time_str, 'end_time': end_time_str, 'step_size': 86400, 'project_uuid': working_project.get_uuid(), 'description': 'Created by test at ' + start_time_str }) opm_params = OpmParams({ 'epoch': start_time_str, 'state_vector': sun_icrf_state_vec, 'center_name': 'SUN', 'ref_frame': 'ICRF', }) batch = Batch(propagation_params, opm_params) runner = BatchRunManager(service.get_batches_module(), [batch]) runner.run() end_state = batch.get_results().get_end_state_vector() expected_end_state = [ 73978163.61069362, -121822760.05571477, -52811158.83249758, 31.71000343989318, 29.9657246374751, .6754531613947713 ] difference = np.subtract(expected_end_state, end_state) print("Difference is %s" % difference) print("End state: %s" % end_state) npt.assert_allclose(difference[0:3], [0, 0, 0], rtol=0, atol=.02) npt.assert_allclose(difference[3:6], [0, 0, 0], rtol=0, atol=.00002) ephem = batch.get_results().get_parts()[-1].get_ephemeris() assert "ICRF" in ephem
def new_dummy_batch(self, days_to_propagate): if (days_to_propagate > 36500): print( "Server has trouble handling propagation durations longer than 100 years. " + "Try something smaller.") return now = datetime.datetime.utcnow() later = now + datetime.timedelta(days_to_propagate) propagation_params = PropagationParams({ 'start_time': now.isoformat() + 'Z', 'end_time': later.isoformat() + 'Z', 'step_size': 60 * 60, # 1 hour. 'project_uuid': self.working_project.get_uuid(), 'description': 'Created by test at ' + str(now) + 'Z' }) state_vec = [ 130347560.13690618, -74407287.6018632, -35247598.541470632, 23.935241263310683, 27.146279819258538, 10.346605942591514 ] opm_params = OpmParams({ 'epoch': now.isoformat() + 'Z', 'state_vector': state_vec, 'mass': 500.5, 'solar_rad_area': 25.2, 'solar_rad_coeff': 1.2, 'drag_area': 33.3, 'drag_coeff': 2.5, 'originator': 'Test', 'object_name': 'TestObj', 'object_id': 'TestObjId', }) return Batch(propagation_params, opm_params)
def test_generate_opm(self): o = OpmParams({ 'epoch': 'foo', 'state_vector': [1, 2, 3, 4, 5, 6], 'keplerian_elements': { 'semi_major_axis_km': 1, 'eccentricity': 2, 'inclination_deg': 3, 'ra_of_asc_node_deg': 4, 'arg_of_pericenter_deg': 5, 'true_anomaly_deg': 6, 'gm': 7 }, 'originator': 'a', 'object_name': 'b', 'object_id': 'c', 'center_name': 'EARTH', 'ref_frame': 'EMEME2000', 'mass': 1, 'solar_rad_area': 2, 'solar_rad_coeff': 3, 'drag_area': 4, 'drag_coeff': 5, 'covariance': [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 ], 'perturbation': 7, 'hypercube': 'CORNERS', }) expected_opm = """CCSDS_OPM_VERS = 2.0 ORIGINATOR = a COMMENT Cartesian coordinate system OBJECT_NAME = b OBJECT_ID = c CENTER_NAME = EARTH REF_FRAME = EMEME2000 TIME_SYSTEM = UTC EPOCH = foo X = 1 Y = 2 Z = 3 X_DOT = 4 Y_DOT = 5 Z_DOT = 6 SEMI_MAJOR_AXIS = 1 ECCENTRICITY = 2 INCLINATION = 3 RA_OF_ASC_NODE = 4 ARG_OF_PERICENTER = 5 TRUE_ANOMALY = 6 GM = 7 MASS = 1 SOLAR_RAD_AREA = 2 SOLAR_RAD_COEFF = 3 DRAG_AREA = 4 DRAG_COEFF = 5 CX_X = 0 CY_X = 1 CY_Y = 2 CZ_X = 3 CZ_Y = 4 CZ_Z = 5 CX_DOT_X = 6 CX_DOT_Y = 7 CX_DOT_Z = 8 CX_DOT_X_DOT = 9 CY_DOT_X = 10 CY_DOT_Y = 11 CY_DOT_Z = 12 CY_DOT_X_DOT = 13 CY_DOT_Y_DOT = 14 CZ_DOT_X = 15 CZ_DOT_Y = 16 CZ_DOT_Z = 17 CZ_DOT_X_DOT = 18 CZ_DOT_Y_DOT = 19 CZ_DOT_Z_DOT = 20 USER_DEFINED_ADAM_INITIAL_PERTURBATION = 7 [sigma] USER_DEFINED_ADAM_HYPERCUBE = CORNERS""" # Remove the CREATION_DATE stamp since that varies. opm = "\n".join([ line for line in o.generate_opm().splitlines() if not line.startswith('CREATION_DATE') ]) self.maxDiff = None # Otherwise if the next line fails, we can't see the diff self.assertEqual(expected_opm, opm)
def test_generate_opm(self): o = OpmParams({ 'epoch': 'foo', 'state_vector': [1, 2, 3, 4, 5, 6], 'originator': 'a', 'object_name': 'b', 'object_id': 'c', 'mass': 1, 'solar_rad_area': 2, 'solar_rad_coeff': 3, 'drag_area': 4, 'drag_coeff': 5, 'covariance': [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20 ], 'perturbation': 7, 'hypercube': 'CORNERS', }) expected_opm = """CCSDS_OPM_VERS = 2.0 ORIGINATOR = a COMMENT Cartesian coordinate system OBJECT_NAME = b OBJECT_ID = c CENTER_NAME = SUN REF_FRAME = ITRF-97 TIME_SYSTEM = UTC EPOCH = foo X = 1 Y = 2 Z = 3 X_DOT = 4 Y_DOT = 5 Z_DOT = 6 MASS = 1 SOLAR_RAD_AREA = 2 SOLAR_RAD_COEFF = 3 DRAG_AREA = 4 DRAG_COEFF = 5 CX_X = 0 CY_X = 1 CY_Y = 2 CZ_X = 3 CZ_Y = 4 CZ_Z = 5 CX_DOT_X = 6 CX_DOT_Y = 7 CX_DOT_Z = 8 CX_DOT_X_DOT = 9 CY_DOT_X = 10 CY_DOT_Y = 11 CY_DOT_Z = 12 CY_DOT_X_DOT = 13 CY_DOT_Y_DOT = 14 CZ_DOT_X = 15 CZ_DOT_Y = 16 CZ_DOT_Z = 17 CZ_DOT_X_DOT = 18 CZ_DOT_Y_DOT = 19 CZ_DOT_Z_DOT = 20 USER_DEFINED_ADAM_INITIAL_PERTURBATION = 7 [sigma] USER_DEFINED_ADAM_HYPERCUBE = CORNERS""" # Remove the CREATION_DATE stamp since that varies. opm = "\n".join([ line for line in o.generate_opm().splitlines() if not line.startswith('CREATION_DATE') ]) self.maxDiff = None # Otherwise if the next line fails, we can't see the diff self.assertEqual(expected_opm, opm)
def test_invalid_keys(self): with self.assertRaises(KeyError): OpmParams({'unrecognized': 0})
def test_required_keys(self): with self.assertRaises(KeyError): OpmParams({'epoch': 'foo'}) with self.assertRaises(KeyError): OpmParams({'state_vector': []})
def test_access_state_vector(self): o = OpmParams({'epoch': 'foo', 'state_vector': [1, 2, 3, 4, 5, 6]}) self.assertEqual([1, 2, 3, 4, 5, 6], o.get_state_vector()) o.set_state_vector([6, 5, 4, 3, 2, 1]) self.assertEqual([6, 5, 4, 3, 2, 1], o.get_state_vector())
def test_required_keys(self): with self.assertRaises(KeyError): OpmParams({'epoch': 'foo'}) with self.assertRaises(KeyError): OpmParams({'state_vector': []}) with self.assertRaises(KeyError): OpmParams({ 'keplerian_elements': { 'semi_major_axis_km': 1, 'eccentricity': 2, 'inclination_deg': 3, 'ra_of_asc_node_deg': 4, 'arg_of_pericenter_deg': 5, 'true_anomaly_deg': 6, 'gm': 7 } }) with self.assertRaises(KeyError): OpmParams({ 'epoch': 'foo', 'keplerian_elements': { 'semi_major_axis_km': 1, 'eccentricity': 2, 'inclination_deg': 3, 'ra_of_asc_node_deg': 4, 'arg_of_pericenter_deg': 5, 'true_anomaly_deg': 6, # Missing gm. } }) with self.assertRaises(KeyError): OpmParams({ 'epoch': 'foo', 'keplerian_elements': { 'semi_major_axis_km': 1, 'eccentricity': 2, 'inclination_deg': 3, 'ra_of_asc_node_deg': 4, 'arg_of_pericenter_deg': 5, 'true_anomaly_deg': 6, 'gm': 7, 'extra what is this': 8 } }) # No KeyError with no state vector. OpmParams({ 'epoch': 'foo', 'keplerian_elements': { 'semi_major_axis_km': 1, 'eccentricity': 2, 'inclination_deg': 3, 'ra_of_asc_node_deg': 4, 'arg_of_pericenter_deg': 5, 'true_anomaly_deg': 6, 'gm': 7 } })
class BatchesTest(unittest.TestCase): """Unit tests for batches module """ dummy_propagation_params = PropagationParams({ 'start_time': 'AAA', 'end_time': 'BBB', 'project_uuid': 'CCC' }) dummy_opm_params = OpmParams({ 'epoch': 'DDD', 'state_vector': [1, 2, 3, 4, 5, 6] }) def _check_input(self, data_dict): """Check input data Checks input data by asserting the following: - start time = 'AAA' - end time = 'BBB' - step size = 86400 (default) - opm string in data dictionary is not None - originator = 'ADAM_User' - object name = 'dummy' - object ID = '001' - epoch and state vector are 'CCC' and [1, 2, 3, 4, 5, 6], respectively - object mass = 1000 (default) - object solar radiation area = 20 (default) - object solar radiation coefficient = 1 (default) - object drag area = 20 (default) - object drag coefficient = 2.2 (default) - propagator ID is default (none specified) Args: data_dict (dict) - input data for POST Returns: True """ self.assertEqual(data_dict['start_time'], self.dummy_propagation_params.get_start_time()) self.assertEqual(data_dict['end_time'], self.dummy_propagation_params.get_end_time()) self.assertEqual(data_dict['project'], self.dummy_propagation_params.get_project_uuid()) self.assertEqual(data_dict['step_duration_sec'], 86400) self.assertEqual(data_dict['propagator_uuid'], "00000000-0000-0000-0000-000000000001") opm = data_dict['opm_string'] self.assertIsNotNone(opm) self.assertIn('ORIGINATOR = ADAM_User', opm) self.assertIn('OBJECT_NAME = dummy', opm) self.assertIn('OBJECT_ID = 001', opm) self.assertIn('EPOCH = DDD', opm) self.assertIn('X = 1', opm) self.assertIn('Y = 2', opm) self.assertIn('Z = 3', opm) self.assertIn('X_DOT = 4', opm) self.assertIn('Y_DOT = 5', opm) self.assertIn('Z_DOT = 6', opm) self.assertIn('MASS = 1000', opm) self.assertIn('SOLAR_RAD_AREA = 20', opm) self.assertIn('SOLAR_RAD_COEFF = 1', opm) self.assertIn('DRAG_AREA = 20', opm) self.assertIn('DRAG_COEFF = 2.2', opm) return True def _check_inputs(self, inputs): for data_dict in inputs['requests']: self._check_input(data_dict) return True def test_new_batch(self): rest = _RestProxyForTest() batches = Batches(rest) # A successful run. rest.expect_post("/batch", self._check_input, 200, { 'calc_state': 'PENDING', 'uuid': '1' }) state = batches.new_batch(self.dummy_propagation_params, self.dummy_opm_params) self.assertEqual('1', state.get_uuid()) self.assertEqual('PENDING', state.get_calc_state()) # Unsuccessful run. rest.expect_post("/batch", self._check_input, 400, { 'calc_state': 'PENDING', 'uuid': '1' }) with self.assertRaises(RuntimeError): batches.new_batch(self.dummy_propagation_params, self.dummy_opm_params) def test_new_batches(self): rest = _RestProxyForTest() batches = Batches(rest) # Successful run. rest.expect_post( "/batches", self._check_inputs, 200, { 'requests': [{ 'calc_state': 'PENDING', 'uuid': '1' }, { 'calc_state': 'RUNNING', 'uuid': '2' }] }) states = batches.new_batches( [[self.dummy_propagation_params, self.dummy_opm_params], [self.dummy_propagation_params, self.dummy_opm_params]]) self.assertEqual(2, len(states)) self.assertEqual('1', states[0].get_uuid()) self.assertEqual('PENDING', states[0].get_calc_state()) self.assertEqual('2', states[1].get_uuid()) self.assertEqual('RUNNING', states[1].get_calc_state()) # Unsuccessful run. rest.expect_post("/batches", self._check_inputs, 400, {}) with self.assertRaises(RuntimeError): batches.new_batches( [[self.dummy_propagation_params, self.dummy_opm_params], [self.dummy_propagation_params, self.dummy_opm_params]]) def test_delete_batch(self): rest = _RestProxyForTest() batches = Batches(rest) # Successful request. rest.expect_delete("/batch/aaa", 204) batches.delete_batch('aaa') # 200 isn't a valid return value for delete calls right now rest.expect_delete("/batch/aaa", 200) with self.assertRaises(RuntimeError): batches.delete_batch('aaa') def test_get_summary(self): rest = _RestProxyForTest() batches = Batches(rest) # Successful request. rest.expect_get('/batch/aaa', 200, { 'uuid': 'aaa', 'calc_state': 'RUNNING' }) summary = batches.get_summary('aaa') self.assertEqual('aaa', summary.get_uuid()) self.assertEqual('RUNNING', summary.get_calc_state()) # Successfully found missing. rest.expect_get('/batch/aaa', 404, 'Not JSON wat') self.assertIsNone(batches.get_summary('aaa')) # Unsuccessful request. rest.expect_get('/batch/aaa', 503, 'Also not JSON wat') with self.assertRaises(RuntimeError): batches.get_summary('aaa') def test_get_summaries(self): rest = _RestProxyForTest() batches = Batches(rest) # Successful request. rest.expect_get( '/batch?project_uuid=' + self.dummy_propagation_params.get_project_uuid(), 200, { 'items': [{ 'uuid': 'aaa', 'calc_state': 'RUNNING' }, { 'uuid': 'bbb', 'calc_state': 'COMPLETED' }, { 'uuid': 'ccc', 'calc_state': 'FAILED' }] }) summaries = batches.get_summaries( self.dummy_propagation_params.get_project_uuid()) self.assertEqual(3, len(summaries)) self.assertEqual('aaa', summaries['aaa'].get_uuid()) self.assertEqual('RUNNING', summaries['aaa'].get_calc_state()) self.assertEqual('bbb', summaries['bbb'].get_uuid()) self.assertEqual('COMPLETED', summaries['bbb'].get_calc_state()) self.assertEqual('ccc', summaries['ccc'].get_uuid()) self.assertEqual('FAILED', summaries['ccc'].get_calc_state()) # Unsuccessful request. rest.expect_get( '/batch?project_uuid=' + self.dummy_propagation_params.get_project_uuid(), 403, {}) with self.assertRaises(RuntimeError): batches.get_summaries( self.dummy_propagation_params.get_project_uuid()) def test_get_propagation_results(self): rest = _RestProxyForTest() batches = Batches(rest) # Parts count not specified. No result retrieval is attempted. state = StateSummary({ 'uuid': 'aaa', 'calc_state': 'COMPLETED', }) self.assertIsNone(batches.get_propagation_results(state)) # Parts count is 0. No result retrieval is attempted. state = StateSummary({ 'uuid': 'aaa', 'calc_state': 'COMPLETED', 'parts_count': 0, }) self.assertIsNone(batches.get_propagation_results(state)) # Normal retrieval. state = StateSummary({ 'uuid': 'aaa', 'calc_state': 'COMPLETED', 'parts_count': 2, }) rest.expect_get('/batch/aaa/1', 200, { 'part_index': 'a', 'calc_state': 'RUNNING' }) rest.expect_get('/batch/aaa/2', 200, { 'part_index': 'z', 'calc_state': 'COMPLETED' }) results = batches.get_propagation_results(state) self.assertEqual(2, len(results.get_parts())) self.assertEqual('a', results.get_parts()[0].get_part_index()) self.assertEqual('z', results.get_parts()[1].get_part_index()) # Some parts could not be found. state = StateSummary({ 'uuid': 'aaa', 'calc_state': 'FAILED', 'parts_count': 3, }) rest.expect_get('/batch/aaa/1', 404, 'Not json') rest.expect_get('/batch/aaa/2', 200, { 'part_index': 'z', 'calc_state': 'COMPLETED' }) rest.expect_get('/batch/aaa/3', 404, 'Not json') results = batches.get_propagation_results(state) self.assertEqual(3, len(results.get_parts())) self.assertIsNone(results.get_parts()[0]) self.assertEqual('z', results.get_parts()[1].get_part_index()) self.assertIsNone(results.get_parts()[2]) # Complete failure. state = StateSummary({ 'uuid': 'aaa', 'calc_state': 'COMPLETED', 'parts_count': 2, }) rest.expect_get('/batch/aaa/1', 403, 'irrelevant') with self.assertRaises(RuntimeError): batches.get_propagation_results(state)
'project_uuid': config.get_workspace(), # 'step_size': 60 * 60, # step size (seconds) # 'propagator_uuid': '00000000-0000-0000-0000-000000000002', # force model # 'description': 'some description' # description of run }) opm_params = OpmParams({ 'epoch': '2017-10-04T00:00:00Z', 'state_vector': state_vec, # 'mass': 500.5, # object mass # 'solar_rad_area': 25.2, # object solar radiation area (m^2) # 'solar_rad_coeff': 1.2, # object solar radiation coefficient # 'drag_area': 33.3, # object drag area (m^2) # 'drag_coeff': 2.5, # object drag coefficient # 'covariance': covariance, # object covariance # 'perturbation': 3, # sigma perturbation on state vector # 'hypercube': 'FACES', # hypercube propagation type # 'originator': 'Robot', # originator of run # 'object_name': 'TestObj', # object name # 'object_id': 'test1234', # object ID }) batch = Batch(propagation_params, opm_params) print("Submitting OPM:") print(batch.get_opm_params().generate_opm()) # Submit and wait until batch run is ready batches_module = Batches(auth_rest) BatchRunManager(batches_module, [batch]).run()
def test_from_json(self): self.maxDiff = None json1 = { "header": { "originator": "Test", "creation_date": "2018-06-21 16:22:20.550672" }, "metadata": { "comments": ["Cartesian coordinate system"], "object_name": "TestObj", "object_id": "TestObjId", "center_name": "SUN", "ref_frame": "ICRF", "time_system": "UTC" }, "spacecraft": { "mass": 500.5, "solar_rad_area": 25.2, "solar_rad_coeff": 1.2, "drag_area": 33.3, "drag_coeff": 2.5 }, "ccsds_opm_vers": "2.0", "state_vector": { "epoch": "2018-06-21T16:22:20.550561Z", "x": 130347560.13690618, "y": -74407287.6018632, "z": -35247598.54147063, "x_dot": 23.935241263310683, "y_dot": 27.146279819258538, "z_dot": 10.346605942591514 } } expected_opm1 = """CCSDS_OPM_VERS = 2.0 CREATION_DATE = 2018-06-21 16:25:33.374936 ORIGINATOR = Test COMMENT Cartesian coordinate system OBJECT_NAME = TestObj OBJECT_ID = TestObjId CENTER_NAME = SUN REF_FRAME = ICRF TIME_SYSTEM = UTC EPOCH = 2018-06-21T16:22:20.550561Z X = 130347560.13690618 Y = -74407287.6018632 Z = -35247598.54147063 X_DOT = 23.935241263310683 Y_DOT = 27.146279819258538 Z_DOT = 10.346605942591514 MASS = 500.5 SOLAR_RAD_AREA = 25.2 SOLAR_RAD_COEFF = 1.2 DRAG_AREA = 33.3 DRAG_COEFF = 2.5""" expected_opm1 = OpmParamsTest.remove_non_static_fields(expected_opm1) opm_params1 = OpmParams.fromJsonResponse(json1) actual_opm1 = OpmParamsTest.remove_non_static_fields( opm_params1.generate_opm()) self.assertEqual(expected_opm1, actual_opm1) json2 = { "header": { "originator": "Test", "creation_date": "2018-06-21 17:43:20.984533" }, "metadata": { "comments": ["Cartesian coordinate system"], "object_name": "TestObj", "object_id": "TestObjId", "center_name": "SUN", "ref_frame": "ICRF", "time_system": "UTC" }, "spacecraft": { "mass": 500.5, "solar_rad_area": 25.2, "solar_rad_coeff": 1.2, "drag_area": 33.3, "drag_coeff": 2.5 }, "maneuvers": [{ "duration": 0.0, "man_epoch_ignition": "2018-06-21T17:43:20.984304Z", "delta_mass": 0.0, "man_ref_frame": "TNW", "man_dv_1": 1.0, "man_dv_2": 2.0, "man_dv_3": 3.0, }], "covariance": { "cx_x": 0.0003331349476038534, "cy_x": 0.0004618927349220216, "cy_y": 0.0006782421679971363, "cz_x": -0.0003070007847730449, "cz_y": -0.0004221234189514228, "cz_z": 0.0003231931992380369, "cx_dot_x": -3.34936503392263e-07, "cx_dot_y": -4.686084221046758e-07, "cx_dot_z": 2.484949578400095e-07, "cx_dot_x_dot": 4.29602280558729e-10, "cy_dot_x": -2.211832501084875e-07, "cy_dot_y": -2.864186892102733e-07, "cy_dot_z": 1.798098699846038e-07, "cy_dot_x_dot": 2.608899201686016e-10, "cy_dot_y_dot": 1.767514756338532e-10, "cz_dot_x": -3.041346050686871e-07, "cz_dot_y": -4.989496988610662e-07, "cz_dot_z": 3.540310904497689e-07, "cz_dot_x_dot": 1.86926319295459e-10, "cz_dot_y_dot": 1.008862586240695e-10, "cz_dot_z_dot": 6.2244443386355e-10 }, "adam_fields": [{ "key": "INITIAL_PERTURBATION", "value": "3" }, { "key": "HYPERCUBE", "value": "FACES" }], "ccsds_opm_vers": "2.0", "state_vector": { "epoch": "2018-06-21T17:43:20.984304Z", "x": 130347560.13690618, "y": -74407287.6018632, "z": -35247598.54147063, "x_dot": 23.935241263310683, "y_dot": 27.146279819258538, "z_dot": 10.346605942591514 } } expected_opm2 = """CCSDS_OPM_VERS = 2.0 CREATION_DATE = 2018-06-21 17:43:20.984372 ORIGINATOR = Test COMMENT Cartesian coordinate system OBJECT_NAME = TestObj OBJECT_ID = TestObjId CENTER_NAME = SUN REF_FRAME = ICRF TIME_SYSTEM = UTC EPOCH = 2018-06-21T17:43:20.984304Z X = 130347560.13690618 Y = -74407287.6018632 Z = -35247598.54147063 X_DOT = 23.935241263310683 Y_DOT = 27.146279819258538 Z_DOT = 10.346605942591514 MASS = 500.5 SOLAR_RAD_AREA = 25.2 SOLAR_RAD_COEFF = 1.2 DRAG_AREA = 33.3 DRAG_COEFF = 2.5 CX_X = 0.0003331349476038534 CY_X = 0.0004618927349220216 CY_Y = 0.0006782421679971363 CZ_X = -0.0003070007847730449 CZ_Y = -0.0004221234189514228 CZ_Z = 0.0003231931992380369 CX_DOT_X = -3.34936503392263e-07 CX_DOT_Y = -4.686084221046758e-07 CX_DOT_Z = 2.484949578400095e-07 CX_DOT_X_DOT = 4.29602280558729e-10 CY_DOT_X = -2.211832501084875e-07 CY_DOT_Y = -2.864186892102733e-07 CY_DOT_Z = 1.798098699846038e-07 CY_DOT_X_DOT = 2.608899201686016e-10 CY_DOT_Y_DOT = 1.767514756338532e-10 CZ_DOT_X = -3.041346050686871e-07 CZ_DOT_Y = -4.989496988610662e-07 CZ_DOT_Z = 3.540310904497689e-07 CZ_DOT_X_DOT = 1.86926319295459e-10 CZ_DOT_Y_DOT = 1.008862586240695e-10 CZ_DOT_Z_DOT = 6.2244443386355e-10 USER_DEFINED_ADAM_INITIAL_PERTURBATION = 3 [sigma] USER_DEFINED_ADAM_HYPERCUBE = FACES MAN_EPOCH_IGNITION = 2018-06-21T17:43:20.984304Z MAN_DURATION = 0.0 MAN_DELTA_MASS = 0.0 MAN_REF_FRAME = TNW MAN_DV_1 = 1.0 MAN_DV_2 = 2.0 MAN_DV_3 = 3.0""" expected_opm2 = OpmParamsTest.remove_non_static_fields(expected_opm2) opm_params2 = OpmParams.fromJsonResponse(json2) actual_opm2 = OpmParamsTest.remove_non_static_fields( opm_params2.generate_opm()) self.assertEqual(expected_opm2, actual_opm2) json3 = { "header": { "originator": "Test", "creation_date": "2018-06-21 17:56:58.406867" }, "metadata": { "comments": ["Cartesian coordinate system"], "object_name": "TestObj", "object_id": "TestObjId", "center_name": "SUN", "ref_frame": "ICRF", "time_system": "UTC" }, "keplerian": { "eccentricity": 0.5355029800000188, "inclination": 23.439676743246295, "gm": 132712440041.9394, "semi_major_axis": 313072891.38037175, "mean_motion": 0.0, "ra_of_asc_node": 359.9942693176405, "arg_of_pericenter": 328.5584374618295, "true_anomaly": -127.01778914927144, "mean_anomaly": 0.0 }, "spacecraft": { "mass": 500.5, "solar_rad_area": 25.2, "solar_rad_coeff": 1.2, "drag_area": 33.3, "drag_coeff": 2.5 }, "ccsds_opm_vers": "2.0", "state_vector": { "epoch": "2018-06-21T17:56:58.406556Z", "x": 0.0, "y": 0.0, "z": 0.0, "x_dot": 0.0, "y_dot": 0.0, "z_dot": 0.0 } } expected_opm3 = """CCSDS_OPM_VERS = 2.0 CREATION_DATE = 2018-06-21 17:56:58.406717 ORIGINATOR = Test COMMENT Cartesian coordinate system OBJECT_NAME = TestObj OBJECT_ID = TestObjId CENTER_NAME = SUN REF_FRAME = ICRF TIME_SYSTEM = UTC EPOCH = 2018-06-21T17:56:58.406556Z X = 0.0 Y = 0.0 Z = 0.0 X_DOT = 0.0 Y_DOT = 0.0 Z_DOT = 0.0 SEMI_MAJOR_AXIS = 313072891.38037175 ECCENTRICITY = 0.5355029800000188 INCLINATION = 23.439676743246295 RA_OF_ASC_NODE = 359.9942693176405 ARG_OF_PERICENTER = 328.5584374618295 TRUE_ANOMALY = -127.01778914927144 GM = 132712440041.9394 MASS = 500.5 SOLAR_RAD_AREA = 25.2 SOLAR_RAD_COEFF = 1.2 DRAG_AREA = 33.3 DRAG_COEFF = 2.5""" expected_opm3 = OpmParamsTest.remove_non_static_fields(expected_opm3) opm_params3 = OpmParams.fromJsonResponse(json3) actual_opm3 = OpmParamsTest.remove_non_static_fields( opm_params3.generate_opm()) self.assertEqual(expected_opm3, actual_opm3)
class TargetedPropagationsTest(unittest.TestCase): """Unit tests for TargetedPropagations module """ @classmethod def remove_non_static_fields(cls, opm_string): # Remove the CREATION_DATE stamp since that varies. return "\n".join([line for line in opm_string.splitlines() if not line.startswith('CREATION_DATE')]) dummy_propagation_params = PropagationParams({ 'start_time': 'AAA', 'end_time': 'BBB', }) dummy_opm_params = OpmParams({ 'epoch': 'DDD', 'state_vector': [1.0, 2.0, 3.0, 4.0, 5.0, 6.0] }) dummy_targeting_params = TargetingParams({ 'target_distance_from_earth': 123 }) dummy_opm_params_as_api_response = { "header": { "originator": "ADAM_User", "creation_date": "2018-06-21 19:13:27.261813" }, "metadata": { "comments": [ "Cartesian coordinate system" ], "object_name": "dummy", "object_id": "001", "center_name": "SUN", "ref_frame": "ICRF", "time_system": "UTC" }, "spacecraft": { "mass": 1000.0, "solar_rad_area": 20.0, "solar_rad_coeff": 1.0, "drag_area": 20.0, "drag_coeff": 2.2 }, "ccsds_opm_vers": "2.0", "state_vector": { "epoch": "DDD", "x": 1.0, "y": 2.0, "z": 3.0, "x_dot": 4.0, "y_dot": 5.0, "z_dot": 6.0 } } def test_insert_targeted_propagation(self): dummy_rest = {'not': 'used'} targeted_props = TargetedPropagations(dummy_rest) # Override AdamObjects._insert to just dump out a copy of the data passed. passed_data = [] def store_data(self, data, passed_data=passed_data): passed_data.append(data) return 'uuid' tmp_insert = AdamObjects._insert AdamObjects._insert = store_data prop = TargetedPropagation( self.dummy_propagation_params, self.dummy_opm_params, self.dummy_targeting_params) targeted_props.insert(prop, 'project_uuid') uuid = prop.get_uuid() self.assertEqual('uuid', uuid) self.assertEqual( self.dummy_propagation_params.get_description(), passed_data[0]['description']) passed_prop_params = passed_data[0]['initialPropagationParameters'] self.assertEqual( self.dummy_propagation_params.get_start_time(), passed_prop_params['start_time']) self.assertEqual( self.dummy_propagation_params.get_end_time(), passed_prop_params['end_time']) self.assertEqual( self.dummy_propagation_params.get_propagator_uuid(), passed_prop_params['propagator_uuid']) self.assertEqual( self.dummy_propagation_params.get_step_size(), passed_prop_params['step_duration_sec']) self.assertEqual( TargetedPropagationsTest.remove_non_static_fields( self.dummy_opm_params.generate_opm()), TargetedPropagationsTest.remove_non_static_fields( passed_prop_params['opmFromString'])) passed_targeting_params = passed_data[0]['targetingParameters'] self.assertEqual(self.dummy_targeting_params.get_target_distance_from_earth(), passed_targeting_params['targetDistanceFromEarth']) self.assertEqual(self.dummy_targeting_params.get_tolerance(), passed_targeting_params['tolerance']) self.assertEqual(self.dummy_targeting_params.get_run_nominal_only(), passed_targeting_params['runNominalOnly']) self.assertEqual('project_uuid', passed_data[0]['project']) AdamObjects._insert = tmp_insert def test_get_targeted_propagation(self): dummy_rest = {'not': 'used'} targeted_props = TargetedPropagations(dummy_rest) return_data = { "uuid": "uuid", "initialPropagationParameters": { "start_time": "AAA", "end_time": "BBB", "step_duration_sec": "0", "propagator_uuid": "00000000-0000-0000-0000-000000000001", "executor": "stk", "opm": { "header": { "originator": "ADAM_User", "creation_date": "2018-06-21 19:28:47.304102" }, "metadata": { "comments": [ "Cartesian coordinate system" ], "object_name": "dummy", "object_id": "001", "center_name": "SUN", "ref_frame": "ICRF", "time_system": "UTC" }, "spacecraft": { "mass": 1000.0, "solar_rad_area": 20.0, "solar_rad_coeff": 1.0, "drag_area": 20.0, "drag_coeff": 2.2 }, "ccsds_opm_vers": "2.0", "state_vector": { "epoch": "DDD", "x": 1.0, "y": 2.0, "z": 3.0, "x_dot": 4.0, "y_dot": 5.0, "z_dot": 6.0 } } }, "targetingParameters": { "targetDistanceFromEarth": 123.0, "tolerance": 1.0, "runNominalOnly": False }, "description": "Created by test at 2018-06-21 19:28:47.303980Z", "maneuverX": 0.0, "maneuverY": 0.0, "maneuverZ": 0.0 } def return_data(self, uuid, return_data=return_data): return return_data tmp_get_json = AdamObjects._get_json AdamObjects._get_json = return_data targeted_prop = targeted_props.get('uuid') self.assertEqual('uuid', targeted_prop.get_uuid()) self.assertEqual(self.dummy_propagation_params.get_start_time(), targeted_prop.get_propagation_params().get_start_time()) self.assertEqual(self.dummy_propagation_params.get_end_time(), targeted_prop.get_propagation_params().get_end_time()) self.assertEqual( TargetedPropagationsTest.remove_non_static_fields( self.dummy_opm_params.generate_opm()), TargetedPropagationsTest.remove_non_static_fields( targeted_prop.get_opm_params().generate_opm())) self.assertEqual(self.dummy_targeting_params.get_target_distance_from_earth(), targeted_prop.get_targeting_params().get_target_distance_from_earth()) self.assertIsNone(targeted_prop.get_ephemeris()) self.assertEqual([0, 0, 0], targeted_prop.get_maneuver()) AdamObjects._get_json = tmp_get_json
class BatchPropagationsTest(unittest.TestCase): """Unit tests for BatchPropagations module """ @classmethod def remove_non_static_fields(cls, opm_string): # Remove the CREATION_DATE stamp since that varies. return "\n".join([ line for line in opm_string.splitlines() if not line.startswith('CREATION_DATE') ]) dummy_propagation_params = PropagationParams({ 'start_time': 'AAA', 'end_time': 'BBB', }) dummy_opm_params = OpmParams({ 'epoch': 'DDD', 'state_vector': [1.0, 2.0, 3.0, 4.0, 5.0, 6.0] }) dummy_opm_params_as_api_response = { "header": { "originator": "ADAM_User", "creation_date": "2018-06-21 19:13:27.261813" }, "metadata": { "comments": ["Cartesian coordinate system"], "object_name": "dummy", "object_id": "001", "center_name": "SUN", "ref_frame": "ICRF", "time_system": "UTC" }, "spacecraft": { "mass": 1000.0, "solar_rad_area": 20.0, "solar_rad_coeff": 1.0, "drag_area": 20.0, "drag_coeff": 2.2 }, "ccsds_opm_vers": "2.0", "state_vector": { "epoch": "DDD", "x": 1.0, "y": 2.0, "z": 3.0, "x_dot": 4.0, "y_dot": 5.0, "z_dot": 6.0 } } def test_create_batch_propagation(self): dummy_rest = {'not': 'used'} batch_props = BatchPropagations(dummy_rest) # Override AdamObjects._insert to just dump out a copy of the data passed. passed_data = [] def store_data(self, data, passed_data=passed_data): passed_data.append(data) return 'uuid' tmp_insert = AdamObjects._insert AdamObjects._insert = store_data batch_prop = BatchPropagation(self.dummy_propagation_params, self.dummy_opm_params) batch_props.insert(batch_prop, 'project_uuid') uuid = batch_prop.get_uuid() self.assertEqual('uuid', uuid) self.assertEqual(self.dummy_propagation_params.get_description(), passed_data[0]['description']) passed_prop_params = passed_data[0]['templatePropagationParameters'] self.assertEqual(self.dummy_propagation_params.get_start_time(), passed_prop_params['start_time']) self.assertEqual(self.dummy_propagation_params.get_end_time(), passed_prop_params['end_time']) self.assertEqual(self.dummy_propagation_params.get_propagator_uuid(), passed_prop_params['propagator_uuid']) self.assertEqual(self.dummy_propagation_params.get_step_size(), passed_prop_params['step_duration_sec']) self.assertEqual( BatchPropagationsTest.remove_non_static_fields( self.dummy_opm_params.generate_opm()), BatchPropagationsTest.remove_non_static_fields( passed_prop_params['opmFromString'])) self.assertEqual('project_uuid', passed_data[0]['project']) AdamObjects._insert = tmp_insert def test_get_batch_propagation(self): dummy_rest = {'not': 'used'} batch_props = BatchPropagations(dummy_rest) return_data = { "uuid": "uuid", "templatePropagationParameters": { "start_time": "AAA", "end_time": "BBB", "step_duration_sec": "0", "propagator_uuid": "00000000-0000-0000-0000-000000000001", "executor": "stk", "opm": { "header": { "originator": "ADAM_User", "creation_date": "2018-06-21 19:28:47.304102" }, "metadata": { "comments": ["Cartesian coordinate system"], "object_name": "dummy", "object_id": "001", "center_name": "SUN", "ref_frame": "ICRF", "time_system": "UTC" }, "spacecraft": { "mass": 1000.0, "solar_rad_area": 20.0, "solar_rad_coeff": 1.0, "drag_area": 20.0, "drag_coeff": 2.2 }, "ccsds_opm_vers": "2.0", "state_vector": { "epoch": "DDD", "x": 1.0, "y": 2.0, "z": 3.0, "x_dot": 4.0, "y_dot": 5.0, "z_dot": 6.0 } } }, "summary": "1000 2000 3000 4000 5000 6000 7000\n7000 6000 5000 4000 3000 2000 1000" } def return_data(self, uuid, return_data=return_data): return return_data tmp_get_json = AdamObjects._get_json AdamObjects._get_json = return_data batch_prop = batch_props.get('uuid') self.assertEqual('uuid', batch_prop.get_uuid()) self.assertEqual(self.dummy_propagation_params.get_start_time(), batch_prop.get_propagation_params().get_start_time()) self.assertEqual(self.dummy_propagation_params.get_end_time(), batch_prop.get_propagation_params().get_end_time()) self.assertEqual( BatchPropagationsTest.remove_non_static_fields( self.dummy_opm_params.generate_opm()), BatchPropagationsTest.remove_non_static_fields( batch_prop.get_opm_params().generate_opm())) self.assertEqual( '1000 2000 3000 4000 5000 6000 7000\n7000 6000 5000 4000 3000 2000 1000', batch_prop.get_summary()) self.assertEqual([[1, 2, 3, 4, 5, 6, 7], [7, 6, 5, 4, 3, 2, 1]], batch_prop.get_final_state_vectors()) AdamObjects._get_json = tmp_get_json
def test_basic_stm(self): state_vec = [ 130347560.13690618, -74407287.6018632, -35247598.541470632, 23.935241263310683, 27.146279819258538, 10.346605942591514 ] start_time = datetime.datetime(2017, 10, 4, 0, 0, 0, 123456) end_time = datetime.datetime(2018, 10, 4, 0, 0, 0, 123456) propagation_params = PropagationParams({ 'start_time': start_time.isoformat() + 'Z', 'end_time': end_time.isoformat() + 'Z', 'project_uuid': self.working_project.get_uuid(), 'description': 'Created by test at ' + start_time.isoformat() + 'Z' }) opm_params = OpmParams({ 'epoch': start_time.isoformat() + 'Z', 'state_vector': state_vec, }) end_state, stm = self.stm_module.run_stm_propagation( propagation_params, opm_params) # Taken from printed output of ../state_stm_propagation.py expected_end_state = np.array([ -37523497.931654416, 492950622.8491298, 204482176.63445434, -11.336957217854795, 7.18499733419028, 3.3597496059480085 ]) expected_stm = np.matrix( [[ 9.70874844e+00, -1.21563565e+00, -9.26967637e-01, 5.34214567e+07, 1.64329953e+07, 5.30094892e+06 ], [ 7.11171945e+00, -3.24202476e+00, -5.93038128e-01, 3.90278376e+07, 3.82420496e+07, 9.62761631e+06 ], [ 2.50503331e+00, -3.00334152e-01, -2.62144498e+00, 1.46131045e+07, 1.04218322e+07, 1.53347450e+07 ], [ 2.14264136e-07, -2.82295666e-08, -2.23357566e-08, 1.33259336e+00, 6.98930318e-01, 2.41824966e-01 ], [ 4.69172199e-07, -2.03571494e-07, -6.32223023e-08, 2.52995851e+00, 2.04570983e+00, 7.47014439e-01 ], [ 1.82661672e-07, -4.57388872e-08, -1.15455121e-07, 9.96459361e-01, 8.11376173e-01, 3.16765622e-01 ]]) npt.assert_allclose(expected_end_state, np.array(end_state), rtol=1e-8, atol=0) npt.assert_allclose(expected_stm.getA(), stm.getA(), rtol=1e-8, atol=0)