diff --git a/tests/integration/envs/general_satellite_tasking/scenario/test_int_sat_actions.py b/tests/integration/envs/general_satellite_tasking/scenario/test_int_sat_actions.py index d31cbd80..d99ab371 100644 --- a/tests/integration/envs/general_satellite_tasking/scenario/test_int_sat_actions.py +++ b/tests/integration/envs/general_satellite_tasking/scenario/test_int_sat_actions.py @@ -6,6 +6,7 @@ from bsk_rl.envs.general_satellite_tasking.scenario import sat_actions as sa from bsk_rl.envs.general_satellite_tasking.scenario import sat_observations as so from bsk_rl.envs.general_satellite_tasking.scenario.environment_features import ( + NadirTarget, StaticTargets, ) from bsk_rl.envs.general_satellite_tasking.simulation import dynamics, environment, fsw @@ -148,3 +149,42 @@ def test_desat_action(self): assert np.linalg.norm( self.env.satellite.dynamics.wheel_speeds ) < np.linalg.norm(init_speeds) + + +class TestNadirImagingActions: + class ImageSat( + sa.NadirImagingActions, + so.TimeState, + ): + dyn_type = dynamics.ContinuousImagingDynModel + fsw_type = fsw.ContinuousImagingFSWModel + + env = gym.make( + "SingleSatelliteTasking-v1", + satellites=ImageSat( + "EO-1", + n_ahead_act=10, + sat_args=ImageSat.default_sat_args( + oe=random_orbit, + imageAttErrorRequirement=0.05, + imageRateErrorRequirement=0.05, + instrumentBaudRate=1.0, + dataStorageCapacity=3.0, + transmitterBaudRate=-1.0, + ), + ), + env_type=environment.BasicEnvironmentModel, + env_args=environment.BasicEnvironmentModel.default_env_args(), + env_features=NadirTarget(), + data_manager=data.NoDataManager(), + sim_rate=1.0, + time_limit=10000.0, + max_step_duration=1e9, + disable_env_checker=True, + ) + + def test_image(self): + self.env.reset() + storage_init = self.env.satellite.dynamics.storage_level + self.env.step(0) + assert self.env.satellite.dynamics.storage_level > storage_init diff --git a/tests/unittest/envs/general_satellite_tasking/scenario/test_data.py b/tests/unittest/envs/general_satellite_tasking/scenario/test_data.py index f23c71b4..93f7ad14 100644 --- a/tests/unittest/envs/general_satellite_tasking/scenario/test_data.py +++ b/tests/unittest/envs/general_satellite_tasking/scenario/test_data.py @@ -183,3 +183,84 @@ def test_calc_reward_custom_fn(self): } ) assert reward == approx(1.5) + + +class TestNadirScanningTimeData: + def test_add_null(self): + dat1 = data.NadirScanningTimeData() + dat2 = data.NadirScanningTimeData() + dat = dat1 + dat2 + assert dat.scanning_time == 0.0 + + def test_add_to_null(self): + dat1 = data.NadirScanningTimeData(1.0) + dat2 = data.NadirScanningTimeData() + dat = dat1 + dat2 + assert dat.scanning_time == 1.0 + + def test_add(self): + dat1 = data.NadirScanningTimeData(1.0) + dat2 = data.NadirScanningTimeData(3.0) + dat = dat1 + dat2 + assert dat.scanning_time == 4.0 + + +class TestScanningNadirTimeStore: + def test_get_log_state(self): + sat = MagicMock() + sat.dynamics.storageUnit.storageUnitDataOutMsg.read().storageLevel = 6 + ds = data.ScanningNadirTimeStore(MagicMock(), sat) + assert ds._get_log_state() == 6.0 + + @pytest.mark.parametrize( + "before,after,new_time", + [ + (0, 3, 1), + (3, 6, 1), + (1, 1, 0), + (0, 6, 2), + ], + ) + def test_compare_log_states(self, before, after, new_time): + sat = MagicMock() + ds = data.ScanningNadirTimeStore(MagicMock(), sat) + sat.dynamics.instrument.nodeBaudRate = 3 + dat = ds._compare_log_states(before, after) + assert dat.scanning_time == new_time + + +class TestNadirScanningManager: + def test_calc_reward(self): + dm = data.NadirScanningManager(MagicMock()) + dm.data = data.NadirScanningTimeData([]) + dm.env_features.value_per_second = 1.0 + reward = dm._calc_reward( + { + "sat1": data.NadirScanningTimeData(1), + "sat2": data.NadirScanningTimeData(2), + } + ) + assert reward == approx(3) + + def test_calc_reward_existing(self): + dm = data.NadirScanningManager(MagicMock()) + dm.data = data.NadirScanningTimeData(1) + dm.env_features.value_per_second = 1.0 + reward = dm._calc_reward( + { + "sat1": data.NadirScanningTimeData(2), + "sat2": data.NadirScanningTimeData(3), + } + ) + assert reward == approx(5) + + def test_calc_reward_custom_fn(self): + dm = data.NadirScanningManager(MagicMock(), reward_fn=lambda x: 1 / x) + dm.data = data.NadirScanningTimeData([]) + reward = dm._calc_reward( + { + "sat1": data.NadirScanningTimeData(2), + "sat2": data.NadirScanningTimeData(2), + } + ) + assert reward == approx(1.0) diff --git a/tests/unittest/envs/general_satellite_tasking/scenario/test_environment_features.py b/tests/unittest/envs/general_satellite_tasking/scenario/test_environment_features.py index faead34a..f524a163 100644 --- a/tests/unittest/envs/general_satellite_tasking/scenario/test_environment_features.py +++ b/tests/unittest/envs/general_satellite_tasking/scenario/test_environment_features.py @@ -6,6 +6,7 @@ from bsk_rl.envs.general_satellite_tasking.scenario.environment_features import ( CityTargets, + NadirTarget, StaticTargets, Target, lla2ecef, @@ -146,3 +147,10 @@ def test_regenerate_targets_offset(self, mock_read_csv, mock_lla2ecef): for target in ct.targets: assert np.linalg.norm(target.location - nominal) <= 0.03 assert np.linalg.norm(target.location) == approx(1.0) + + +class TestNadirTarget: + def test_init(self): + st = NadirTarget() + assert st.name == "nadir" + assert st.location == [0, 0, 0] diff --git a/tests/unittest/envs/general_satellite_tasking/scenario/test_sat_actions.py b/tests/unittest/envs/general_satellite_tasking/scenario/test_sat_actions.py index cce8a1fb..7c4c8374 100644 --- a/tests/unittest/envs/general_satellite_tasking/scenario/test_sat_actions.py +++ b/tests/unittest/envs/general_satellite_tasking/scenario/test_sat_actions.py @@ -168,6 +168,23 @@ def test_set_action(self, sat_init, discrete_set, target): sat.image.assert_called_once() +@patch.multiple(sa.NadirImagingActions, __abstractmethods__=set()) +@patch("bsk_rl.envs.general_satellite_tasking.scenario.satellites.Satellite.__init__") +class TestNadirImagingActions: + def test_init(self, sat_init): + sat = sa.NadirImagingActions() + sat_init.assert_called_once() + assert sat.action_map == {"0": "nadirImage"} + + @patch("bsk_rl.envs.general_satellite_tasking.simulation.fsw") + def test_image(self, sat_init, fsw): + sat = sa.NadirImagingActions() + sat.task_target_for_imaging = MagicMock() + sat.log_info = MagicMock() + sat.fsw = fsw + assert "nadir_image" == sat.nadirImage() + + @patch.multiple(sa.ChargingAction, __abstractmethods__=set()) @patch.multiple(sa.DriftAction, __abstractmethods__=set()) @patch.multiple(sa.DesatAction, __abstractmethods__=set()) diff --git a/tests/unittest/envs/general_satellite_tasking/simulation/test_dynamics.py b/tests/unittest/envs/general_satellite_tasking/simulation/test_dynamics.py index 8ab166ae..c57d4077 100644 --- a/tests/unittest/envs/general_satellite_tasking/simulation/test_dynamics.py +++ b/tests/unittest/envs/general_satellite_tasking/simulation/test_dynamics.py @@ -7,6 +7,7 @@ from bsk_rl.envs.general_satellite_tasking.simulation import environment from bsk_rl.envs.general_satellite_tasking.simulation.dynamics import ( BasicDynamicsModel, + ContinuousImagingDynModel, DynamicsModel, GroundStationDynModel, ImagingDynModel, @@ -256,3 +257,15 @@ def test_init_objects(self, *args): GroundStationDynModel(MagicMock(simulator=MagicMock()), 1.0) for setter in args: setter.assert_called_once() + + +@patch(imdyn + "requires_env", MagicMock(return_value=[])) +@patch(imdyn + "_init_dynamics_objects", MagicMock()) +class TestContinuousImagingDynModel: + def test_storage_properties(self): + dyn = ContinuousImagingDynModel(MagicMock(simulator=MagicMock()), 1.0) + dyn.storageUnit = MagicMock() + dyn.storageUnit.storageUnitDataOutMsg.read.return_value.storageLevel = 50.0 + dyn.storageUnit.storageCapacity = 100.0 + assert dyn.storage_level == 50.0 + assert dyn.storage_level_fraction == 0.5