From 9e70ace4b7bc687507b14b6e1c8b31dcbd9e2036 Mon Sep 17 00:00:00 2001 From: "Timur A. Fatkhullin" Date: Wed, 12 Mar 2025 17:43:17 +0300 Subject: [PATCH] ... --- cxx/CMakeLists.txt | 11 +++- cxx/mount.h | 55 ++++++++++++++++ cxx/mount_astrom.h | 131 ++++++++++++++++++++++++++------------ cxx/tests/astrom_test.cpp | 3 +- 4 files changed, 156 insertions(+), 44 deletions(-) diff --git a/cxx/CMakeLists.txt b/cxx/CMakeLists.txt index 69ddf8b..fb4ff83 100644 --- a/cxx/CMakeLists.txt +++ b/cxx/CMakeLists.txt @@ -7,6 +7,9 @@ set(CMAKE_CXX_STANDARD_REQUIRED ON) set(CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_SOURCE_DIR}/cmake") +option(USE_XSIMD "Use of XSIMD library to generate vectorized code" ON) + + find_package(ASIO QUIET) if (ASIO_FOUND) # message(STATUS "ASIO library was found") @@ -69,6 +72,12 @@ endif() add_compile_definitions(SPDLOG_USE_STD_FORMAT) add_compile_definitions(SPDLOG_FMT_EXTERNAL=0) +if (USE_XSIMD) + # fetch XSIMD library + add_compile_definitions(VEC_XSIMD) +endif() + + option(WITH_TESTS "Build tests" ON) # Mount client-to-server communication protocol @@ -85,7 +94,7 @@ set(CNTR_PROTO_LIB_SRC set(CNTR_PROTO_LIB comm_proto) add_library(${CNTR_PROTO_LIB} STATIC ${CNTR_PROTO_LIB_SRC}) -set(MOUNT_SERVER_APP_SRC mount.h mount_server.cpp comm_server.h comm_server_endpoint.h) +set(MOUNT_SERVER_APP_SRC mount.h mount_server.cpp comm_server.h comm_server_endpoint.h mount_astrom.h) set(MOUNT_SERVER_APP mount_server) add_executable(${MOUNT_SERVER_APP} ${MOUNT_SERVER_APP_SRC} comm_server_configfile.h) diff --git a/cxx/mount.h b/cxx/mount.h index bc2cb2a..8ef7feb 100644 --- a/cxx/mount.h +++ b/cxx/mount.h @@ -10,6 +10,7 @@ #include #include "spdlog/sinks/null_sink.h" +#include "mount_astrom.h" // low-level functions namespace lowlevel @@ -35,6 +36,60 @@ concept mcc_mount_state_c = requires(T t, const T t_const) { }; +class MccMountPosition +{ +public: + typedef double mnt_coord_t; + typedef double mnt_speed_t; + typedef double time_point_t; + + // time-related + std::chrono::system_clock::time_point utc; + time_point_t mjd; // modified Julian date + time_point_t ut1; + time_point_t tt; + time_point_t siderTime; // sideral time (in radians) + + // apparent target (user-input) current coordinates (in radians) + mnt_coord_t tagRA, tagDEC; + mnt_coord_t tagHA; + mnt_coord_t tagAZ, tagZD; + + // encoder-measured current mount coordinates (in radians) + mnt_coord_t mntRA, mntDEC; + mnt_coord_t mntHA; + mnt_coord_t mntAZ, mntZD; + + // encoder-measured current mount moving speed (in radians/s) + mnt_speed_t mntSpeedX, + mntSpeedY; // X - HA, Y - DEC for equatorial-type mount; X - AZ, Y - ZD for horizontal-type one + + // current refraction coefficient + mnt_coord_t currRefr; + + // PCS (pointing correction system) corrections + mnt_coord_t pcsX, pcsY; // X - HA, Y - DEC for equatorial-type mount; X - AZ, Y - ZD for horizontal-type one + + bool update(const std::chrono::system_clock::time_point& utc_time) + { + // + + astro::mcc_julday(utc_time, mjd); + + return true; + } + +protected: + bool updateTime(const std::chrono::system_clock::time_point& utc_time) + { + // UTC to TAI + double tai; + + return true; + } +}; + + // implements a Finite State Machine Pattern template diff --git a/cxx/mount_astrom.h b/cxx/mount_astrom.h index ddc11fb..112dec2 100644 --- a/cxx/mount_astrom.h +++ b/cxx/mount_astrom.h @@ -19,6 +19,10 @@ template concept mcc_scalar_or_simd_c = xsimd::is_batch::value || std::is_arithmetic_v; +template +concept mcc_real_scalar_or_real_range_c = + std::floating_point || std::ranges::output_range || std::ranges::output_range; + template concept mcc_real_or_char_range = std::floating_point || @@ -31,13 +35,17 @@ namespace mcc::astro { // modified Julian date (based on ERFA eraCal2jd) -// template +template static int mcc_julday(const std::chrono::system_clock::time_point& start_time, - const std::chrono::system_clock::duration& step, - std::vector>& mjd) + ResT& mjd, + const std::chrono::system_clock::duration& step = std::chrono::milliseconds(100)) { - if (mjd.empty()) { - return -100; + size_t mjd_size = 0; + if constexpr (std::ranges::range) { + mjd_size = std::ranges::distance(mjd.begin(), mjd.end()); + if (!mjd_size) { + return -100; + } } using namespace std::literals::chrono_literals; @@ -74,27 +82,52 @@ static int mcc_julday(const std::chrono::system_clock::time_point& start_time, double mjd_float = static_cast(mjd_int) + std::chrono::duration_cast(start_time - dd).count() * nanosec; - double d_step = std::chrono::duration_cast(step).count() * nanosec; - constexpr size_t reg_size = xsimd::batch::size; - size_t vec_size = mjd.size() - mjd.size() % reg_size; + if constexpr (std::ranges::range) { + double d_step = std::chrono::duration_cast(step).count() * nanosec; - xsimd::batch res_reg{mjd_float}; - xsimd::batch step_reg = [d_step](std::index_sequence) { - return xsimd::batch{(Is * d_step)...}; - }(std::make_index_sequence{}); + size_t i = 0; - // vectorized part - size_t i = 0; - for (; i < vec_size; i += vec_size) { - res_reg += step_reg; +#ifdef VEC_XSIMD + constexpr size_t reg_size = xsimd::batch::size; + size_t vec_size = mjd_size - mjd_size % reg_size; - res_reg.store_aligned(mjd.data() + i); - } + xsimd::batch res_reg{mjd_float}; + xsimd::batch step_reg = [d_step](std::index_sequence) { + return xsimd::batch{(Is * d_step)...}; + }(std::make_index_sequence{}); - // scalar part - for (size_t j = i; j < mjd.size(); ++j) { - mjd[j] = mjd_float + j * d_step; + alignas(xsimd::batch::arch_type::alignment()) double arr[reg_size]; + + auto ptr = mjd.begin(); + + // vectorized part + for (; i < vec_size; i += vec_size) { + res_reg += step_reg; + + if constexpr (std::ranges::contiguous_range) { + res_reg.store_unaligned(mjd.data() + i); + // res_reg.store_aligned(mjd.data() + i); + } else { + res_reg.store_aligned(arr); + std::ranges::copy(arr, ptr); + + if constexpr (std::ranges::random_access_range) { + ptr += reg_size; + } else { + for (int k = 0; k < reg_size; ++k) { + ++ptr; + } + } + } + } +#endif + // scalar part + for (size_t j = i; j < mjd_size; ++j, ++ptr) { + *ptr = mjd_float + j * d_step; + } + } else { // result is scalar + mjd = mjd_float; } @@ -174,7 +207,29 @@ struct leapsecond_db_elem_t { double tai_utc; // TAI-UTC in seconds }; -typedef std::vector leapsecond_db_t; +// typedef std::vector leapsecond_db_t; + +struct leapsecond_db_t { + std::chrono::system_clock::time_point expireDate; + std::vector db; +}; + + +// init to some known state +static leapsecond_db_t CURRENT_LEAPSECONDS_DB; +// = { +// {41317.0, 1, 1, 1972, 10}, {41499.0, 1, 7, 1972, 11}, {41683.0, 1, 1, 1973, 12}, +// {42048.0, 1, 1, 1974, 13}, {42413.0, 1, 1, 1975, 14}, {42778.0, 1, 1, 1976, 15}, +// {43144.0, 1, 1, 1977, 16}, {43509.0, 1, 1, 1978, 17}, {43874.0, 1, 1, 1979, 18}, +// {44239.0, 1, 1, 1980, 19}, {44786.0, 1, 7, 1981, 20}, {45151.0, 1, 7, 1982, 21}, +// {45516.0, 1, 7, 1983, 22}, {46247.0, 1, 7, 1985, 23}, {47161.0, 1, 1, 1988, 24}, +// {47892.0, 1, 1, 1990, 25}, {48257.0, 1, 1, 1991, 26}, {48804.0, 1, 7, 1992, 27}, +// {49169.0, 1, 7, 1993, 28}, {49534.0, 1, 7, 1994, 29}, {50083.0, 1, 1, 1996, 30}, +// {50630.0, 1, 7, 1997, 31}, {51179.0, 1, 1, 1999, 32}, {53736.0, 1, 1, 2006, 33}, +// {54832.0, 1, 1, 2009, 34}, {56109.0, 1, 7, 2012, 35}, {57204.0, 1, 7, 2015, 36}, +// {57754.0, 1, 1, 2017, 37} + +// }; struct earth_orient_db_elem_t { @@ -186,27 +241,11 @@ struct earth_orient_db_elem_t { }; -// typedef std::vector earth_orient_db_t; struct earth_orient_db_t { std::chrono::system_clock::time_point bulletinDate{}; std::vector db{}; }; -// init to some known state -static leapsecond_db_t CURRENT_LEAPSECONDS_DB = { - {41317.0, 1, 1, 1972, 10}, {41499.0, 1, 7, 1972, 11}, {41683.0, 1, 1, 1973, 12}, - {42048.0, 1, 1, 1974, 13}, {42413.0, 1, 1, 1975, 14}, {42778.0, 1, 1, 1976, 15}, - {43144.0, 1, 1, 1977, 16}, {43509.0, 1, 1, 1978, 17}, {43874.0, 1, 1, 1979, 18}, - {44239.0, 1, 1, 1980, 19}, {44786.0, 1, 7, 1981, 20}, {45151.0, 1, 7, 1982, 21}, - {45516.0, 1, 7, 1983, 22}, {46247.0, 1, 7, 1985, 23}, {47161.0, 1, 1, 1988, 24}, - {47892.0, 1, 1, 1990, 25}, {48257.0, 1, 1, 1991, 26}, {48804.0, 1, 7, 1992, 27}, - {49169.0, 1, 7, 1993, 28}, {49534.0, 1, 7, 1994, 29}, {50083.0, 1, 1, 1996, 30}, - {50630.0, 1, 7, 1997, 31}, {51179.0, 1, 1, 1999, 32}, {53736.0, 1, 1, 2006, 33}, - {54832.0, 1, 1, 2009, 34}, {56109.0, 1, 7, 2012, 35}, {57204.0, 1, 7, 2015, 36}, - {57754.0, 1, 1, 2017, 37} - -}; - static earth_orient_db_t CURRENT_EARTH_ORIENT_DB; @@ -300,13 +339,20 @@ static bool mcc_parse_leapsecs(std::derived_from> auto& leapsecond_db_t db; - // leapsecond_db_elem_t db_elem; for (std::string line; std::getline(stream, line);) { auto sv = utils::trimSpaces(line, utils::TrimType::TRIM_LEFT); if (sv.size()) { if (sv[0] == comment_sym) { // comment string + if (std::regex_match(line, expr_date_rx)) { + auto pos = line.find("on"); + sv = utils::trimSpaces(std::string_view{line.begin() + pos + 2, line.end()}, + utils::TrimType::TRIM_LEFT); + is.str({sv.begin(), sv.end()}); + is >> std::chrono::parse("%d %B %Y", db.expireDate); + is.clear(); + } continue; } } else { @@ -314,14 +360,15 @@ static bool mcc_parse_leapsecs(std::derived_from> auto& } if (std::regex_match(line, data_rx)) { - is.str(std::move(line)); + is.str(line); is >> mjd >> day >> month >> year >> tai_utc; - db.emplace_back(mjd, day, month, year, tai_utc); + db.db.emplace_back(mjd, day, month, year, tai_utc); is.clear(); + continue; } } - if (db.empty()) { + if (db.db.empty()) { return false; } diff --git a/cxx/tests/astrom_test.cpp b/cxx/tests/astrom_test.cpp index 7b11987..a234c8a 100644 --- a/cxx/tests/astrom_test.cpp +++ b/cxx/tests/astrom_test.cpp @@ -89,7 +89,8 @@ int main(int argc, char* argv[]) ecode = 1; } else { std::cout << "IERS leap seconds data:\n"; - for (auto& el : mcc::astro::CURRENT_LEAPSECONDS_DB) { + std::cout << "Expire date: " << mcc::astro::CURRENT_LEAPSECONDS_DB.expireDate << "\n"; + for (auto& el : mcc::astro::CURRENT_LEAPSECONDS_DB.db) { std::cout << "MJD: " << el.mjd << "\tTAI-UTC = " << el.tai_utc << "\n"; } }