def test_visible_above_horizon(self): """ visible_above_horizon test """ #equitorial orbit tle_line1 = "1 44235U 19029A 20178.66667824 .02170155 00000-0 40488-1 0 9998" tle_line2 = "2 44235 00.0000 163.9509 0005249 306.3756 83.0170 15.45172567 61683" #high inclination orbit tle2_line1 = "1 44235U 19029A 20178.66667824 .02170155 00000-0 40488-1 0 9998" tle2_line2 = "2 44235 70.0000 163.9509 0005249 306.3756 83.0170 15.45172567 61683" prop1 = orekit_utils.str_tle_propagator(tle_line1, tle_line2) prop2 = orekit_utils.str_tle_propagator(tle2_line1, tle2_line2) time = AbsoluteDate(2020, 6, 26, 1, 40, 00.000, TimeScalesFactory.getUTC()) #verified with graphing overviews self.assertFalse(orekit_utils.visible_above_horizon( prop1, prop2, time)) self.assertTrue( orekit_utils.visible_above_horizon(prop1, prop2, time.shiftedBy(60. * 10.))) self.assertTrue( orekit_utils.visible_above_horizon( prop1, prop2, time.shiftedBy(60. * 10. + 45. * 60.))) time_period_visible = orekit_utils.visible_above_horizon( prop1, prop2, time, 60 * 30)[0] self.assertTrue( time.shiftedBy(60. * 10.).isBetween(time_period_visible[0], time_period_visible[1]))
def test_check_iot_in_range(self): """ check_iot_in_range test """ tle_line1 = "1 44235U 19029A 20178.66667824 .02170155 00000-0 40488-1 0 9998" tle_line2 = "2 44235 00.0000 163.9509 0005249 306.3756 270.0170 15.45172567 61683" prop1 = orekit_utils.str_tle_propagator(tle_line1, tle_line2) lat = 0. lon = 0. alt = 10. time = AbsoluteDate(2020, 6, 26, 1, 40, 00.000, TimeScalesFactory.getUTC()) self.assertTrue(check_iot_in_range(prop1, lat, lon, alt, time)) self.assertFalse(check_iot_in_range(prop1, lat, lon, alt, time.shiftedBy(60.*30.)))
def get_sun_max_elevation(self, year, month, day): """ Returns the maximum elevation angle (in radians) of the Sun (that is the zenith) a given day. Parameters ---------- year : int Year. month : int Month. day : int Day. Returns ------- current_ele0 : TYPE DESCRIPTION. currentutc_date : TYPE DESCRIPTION. """ currentutc_date = AbsoluteDate(year, month, day, 0, 0, 0.0, TimeScalesFactory.getUTC()) is_max_elevation = False time_step = 10.0 current_ele0 = self.get_sun_elevation(currentutc_date) current_ele1 = self.get_sun_elevation( currentutc_date.shiftedBy(time_step)) if current_ele0 > current_ele1: is_max_elevation = True while not is_max_elevation: current_ele0 = current_ele1 current_ele1 = self.get_sun_elevation( currentutc_date.shiftedBy(time_step)) if current_ele0 > current_ele1: is_max_elevation = True currentutc_date.shiftedBy(-time_step) currentutc_date = currentutc_date.shiftedBy(time_step) return current_ele0, currentutc_date
class Environment(): """ Simulation environment. This environment is used to propagate trajectories and render images at each simulation step. """ def __init__(self, res_dir, starcat_dir, instrument, with_infobox, with_clipping, sssb, sun, lightref, encounter_date, duration, frames, encounter_distance, relative_velocity, with_sunnyside, with_terminator, timesampler_mode, slowmotion_factor, exposure, samples, device, tile_size, oneshot=False, spacecraft=None, opengl_renderer=False): self.opengl_renderer = opengl_renderer self.brdf_params = sssb.get('brdf_params', None) self.root_dir = Path(__file__).parent.parent.parent data_dir = self.root_dir / "data" self.models_dir = utils.check_dir(data_dir / "models") self.res_dir = res_dir self.starcat_dir = starcat_dir self.inst = sc.Instrument(instrument) self.ts = TimeScalesFactory.getTDB() self.ref_frame = FramesFactory.getICRF() self.mu_sun = Constants.IAU_2015_NOMINAL_SUN_GM encounter_date = encounter_date self.encounter_date = AbsoluteDate(int(encounter_date["year"]), int(encounter_date["month"]), int(encounter_date["day"]), int(encounter_date["hour"]), int(encounter_date["minutes"]), float(encounter_date["seconds"]), self.ts) self.duration = duration self.start_date = self.encounter_date.shiftedBy(-self.duration / 2.) self.end_date = self.encounter_date.shiftedBy(self.duration / 2.) self.frames = frames self.minimum_distance = encounter_distance self.relative_velocity = relative_velocity self.with_terminator = bool(with_terminator) self.with_sunnyside = bool(with_sunnyside) self.timesampler_mode = timesampler_mode self.slowmotion_factor = slowmotion_factor self.render_settings = dict() self.render_settings["exposure"] = exposure self.render_settings["samples"] = samples self.render_settings["device"] = device self.render_settings["tile"] = tile_size self.sssb_settings = sssb self.with_infobox = with_infobox self.with_clipping = with_clipping # Setup rendering engine (renderer) self.setup_renderer() # Setup SSSB self.setup_sssb(sssb) # Setup SC self.setup_spacecraft(spacecraft, oneshot=oneshot) if not self.opengl_renderer: # Setup Sun self.setup_sun(sun) # Setup Lightref self.setup_lightref(lightref) logger.debug("Init finished") def setup_renderer(self): """Create renderer, apply common settings and create sc cam.""" render_dir = utils.check_dir(self.res_dir) raw_dir = utils.check_dir(render_dir / "raw") if self.opengl_renderer: from .opengl import rendergl self.renderer = rendergl.RenderController(render_dir, stardb_path=self.starcat_dir) self.renderer.create_scene("SssbOnly") else: from .render import BlenderController self.renderer = BlenderController(render_dir, raw_dir, self.starcat_dir, self.inst, self.sssb_settings, self.with_infobox, self.with_clipping) self.renderer.create_camera("ScCam") self.renderer.configure_camera("ScCam", self.inst.focal_l, self.inst.chip_w) if not self.opengl_renderer: self.renderer.create_scene("SssbConstDist") self.renderer.create_camera("SssbConstDistCam", scenes="SssbConstDist") self.renderer.configure_camera("SssbConstDistCam", self.inst.focal_l, self.inst.chip_w) self.renderer.create_scene("LightRef") self.renderer.create_camera("LightRefCam", scenes="LightRef") self.renderer.configure_camera("LightRefCam", self.inst.focal_l, self.inst.chip_w) else: # as use sispo cam model self.renderer.set_scene_config({ 'debug': False, 'flux_only': False, 'sispo_cam': self.inst, # use sispo cam model instead #of own (could use own if can give exposure & gain) 'stars': True, # use own star db 'lens_effects': False, # includes the sun 'brdf_params': self.brdf_params, }) self.renderer.set_device(self.render_settings["device"], self.render_settings["tile"]) self.renderer.set_samples(self.render_settings["samples"]) self.renderer.set_exposure(self.render_settings["exposure"]) self.renderer.set_resolution(self.inst.res) self.renderer.set_output_format() def setup_sun(self, settings): """Create Sun and respective render object.""" sun_model_file = Path(settings["model"]["file"]) try: sun_model_file = sun_model_file.resolve() except OSError as e: raise SimulationError(e) if not sun_model_file.is_file(): sun_model_file = self.models_dir / sun_model_file.name sun_model_file = sun_model_file.resolve() if not sun_model_file.is_file(): raise SimulationError("Given SSSB model filename does not exist.") self.sun = cb.CelestialBody(settings["model"]["name"], model_file=sun_model_file) self.sun.render_obj = self.renderer.load_object(self.sun.model_file, self.sun.name) def setup_sssb(self, settings): """Create SmallSolarSystemBody and respective blender object.""" sssb_model_file = Path(settings["model"]["file"]) try: sssb_model_file = sssb_model_file.resolve() except OSError as e: raise SimulationError(e) if not sssb_model_file.is_file(): sssb_model_file = self.models_dir / sssb_model_file.name sssb_model_file = sssb_model_file.resolve() if not sssb_model_file.is_file(): raise SimulationError("Given SSSB model filename does not exist.") self.sssb = sssb.SmallSolarSystemBody(settings["model"]["name"], self.mu_sun, settings["trj"], settings["att"], model_file=sssb_model_file) self.sssb.render_obj = self.renderer.load_object( self.sssb.model_file, settings["model"]["name"], ["SssbOnly"] + ([] if self.opengl_renderer else ["SssbConstDist"])) self.sssb.render_obj.rotation_mode = "AXIS_ANGLE" self.sssb.render_obj.location = (0.0, 0.0, 0.0) # Setup previously generated coma coma = settings.get('coma', None) if coma: with open(coma['file'], 'r') as fh: coma.update(json.load(fh)) assert self.opengl_renderer, '"coma" setting under "sssb" is currently only supported for opengl rendering' sssb_rot = coma.get('sssb_rot', False) if not sssb_rot: # if param missing and one shot mode, assumes that coma is created with same asteroid orientation assert self.sssb.rot_history, 'SSSB rotation state for cached coma is not given with "sssb_rot"' sssb_rot = self.sssb.rot_history[0] sssb_rot = (sssb_rot.getAngle(), *sssb_rot.getAxis(RotationConvention.FRAME_TRANSFORM).toArray()) self.sssb.coma = self.renderer.load_coma( coma['tiles_file'], coma['dimensions'], coma['resolution'], coma.get('intensity', 1e-4), sssb_rot ) def setup_spacecraft(self, spacecraft=None, oneshot=False): """Create Spacecraft and respective blender object.""" sc_state = None sc_rot_state = None if spacecraft is None: sssb_state = self.sssb.get_state(self.encounter_date) sc_state = sc.Spacecraft.calc_encounter_state(sssb_state, self.minimum_distance, self.relative_velocity, self.with_terminator, self.with_sunnyside) else: if 'r' in spacecraft: sc_state = PVCoordinates(Vector3D(spacecraft['r']), Vector3D(spacecraft.get('v', [0.0, 0.0, 0.0]))) if 'angleaxis' in spacecraft: sc_pxpz_rot = Rotation(Vector3D(spacecraft['angleaxis'][1:4]), spacecraft['angleaxis'][0], RotationConvention.FRAME_TRANSFORM) # transform camera where +x is forward and +z is up into -z is forward and +y is up mzpy_rot = self.pxpz_to_mzpy(sc_pxpz_rot) sc_rot_state = AngularCoordinates(mzpy_rot, Vector3D(0., 0., 0.)) self.spacecraft = sc.Spacecraft("CI", self.mu_sun, sc_state, self.encounter_date, rot_state=sc_rot_state, oneshot=oneshot) @staticmethod def pxpz_to_mzpy(pxpz_rot): pxpz_to_mzpy_rot = Rotation(0.5, 0.5, -0.5, -0.5, False) return pxpz_to_mzpy_rot.applyTo(pxpz_rot) @staticmethod def mzpy_to_pxpz(mzpy_rot): pxpz_to_mzpy_rot = Rotation(0.5, 0.5, -0.5, -0.5, False) return pxpz_to_mzpy_rot.applyInverseTo(mzpy_rot) def setup_lightref(self, settings): """Create lightreference blender object.""" lightref_model_file = Path(settings["model"]["file"]) try: lightref_model_file = lightref_model_file.resolve() except OSError as e: raise SimulationError(e) if not lightref_model_file.is_file(): lightref_model_file = self.models_dir / lightref_model_file.name lightref_model_file = lightref_model_file.resolve() if not lightref_model_file.is_file(): raise SimulationError("Given lightref model filename does not exist.") self.lightref = self.renderer.load_object(lightref_model_file, settings["model"]["name"], scenes="LightRef") self.lightref.location = (0.0, 0.0, 0.0) def simulate(self): """Do simulation.""" logger.debug("Starting simulation") logger.debug("Propagating SSSB") self.sssb.propagate(self.start_date, self.end_date, self.frames, self.timesampler_mode, self.slowmotion_factor) logger.debug("Propagating Spacecraft") self.spacecraft.propagate(self.start_date, self.end_date, self.frames, self.timesampler_mode, self.slowmotion_factor) logger.debug("Simulation completed") self.save_results() def render(self): """Render simulation scenario.""" logger.debug("Rendering simulation") scaling = 1. if self.opengl_renderer else 1000. N = len(self.spacecraft.date_history) # Render frame by frame print("Rendering in progress...") for i, (date, sc_pos, sc_rot, sssb_pos, sssb_rot) in enumerate(zip( self.spacecraft.date_history, self.spacecraft.pos_history, self.spacecraft.rot_history, self.sssb.pos_history, self.sssb.rot_history)): date_str = datetime.strptime(date.toString(), "%Y-%m-%dT%H:%M:%S.%f") date_str = date_str.strftime("%Y-%m-%dT%H%M%S-%f") # metadict creation metainfo = dict() metainfo["sssb_pos"] = np.asarray(sssb_pos.toArray()) metainfo["sc_pos"] = np.asarray(sc_pos.toArray()) metainfo["distance"] = sc_pos.distance(sssb_pos) metainfo["date"] = date_str # Set Rotation angle, axis = convert_rot_to_angle_axis(sssb_rot, RotationConvention.FRAME_TRANSFORM) self.renderer.set_object_rot(angle, axis , self.sssb.render_obj) # Update environment # Removed unnecessary conditional, opengl can omit the scaling self.renderer.set_sun_location(-np.asarray(sssb_pos.toArray()), scaling, getattr(self,"sun", None)) # Update sssb and spacecraft pos_sc_rel_sssb = np.asarray(sc_pos.subtract(sssb_pos).toArray()) / scaling self.renderer.set_camera_location("ScCam", pos_sc_rel_sssb) if self.spacecraft.auto_targeting: self.renderer.target_camera(self.sssb.render_obj, "ScCam") else: angle, axis = convert_rot_to_angle_axis(sc_rot, RotationConvention.FRAME_TRANSFORM) self.renderer.set_camera_rot(angle, axis, "ScCam") if not self.opengl_renderer: # Update scenes/cameras pos_cam_const_dist = pos_sc_rel_sssb * scaling / np.sqrt( np.dot(pos_sc_rel_sssb, pos_sc_rel_sssb)) self.renderer.set_camera_location("SssbConstDistCam", pos_cam_const_dist) self.renderer.target_camera(self.sssb.render_obj, "SssbConstDistCam") lightrefcam_pos = -np.asarray(sssb_pos.toArray()) * scaling \ / np.sqrt(np.dot(np.asarray(sssb_pos.toArray()), np.asarray(sssb_pos.toArray()))) self.renderer.set_camera_location("LightRefCam", lightrefcam_pos) self.renderer.target_camera(self.sun.render_obj, "CalibrationDisk") self.renderer.target_camera(self.lightref, "LightRefCam") # Render blender scenes self.renderer.render(metainfo) print('%d/%d' % (i+1, N)) logger.debug("Rendering completed") def save_results(self): """Save simulation results to a file.""" logger.debug("Saving propagation results") float_formatter = "{:.16f}".format np.set_printoptions(formatter={'float_kind': float_formatter}) vec2str = lambda v: str(np.asarray(v.toArray())) print_list = [ [str(v) for v in self.spacecraft.date_history], [vec2str(v) for v in self.spacecraft.pos_history], [vec2str(v) for v in self.spacecraft.vel_history], #[vec2str(v) for v in self.spacecraft.rot_history], [vec2str(v) for v in self.sssb.pos_history], [vec2str(v) for v in self.sssb.vel_history], #[vec2str(v) for v in self.sssb.rot_history], ] with open(str(self.res_dir / "DynamicsHistory.txt"), "w+") as file: for i in range(len(self.spacecraft.date_history)): line = "\t".join([v[i] for v in print_list]) + "\n" file.write(line) logger.debug("Propagation results saved")
class Propagator: def __init__(self, initial_orbit, initial_date, shifted_date): self.shifted_date = shifted_date self.initial_orbit = initial_orbit self.initial_date = initial_date def __str__(self): return str(self.__dict__) def propagate_keplerian_elements(self): propagator = KeplerianPropagator(self.initial_orbit) return propagator.propagate(self.initial_date, self.shifted_date) if __name__ == "__main__": instance = KeplerianElements( 24464560.0, 0.7311, 0.122138, 3.10686, 1.00681, 0.048363, PositionAngle.MEAN, FramesFactory.getEME2000(), AbsoluteDate(2020, 1, 1, 0, 0, 00.000, TimeScalesFactory.getUTC()), Constants.GRS80_EARTH_MU) k = instance.init_keplerian_elements() init_date = AbsoluteDate(2020, 1, 1, 0, 0, 00.000, TimeScalesFactory.getUTC()) shift = init_date.shiftedBy(3600.0 * 48) kp = Propagator(k, init_date, shift) kp.propagate_keplerian_elements() print(k) print(kp)
def main(): a = 24396159.0 # semi major axis (m) e = 0.720 # eccentricity i = radians(10.0) # inclination omega = radians(50.0) # perigee argument raan = radians(150) # right ascension of ascending node lM = 0.0 # mean anomaly # Set inertial frame inertialFrame = FramesFactory.getEME2000() # Initial date in UTC time scale utc = TimeScalesFactory.getUTC() initial_date = AbsoluteDate(2004, 1, 1, 23, 30, 00.000, utc) # Setup orbit propagator # gravitation coefficient mu = 3.986004415e+14 # Orbit construction as Keplerian initialOrbit = KeplerianOrbit(a, e, i, omega, raan, lM, PositionAngle.MEAN, inertialFrame, initial_date, mu) initial_state = SpacecraftState(initialOrbit) # use a numerical propogator min_step = 0.001 max_step = 1000.0 position_tolerance = 10.0 propagation_type = OrbitType.KEPLERIAN tolerances = NumericalPropagator.tolerances(position_tolerance, initialOrbit, propagation_type) integrator = DormandPrince853Integrator(min_step, max_step, 1e-5, 1e-10) propagator = NumericalPropagator(integrator) propagator.setOrbitType(propagation_type) # force model gravity field provider = GravityFieldFactory.getNormalizedProvider(10, 10) holmesFeatherstone = HolmesFeatherstoneAttractionModel( FramesFactory.getITRF(IERSConventions.IERS_2010, True), provider) # SRP # ssc = IsotropicRadiationSingleCoefficient(100.0, 0.8) # Spacecraft surface area (m^2), C_r absorbtion # srp = SolarRadiationPressure(CelestialBodyFactory.getSun(), a, ssc) # sun, semi-major Earth, spacecraft sensitivity propagator.addForceModel(holmesFeatherstone) # propagator.addForceModel(ThirdBodyAttraction(CelestialBodyFactory.getSun())) # propagator.addForceModel(ThirdBodyAttraction(CelestialBodyFactory.getMoon())) # propagator.addForceModel(srp) propagator.setMasterMode(60.0, TutorialStepHandler()) propagator.setInitialState(initial_state) # propagator.setEphemerisMode() finalstate = propagator.propagate(initial_date.shiftedBy( 10. * 24 * 60**2)) # TIme shift in seconds
class Environment(): """ Simulation environment. This environment is used to propagate trajectories and render images at each simulation step. """ def __init__(self, res_dir, starcat_dir, instrument, with_infobox, with_clipping, sssb, sun, lightref, encounter_date, duration, frames, encounter_distance, relative_velocity, with_sunnyside, with_terminator, timesampler_mode, slowmotion_factor, exposure, samples, device, tile_size, ext_logger=None): if ext_logger is not None: self.logger = ext_logger else: self.logger = utils.create_logger() self.root_dir = Path(__file__).parent.parent.parent data_dir = self.root_dir / "data" self.models_dir = utils.check_dir(data_dir / "models") self.res_dir = res_dir self.starcat_dir = starcat_dir self.inst = Instrument(instrument) self.ts = TimeScalesFactory.getTDB() self.ref_frame = FramesFactory.getICRF() self.mu_sun = Constants.IAU_2015_NOMINAL_SUN_GM encounter_date = encounter_date self.encounter_date = AbsoluteDate(int(encounter_date["year"]), int(encounter_date["month"]), int(encounter_date["day"]), int(encounter_date["hour"]), int(encounter_date["minutes"]), float(encounter_date["seconds"]), self.ts) self.duration = duration self.start_date = self.encounter_date.shiftedBy(-self.duration / 2.) self.end_date = self.encounter_date.shiftedBy(self.duration / 2.) self.frames = frames self.minimum_distance = encounter_distance self.relative_velocity = relative_velocity self.with_terminator = bool(with_terminator) self.with_sunnyside = bool(with_sunnyside) self.timesampler_mode = timesampler_mode self.slowmotion_factor = slowmotion_factor self.render_settings = dict() self.render_settings["exposure"] = exposure self.render_settings["samples"] = samples self.render_settings["device"] = device self.render_settings["tile"] = tile_size self.sssb_settings = sssb self.with_infobox = with_infobox self.with_clipping = with_clipping # Setup rendering engine (renderer) self.setup_renderer() # Setup Sun self.setup_sun(sun) # Setup SSSB self.setup_sssb(sssb) # Setup SC self.setup_spacecraft() # Setup Lightref self.setup_lightref(lightref) def setup_renderer(self): """Create renderer, apply common settings and create sc cam.""" render_dir = utils.check_dir(self.res_dir) raw_dir = utils.check_dir(render_dir / "raw") self.renderer = render.BlenderController(render_dir, raw_dir, self.starcat_dir, self.inst, self.sssb_settings, self.with_infobox, self.with_clipping, ext_logger=self.logger) self.renderer.create_camera("ScCam") self.renderer.configure_camera("ScCam", self.inst.focal_l, self.inst.chip_w) self.renderer.create_scene("SssbConstDist") self.renderer.create_camera("SssbConstDistCam", scenes="SssbConstDist") self.renderer.configure_camera("SssbConstDistCam", self.inst.focal_l, self.inst.chip_w) self.renderer.create_scene("LightRef") self.renderer.create_camera("LightRefCam", scenes="LightRef") self.renderer.configure_camera("LightRefCam", self.inst.focal_l, self.inst.chip_w) self.renderer.set_device(self.render_settings["device"], self.render_settings["tile"]) self.renderer.set_samples(self.render_settings["samples"]) self.renderer.set_exposure(self.render_settings["exposure"]) self.renderer.set_resolution(self.inst.res) self.renderer.set_output_format() def setup_sun(self, settings): """Create Sun and respective render object.""" sun_model_file = Path(settings["model"]["file"]) try: sun_model_file = sun_model_file.resolve() except OSError as e: raise SimulationError(e) if not sun_model_file.is_file(): sun_model_file = self.models_dir / sun_model_file.name sun_model_file = sun_model_file.resolve() if not sun_model_file.is_file(): raise SimulationError("Given SSSB model filename does not exist.") self.sun = CelestialBody(settings["model"]["name"], model_file=sun_model_file) self.sun.render_obj = self.renderer.load_object( self.sun.model_file, self.sun.name) def setup_sssb(self, settings): """Create SmallSolarSystemBody and respective blender object.""" sssb_model_file = Path(settings["model"]["file"]) try: sssb_model_file = sssb_model_file.resolve() except OSError as e: raise SimulationError(e) if not sssb_model_file.is_file(): sssb_model_file = self.models_dir / sssb_model_file.name sssb_model_file = sssb_model_file.resolve() if not sssb_model_file.is_file(): raise SimulationError("Given SSSB model filename does not exist.") self.sssb = SmallSolarSystemBody(settings["model"]["name"], self.mu_sun, settings["trj"], settings["att"], model_file=sssb_model_file) self.sssb.render_obj = self.renderer.load_object( self.sssb.model_file, settings["model"]["name"], ["SssbOnly", "SssbConstDist"]) self.sssb.render_obj.rotation_mode = "AXIS_ANGLE" def setup_spacecraft(self): """Create Spacecraft and respective blender object.""" sssb_state = self.sssb.get_state(self.encounter_date) sc_state = Spacecraft.calc_encounter_state(sssb_state, self.minimum_distance, self.relative_velocity, self.with_terminator, self.with_sunnyside) self.spacecraft = Spacecraft("CI", self.mu_sun, sc_state, self.encounter_date) def setup_lightref(self, settings): """Create lightreference blender object.""" lightref_model_file = Path(settings["model"]["file"]) try: lightref_model_file = lightref_model_file.resolve() except OSError as e: raise SimulationError(e) if not lightref_model_file.is_file(): lightref_model_file = self.models_dir / lightref_model_file.name lightref_model_file = lightref_model_file.resolve() if not lightref_model_file.is_file(): raise SimulationError("Given SSSB model filename does not exist.") self.lightref = self.renderer.load_object(lightref_model_file, settings["model"]["name"], scenes="LightRef") self.lightref.location = (0, 0, 0) def simulate(self): """Do simulation.""" self.logger.debug("Starting simulation") self.logger.debug("Propagating SSSB") self.sssb.propagate(self.start_date, self.end_date, self.frames, self.timesampler_mode, self.slowmotion_factor) self.logger.debug("Propagating Spacecraft") self.spacecraft.propagate(self.start_date, self.end_date, self.frames, self.timesampler_mode, self.slowmotion_factor) self.logger.debug("Simulation completed") self.save_results() def set_rotation(self, sssb_rot, sispoObj): """Set rotation and returns original transformation matrix""" """Assumes that the blender scaling is set to 1""" #sssb_axis = sssb_rot.getAxis(self.sssb.rot_conv) sssb_angle = sssb_rot.getAngle() eul0 = mathutils.Euler((0.0, 0.0, sssb_angle), 'XYZ') eul1 = mathutils.Euler((0.0, sispoObj.Dec, 0.0), 'XYZ') eul2 = mathutils.Euler((0.0, 0.0, sispoObj.RA), 'XYZ') R0 = eul0.to_matrix() R1 = eul1.to_matrix() R2 = eul2.to_matrix() M = R2 @ R1 @ R0 original_transform = sispoObj.render_obj.matrix_world sispoObj.render_obj.matrix_world = M.to_4x4() return original_transform def render(self): """Render simulation scenario.""" self.logger.debug("Rendering simulation") # Render frame by frame for (date, sc_pos, sssb_pos, sssb_rot) in zip(self.spacecraft.date_history, self.spacecraft.pos_history, self.sssb.pos_history, self.sssb.rot_history): date_str = datetime.strptime(date.toString(), "%Y-%m-%dT%H:%M:%S.%f") date_str = date_str.strftime("%Y-%m-%dT%H%M%S-%f") # metadict creation metainfo = dict() metainfo["sssb_pos"] = np.asarray(sssb_pos.toArray()) metainfo["sc_pos"] = np.asarray(sc_pos.toArray()) metainfo["distance"] = sc_pos.distance(sssb_pos) metainfo["date"] = date_str self.set_rotation(sssb_rot, self.sssb) # Update environment self.sun.render_obj.location = -np.asarray( sssb_pos.toArray()) / 1000. # Update sssb and spacecraft pos_sc_rel_sssb = np.asarray( sc_pos.subtract(sssb_pos).toArray()) / 1000. self.renderer.set_camera_location("ScCam", pos_sc_rel_sssb) self.renderer.target_camera(self.sssb.render_obj, "ScCam") # Update scenes/cameras pos_cam_const_dist = pos_sc_rel_sssb * 1000. / np.sqrt( np.dot(pos_sc_rel_sssb, pos_sc_rel_sssb)) self.renderer.set_camera_location("SssbConstDistCam", pos_cam_const_dist) self.renderer.target_camera(self.sssb.render_obj, "SssbConstDistCam") lightrefcam_pos = -np.asarray( sssb_pos.toArray()) * 1000. / np.sqrt( np.dot(np.asarray(sssb_pos.toArray()), np.asarray(sssb_pos.toArray()))) self.renderer.set_camera_location("LightRefCam", lightrefcam_pos) self.renderer.target_camera(self.sun.render_obj, "CalibrationDisk") self.renderer.target_camera(self.lightref, "LightRefCam") # Render blender scenes self.renderer.render(metainfo) self.logger.debug("Rendering completed") def save_results(self): """Save simulation results to a file.""" self.logger.debug("Saving propagation results") print_list = [] print_list.append([self.spacecraft.date_history, "date"]) print_list.append([self.spacecraft.pos_history, "vector"]) print_list.append([self.spacecraft.vel_history, "vector"]) #print_list.append([self.spacecraft.rot_history,False]) print_list.append([self.sssb.pos_history, "vector"]) print_list.append([self.sssb.vel_history, "vector"]) #print_list.append([self.sssb.rot_history,False]) float_formatter = "{:.16f}".format np.set_printoptions(formatter={'float_kind': float_formatter}) with open(str(self.res_dir / "DynamicsHistory.txt"), "w+") as file: for i in range(0, len(self.spacecraft.date_history)): line = "" sepr = "\t" for history in print_list: if (history[1] == "date"): value = history[0][i] elif (history[1] == "vector"): value = np.asarray(history[0][i].toArray()) line = line + str(value) + sepr line = line + "\n" file.write(line) self.logger.debug("Propagation results saved")