diff --git a/src/services/environment.py b/src/services/environment.py index 991c865..3330869 100644 --- a/src/services/environment.py +++ b/src/services/environment.py @@ -28,13 +28,18 @@ def from_env_model(cls, env: EnvironmentModel) -> Self: elevation=env.elevation, date=env.date, ) + # RocketPy guards pressure/temperature against None but NOT wind, so + # a custom_atmosphere with wind_u/wind_v left unset raises + # "'NoneType' object has no attribute 'shape'". Default missing wind + # to 0 (only None is replaced — real 0.0 values and wind profiles pass + # through). rocketpy_env.set_atmospheric_model( type=env.atmospheric_model_type, file=env.atmospheric_model_file, pressure=env.pressure, temperature=env.temperature, - wind_u=env.wind_u, - wind_v=env.wind_v, + wind_u=env.wind_u if env.wind_u is not None else 0.0, + wind_v=env.wind_v if env.wind_v is not None else 0.0, ) return cls(environment=rocketpy_env) diff --git a/tests/unit/test_services/test_environment_service.py b/tests/unit/test_services/test_environment_service.py new file mode 100644 index 0000000..9f4ce9e --- /dev/null +++ b/tests/unit/test_services/test_environment_service.py @@ -0,0 +1,95 @@ +from src.models.environment import EnvironmentModel +from src.services.environment import EnvironmentService + + +def test_from_env_model_custom_atmosphere_default_wind_none(): + env_model = EnvironmentModel( + latitude=0.0, + longitude=0.0, + elevation=0.0, + atmospheric_model_type='custom_atmosphere', + pressure=101325.0, + temperature=288.15, + wind_u=None, + wind_v=None, + ) + service = EnvironmentService.from_env_model(env_model) + assert service.environment.wind_velocity_x(0) == 0.0 + assert service.environment.wind_velocity_y(0) == 0.0 + + +def test_from_env_model_custom_atmosphere_one_wind_component_none(): + env_model_u_set = EnvironmentModel( + latitude=0.0, + longitude=0.0, + elevation=0.0, + atmospheric_model_type='custom_atmosphere', + pressure=101325.0, + temperature=288.15, + wind_u=5.0, + wind_v=None, + ) + service_u = EnvironmentService.from_env_model(env_model_u_set) + assert service_u.environment.wind_velocity_x(0) == 5.0 + assert service_u.environment.wind_velocity_y(0) == 0.0 + + env_model_v_set = EnvironmentModel( + latitude=0.0, + longitude=0.0, + elevation=0.0, + atmospheric_model_type='custom_atmosphere', + pressure=101325.0, + temperature=288.15, + wind_u=None, + wind_v=3.0, + ) + service_v = EnvironmentService.from_env_model(env_model_v_set) + assert service_v.environment.wind_velocity_x(0) == 0.0 + assert service_v.environment.wind_velocity_y(0) == 3.0 + + +def test_from_env_model_custom_atmosphere_explicit_zero_wind(): + env_model = EnvironmentModel( + latitude=0.0, + longitude=0.0, + elevation=0.0, + atmospheric_model_type='custom_atmosphere', + pressure=101325.0, + temperature=288.15, + wind_u=0.0, + wind_v=0.0, + ) + service = EnvironmentService.from_env_model(env_model) + assert service.environment.wind_velocity_x(0) == 0.0 + assert service.environment.wind_velocity_y(0) == 0.0 + + +def test_from_env_model_custom_atmosphere_wind_profile_list(): + wind_u_profile = [(0.0, 2.0), (1000.0, 10.0)] + wind_v_profile = [(0.0, 1.0), (1000.0, 5.0)] + env_model = EnvironmentModel( + latitude=0.0, + longitude=0.0, + elevation=0.0, + atmospheric_model_type='custom_atmosphere', + pressure=101325.0, + temperature=288.15, + wind_u=wind_u_profile, + wind_v=wind_v_profile, + ) + service = EnvironmentService.from_env_model(env_model) + assert service.environment.wind_velocity_x(0) == 2.0 + assert service.environment.wind_velocity_x(1000) == 10.0 + assert service.environment.wind_velocity_y(0) == 1.0 + assert service.environment.wind_velocity_y(1000) == 5.0 + + +def test_from_env_model_standard_atmosphere(): + env_model = EnvironmentModel( + latitude=0.0, + longitude=0.0, + elevation=0.0, + atmospheric_model_type='standard_atmosphere', + ) + service = EnvironmentService.from_env_model(env_model) + assert service.environment is not None