diff --git a/tudatpy/kernel/expose_io.cpp b/tudatpy/kernel/expose_io.cpp index 240a4f97..7185d47f 100644 --- a/tudatpy/kernel/expose_io.cpp +++ b/tudatpy/kernel/expose_io.cpp @@ -14,10 +14,14 @@ #include "tudat/io/readHistoryFromFile.h" #include "tudat/io/missileDatcomData.h" +#include "tudat/io/solarActivityData.h" +#include "tudat/io/readOdfFile.h" +#include "tudat/io/readTabulatedWeatherData.h" #include namespace py = pybind11; +namespace tio = tudat::input_output; namespace tudatpy { @@ -145,6 +149,38 @@ void expose_io(py::module &m) { .value("clb", tudat::input_output::MissileDatcomData::StaticCoefficientNames::clb, get_docstring("StaticCoefficientNames.clb").c_str()) .export_values(); + py::class_< + tio::solar_activity::SolarActivityData, + std::shared_ptr< tio::solar_activity::SolarActivityData > >( + m, "SolarActivityData", get_docstring("SolarActivityData").c_str() ); + + py::class_< + tio::OdfRawFileContents, + std::shared_ptr< tio::OdfRawFileContents > >( + m, "OdfRawFileContents", get_docstring("OdfRawFileContents").c_str( ) ) + .def("write_to_text_file", + &tio::OdfRawFileContents::writeOdfToTextFile, + py::arg("output_file"), + get_docstring("OdfRawFileContents.write_to_text_file").c_str() ); + + m.def("read_odf_file", + &tio::readOdfFile, + py::arg( "file_name" ), + get_docstring("read_odf_file").c_str() ); + + m.def("set_dsn_weather_data_in_ground_stations", + py::overload_cast< + tudat::simulation_setup::SystemOfBodies&, + const std::vector< std::string >&, + std::shared_ptr< tudat::interpolators::InterpolatorSettings >, + const std::map< int, std::vector< std::string > >&, + const std::string& >( &tio::setDsnWeatherDataInGroundStations ), + py::arg( "bodies" ), + py::arg( "weather_file_names" ), + py::arg( "interpolator_settings" ) = tudat::interpolators::linearInterpolation( ), + py::arg( "ground_stations_per_complex" ) = tudat::simulation_setup::getDefaultDsnStationNamesPerComplex( ), + py::arg( "body_with_ground_stations_name" ) = "Earth", + get_docstring("set_dsn_weather_data_in_ground_stations").c_str() ); }; }// namespace io diff --git a/tudatpy/kernel/expose_numerical_simulation/expose_environment_setup.cpp b/tudatpy/kernel/expose_numerical_simulation/expose_environment_setup.cpp index 01e07536..5c4072ce 100644 --- a/tudatpy/kernel/expose_numerical_simulation/expose_environment_setup.cpp +++ b/tudatpy/kernel/expose_numerical_simulation/expose_environment_setup.cpp @@ -172,7 +172,7 @@ namespace environment_setup { m.def("create_ground_station_ephemeris", py::overload_cast< const std::shared_ptr< tss::Body >, const std::string& >( - &tss::createReferencePointEphemeris ), + &tss::createReferencePointEphemeris< TIME_TYPE, double > ), py::arg("body"), py::arg("station_name") ); diff --git a/tudatpy/kernel/expose_numerical_simulation/expose_estimation.cpp b/tudatpy/kernel/expose_numerical_simulation/expose_estimation.cpp index 946cb1ee..ce178e16 100644 --- a/tudatpy/kernel/expose_numerical_simulation/expose_estimation.cpp +++ b/tudatpy/kernel/expose_numerical_simulation/expose_estimation.cpp @@ -343,6 +343,8 @@ void expose_estimation(py::module &m) { get_docstring("ObservationCollection.observation_vector_size").c_str() ) .def_property_readonly("sorted_observation_sets", &tom::ObservationCollection::getSortedObservationSets, get_docstring("ObservationCollection.sorted_observation_sets").c_str() ) + .def_property_readonly("link_ends_per_observable_type", &tom::ObservationCollection::getLinkEndsPerObservableType, + get_docstring("ObservationCollection.link_ends_per_observable_type").c_str() ) .def("get_single_link_and_type_observations", &tom::ObservationCollection::getSingleLinkAndTypeObservationSets, py::arg( "observable_type" ), py::arg( "link_definition" ), @@ -635,7 +637,10 @@ void expose_estimation(py::module &m) { get_docstring("EstimationOutput.simulation_results_per_iteration").c_str() ) .def_readonly("final_residuals", &tss::EstimationOutput::residuals_, - get_docstring("EstimationOutput.final_residuals").c_str() ); + get_docstring("EstimationOutput.final_residuals").c_str() ) + .def_readonly("best_iteration", + &tss::EstimationOutput::bestIteration_, + get_docstring("EstimationOutput.best_iteration").c_str() ); m.attr("PodOutput") = m.attr("EstimationOutput"); diff --git a/tudatpy/kernel/expose_numerical_simulation/expose_estimation_setup/expose_observation_setup.cpp b/tudatpy/kernel/expose_numerical_simulation/expose_estimation_setup/expose_observation_setup.cpp index a0771c29..c4466493 100644 --- a/tudatpy/kernel/expose_numerical_simulation/expose_estimation_setup/expose_observation_setup.cpp +++ b/tudatpy/kernel/expose_numerical_simulation/expose_estimation_setup/expose_observation_setup.cpp @@ -8,17 +8,21 @@ * http://tudat.tudelft.nl/LICENSE. */ +#include + #include "expose_observation_setup.h" #include "tudat/simulation/estimation_setup/simulateObservations.h" #include "tudat/simulation/estimation_setup/createObservationModel.h" #include "tudat/simulation/estimation_setup/observationSimulationSettings.h" +#include "tudat/simulation/estimation_setup/processOdfFile.h" #include "tudatpy/docstrings.h" #include "tudatpy/scalarTypes.h" namespace tss = tudat::simulation_setup; namespace tom = tudat::observation_models; +namespace tuc = tudat::unit_conversions; namespace tudat { @@ -241,6 +245,8 @@ void expose_observation_setup(py::module &m) { .value("two_way_instantaneous_doppler_type", tom::ObservableType::two_way_doppler ) .value("n_way_averaged_doppler_type", tom::ObservableType::n_way_differenced_range ) .value("euler_angle_313_observable_type", tom::ObservableType::euler_angle_313_observable ) + .value("dsn_one_way_averaged_doppler", tom::ObservableType::dsn_one_way_averaged_doppler ) + .value("dsn_n_way_averaged_doppler", tom::ObservableType::dsn_n_way_averaged_doppler ) .export_values(); @@ -441,13 +447,33 @@ void expose_observation_setup(py::module &m) { py::overload_cast< const std::vector< std::shared_ptr< tom::ObservationModelSettings > >, const std::shared_ptr< tom::ObservationBiasSettings >, - const std::shared_ptr< tom::LightTimeConvergenceCriteria > >( - &tom::nWayDifferencedRangeObservationSettings ), + const std::shared_ptr< tom::LightTimeConvergenceCriteria > >( &tom::nWayDifferencedRangeObservationSettings ), py::arg("one_way_range_settings" ), py::arg("bias_settings") = nullptr, - py::arg("light_time_convergence_settings") = nullptr, + py::arg("light_time_convergence_settings") = std::make_shared< tom::LightTimeConvergenceCriteria >( ), get_docstring("n_way_doppler_averaged_from_one_way_links").c_str() ); + m.def("dsn_n_way_doppler_averaged", + py::overload_cast< + const tom::LinkDefinition&, + const std::vector< std::shared_ptr< tom::LightTimeCorrectionSettings > >, + const std::shared_ptr< tom::ObservationBiasSettings >, + const std::shared_ptr< tom::LightTimeConvergenceCriteria > >( &tom::dsnNWayAveragedDopplerObservationSettings ), + py::arg("link_ends" ), + py::arg("light_time_correction_settings" ) = std::vector< std::shared_ptr< tom::LightTimeCorrectionSettings > >( ), + py::arg("bias_settings") = nullptr, + py::arg("light_time_convergence_settings") = std::make_shared< tom::LightTimeConvergenceCriteria >( ), + get_docstring("dsn_n_way_doppler_averaged").c_str() ); + + m.def("dsn_n_way_doppler_averaged_from_one_way_links", + py::overload_cast< + const std::vector< std::shared_ptr< tom::ObservationModelSettings > >, + const std::shared_ptr< tom::ObservationBiasSettings >, + const std::shared_ptr< tom::LightTimeConvergenceCriteria > >( &tom::dsnNWayAveragedDopplerObservationSettings ), + py::arg("one_way_range_settings" ), + py::arg("bias_settings") = nullptr, + py::arg("light_time_convergence_settings") = std::make_shared< tom::LightTimeConvergenceCriteria >( ), + get_docstring("dsn_n_way_doppler_averaged_from_one_way_links").c_str() ); py::class_>( @@ -459,6 +485,61 @@ void expose_observation_setup(py::module &m) { py::arg("perturbing_bodies"), get_docstring("first_order_relativistic_light_time_correction").c_str() ); + py::enum_< tom::TroposphericMappingModel >(m, "TroposphericMappingModel", + get_docstring("TroposphericMappingModel").c_str() ) + .value("simplified_chao", tom::TroposphericMappingModel::simplified_chao ) + .value("niell", tom::TroposphericMappingModel::niell ) + .export_values(); + + py::enum_< tom::WaterVaporPartialPressureModel >(m, "WaterVaporPartialPressureModel", + get_docstring("WaterVaporPartialPressureModel").c_str() ) + .value("tabulated", tom::WaterVaporPartialPressureModel::tabulated ) + .value("bean_and_dutton", tom::WaterVaporPartialPressureModel::bean_and_dutton ) + .export_values(); + + m.def("dsn_tabulated_tropospheric_light_time_correction", + &tom::tabulatedTroposphericCorrectionSettings, + py::arg("file_names"), + py::arg("body_with_atmosphere_name") = "Earth", + py::arg("mapping_model") = tom::TroposphericMappingModel::niell, + get_docstring("dsn_tabulated_tropospheric_light_time_correction").c_str() ); + + m.def("saastamoinen_tropospheric_light_time_correction", + &tom::tabulatedTroposphericCorrectionSettings, + py::arg("body_with_atmosphere_name") = "Earth", + py::arg("mapping_model") = tom::TroposphericMappingModel::niell, + py::arg("water_vapor_partial_pressure_model") = tom::WaterVaporPartialPressureModel::tabulated, + get_docstring("saastamoinen_tropospheric_light_time_correction").c_str() ); + + m.def("dsn_tabulated_ionospheric_light_time_correction", + &tom::tabulatedIonosphericCorrectionSettings, + py::arg("file_names"), + py::arg("spacecraft_name_per_id") = std::map< int, std::string >( ), + py::arg("quasar_name_per_id") = std::map< int, std::string >( ), + py::arg("reference_frequency") = 2295e6, + py::arg("body_with_atmosphere_name") = "Earth", + get_docstring("dsn_tabulated_ionospheric_light_time_correction").c_str() ); + + m.def("jakowski_ionospheric_light_time_correction", + &tom::jakowskiIonosphericCorrectionSettings, + py::arg("ionosphere_height") = 400.0e3, + py::arg("first_order_delay_coefficient") = 40.3, + py::arg("solar_activity_data") = tudat::input_output::solar_activity::readSolarActivityData( + tudat::paths::getSpaceWeatherDataPath( ) + "/sw19571001.txt" ), + py::arg("geomagnetic_pole_latitude") = tuc::convertDegreesToRadians( 80.9 ), + py::arg("geomagnetic_pole_longitude") = tuc::convertDegreesToRadians( -72.6 ), + py::arg("use_utc_for_local_time_computation") = false, + py::arg("body_with_atmosphere_name") = "Earth", + get_docstring("jakowski_ionospheric_light_time_correction").c_str() ); + + m.def("inverse_power_series_solar_corona_light_time_correction", + &tom::inversePowerSeriesSolarCoronaCorrectionSettings, + py::arg("coefficients") = std::vector< double >{ 1.31 * 5.97e-6 }, + py::arg("positive_exponents") = std::vector< double >{ 2.0 }, + py::arg("delay_coefficient") = 40.3, + py::arg("sun_body_name") = "Sun", + get_docstring("inverse_power_series_solar_corona_light_time_correction").c_str() ); + py::class_>( m, "ObservationBiasSettings", @@ -555,6 +636,9 @@ void expose_observation_setup(py::module &m) { get_docstring("ObservationAncilliarySimulationVariable").c_str() ) .value("link_ends_delays", tom::ObservationAncilliarySimulationVariable::link_ends_delays ) .value("doppler_integration_time", tom::ObservationAncilliarySimulationVariable::doppler_integration_time ) + .value("doppler_reference_frequency", tom::ObservationAncilliarySimulationVariable::doppler_reference_frequency ) + .value("frequency_bands", tom::ObservationAncilliarySimulationVariable::frequency_bands ) + .value("reception_reference_frequency_band", tom::ObservationAncilliarySimulationVariable::reception_reference_frequency_band ) .export_values(); py::class_ >( + py::class_< tom::ObservationAncilliarySimulationSettings, + std::shared_ptr< tom::ObservationAncilliarySimulationSettings > >( m, "ObservationAncilliarySimulationSettings", get_docstring("ObservationAncilliarySimulationSettings").c_str() ) .def("get_float_settings", @@ -659,32 +743,41 @@ void expose_observation_setup(py::module &m) { m.def("doppler_ancilliary_settings", - &tom::getAveragedDopplerAncilliarySettings< TIME_TYPE >, + &tom::getAveragedDopplerAncilliarySettings, py::arg("integration_time") = 60.0, get_docstring("doppler_integration_time_settings").c_str() ); m.def("two_way_range_ancilliary_settings", - &tom::getTwoWayRangeAncilliarySettings< TIME_TYPE >, + &tom::getTwoWayRangeAncilliarySettings, py::arg("retransmission_delay") = 0.0, get_docstring("two_way_range_ancilliary_settings").c_str() ); m.def("two_way_doppler_ancilliary_settings", - &tom::getTwoWayAveragedDopplerAncilliarySettings< TIME_TYPE >, + &tom::getTwoWayAveragedDopplerAncilliarySettings, py::arg("integration_time") = 60.0, py::arg("retransmission_delay") = 0.0, get_docstring("two_way_doppler_ancilliary_settings").c_str() ); m.def("n_way_range_ancilliary_settings", - &tom::getNWayRangeAncilliarySettings< TIME_TYPE >, - py::arg("retransmission_delays") = std::vector< double >( ), + &tom::getNWayRangeAncilliarySettings, + py::arg("link_end_delays") = std::vector< double >( ), get_docstring("n_way_range_ancilliary_settings").c_str() ); m.def("n_way_doppler_ancilliary_settings", - &tom::getNWayAveragedDopplerAncilliarySettings< TIME_TYPE >, + &tom::getNWayAveragedDopplerAncilliarySettings, py::arg("integration_time") = 60.0, - py::arg("retransmission_delays") = std::vector< double >( ), + py::arg("link_end_delays") = std::vector< double >( ), get_docstring("n_way_doppler_ancilliary_settings").c_str() ); + m.def("dsn_n_way_doppler_ancilliary_settings", + &tom::getDsnNWayAveragedDopplerAncillarySettings, + py::arg("frequency_bands"), + py::arg("reference_frequency_band"), + py::arg("reference_frequency"), + py::arg("integration_time") = 60.0, + py::arg("link_end_delays") = std::vector< double >( ), + get_docstring("dsn_n_way_doppler_ancilliary_settings").c_str() ); + m.def("tabulated_simulation_settings", &tss::tabulatedObservationSimulationSettings< TIME_TYPE >, py::arg("observable_type"), @@ -886,11 +979,109 @@ void expose_observation_setup(py::module &m) { py::arg("link_ends"), get_docstring("add_dependent_variables_to_observable_for_link_ends").c_str() ); - - - - - + ///////////////////////////////////////////////////////////////////////////////////////////////// + // FREQUENCIES + ///////////////////////////////////////////////////////////////////////////////////////////////// + + py::enum_< tom::FrequencyBands >(m, "FrequencyBands", get_docstring("FrequencyBands").c_str() ) + .value("s_band", tom::FrequencyBands::s_band ) + .value("x_band", tom::FrequencyBands::x_band ) + .value("ka_band", tom::FrequencyBands::ka_band ) + .value("ku_band", tom::FrequencyBands::ku_band ); + + m.def("dsn_default_turnaround_ratios", + &tom::getDsnDefaultTurnaroundRatios, + py::arg("uplink_band"), + py::arg("downlink_band"), + get_docstring("dsn_default_turnaround_ratios").c_str() ); + + m.def("cassini_turnaround_ratios", + &tom::getCassiniTurnaroundRatio, + py::arg("uplink_band"), + py::arg("downlink_band"), + get_docstring("cassini_turnaround_ratios").c_str() ); + + ///////////////////////////////////////////////////////////////////////////////////////////////// + // ODF OBSERVATIONS + ///////////////////////////////////////////////////////////////////////////////////////////////// + + py::class_< tom::ProcessedOdfFileContents, std::shared_ptr< tom::ProcessedOdfFileContents > > + (m, "ProcessedOdfFileContents", get_docstring("ProcessedOdfFileContents").c_str( ) ) + .def_property_readonly("ground_station_names", + &tom::ProcessedOdfFileContents::getGroundStationsNames, + get_docstring("ProcessedOdfFileContents.get_ground_station_names").c_str( ) ) + .def_property_readonly("processed_observable_types", + &tom::ProcessedOdfFileContents::getProcessedObservableTypes, + get_docstring("ProcessedOdfFileContents.get_processed_observable_types").c_str( ) ) + .def_property_readonly("start_and_end_time", + &tom::ProcessedOdfFileContents::getStartAndEndTime, + get_docstring("ProcessedOdfFileContents.get_start_and_end_time").c_str( ) ) + .def_property_readonly("ignored_odf_observable_types", + &tom::ProcessedOdfFileContents::getIgnoredRawOdfObservableTypes, + get_docstring("ProcessedOdfFileContents.get_ignored_odf_observable_types").c_str( ) ) + .def_property_readonly("ignored_ground_stations", + &tom::ProcessedOdfFileContents::getIgnoredGroundStations, + get_docstring("ProcessedOdfFileContents.get_ignored_ground_stations").c_str( ) ) + .def_property_readonly("raw_odf_data", + &tom::ProcessedOdfFileContents::getRawOdfData, + get_docstring("ProcessedOdfFileContents.raw_odf_data").c_str( ) ); + + m.def("process_odf_data_multiple_files", + py::overload_cast< + const std::vector< std::string >&, + const std::string&, + const bool, + const std::map< std::string, Eigen::Vector3d >& >( &tom::processOdfData ), + py::arg("file_names"), + py::arg("spacecraft_name"), + py::arg("verbose") = true, + py::arg("earth_fixed_ground_station_positions") = tss::getApproximateDsnGroundStationPositions( ), + get_docstring("create_odf_observed_observations").c_str() ); + + m.def("process_odf_data_single_file", + py::overload_cast< + const std::string&, + const std::string&, + const bool, + const std::map< std::string, Eigen::Vector3d >& >( &tom::processOdfData ), + py::arg("file_name"), + py::arg("spacecraft_name"), + py::arg("verbose") = true, + py::arg("earth_fixed_ground_station_positions") = tss::getApproximateDsnGroundStationPositions( ), + get_docstring("create_odf_observed_observations").c_str() ); + + // Create wrapper function + py::cpp_function getDsnDefaultTurnaroundRatios_wrapper = + [](tudat::observation_models::FrequencyBands band1, tudat::observation_models::FrequencyBands band2) { + return tom::getDsnDefaultTurnaroundRatios(band1, band2); }; + + m.def("set_odf_information_in_bodies", + &tom::setOdfInformationInBodies, + py::arg("processed_odf_file"), + py::arg("bodies"), + py::arg("body_with_ground_stations_name") = "Earth", + py::arg("turnaround_ratio_function") = getDsnDefaultTurnaroundRatios_wrapper, + get_docstring("set_odf_information_in_bodies").c_str() ); + + m.def("create_odf_observed_observation_collection", + &tom::createOdfObservedObservationCollection< double, TIME_TYPE >, + py::arg("processed_odf_file"), + py::arg("observable_types_to_process") = std::vector< tom::ObservableType >( ), + py::arg("start_and_end_times_to_process") = std::make_pair< TIME_TYPE, TIME_TYPE >( TUDAT_NAN, TUDAT_NAN ), + get_docstring("create_odf_observed_observation_collection").c_str() ); + + m.def("create_odf_observation_simulation_settings_list", + &tom::createOdfObservationSimulationSettingsList< double, TIME_TYPE >, + py::arg("observed_observation_collection"), + get_docstring("create_odf_observation_simulation_settings_list").c_str() ); + + m.def("change_simulation_settings_observable_types", + &tom::changeObservableTypesOfObservationSimulationSettings< double, TIME_TYPE >, + py::arg("observation_simulation_settings"), + py::arg("replacement_observable_types") = std::map< tom::ObservableType, tom::ObservableType >{ + { tom::dsn_n_way_averaged_doppler, tom::n_way_differenced_range }, + { tom::dsn_one_way_averaged_doppler, tom::one_way_differenced_range } }, + get_docstring("change_simulation_settings_observable_types").c_str() ); //////////////////////////////////////////// DEPRECATED ////////////////////////////////////////////