This commit is contained in:
Timur A. Fatkhullin
2026-02-06 00:09:15 +03:00
parent 6352865610
commit 97b908838c
5 changed files with 269 additions and 46 deletions

277
mcc_ser.h
View File

@@ -158,8 +158,10 @@ template <typename VT>
struct MccSerializer : MccSerializerBase {
constexpr static std::string_view serializerName{"MCC-FALLBACK-SERIALIZER"};
template <typename ParamsT = std::nullptr_t>
error_t operator()(traits::mcc_output_char_range auto& output, VT const& value, ParamsT const& params = nullptr)
template <typename ParamsT = mcc_serialization_params_t>
error_t operator()(traits::mcc_output_char_range auto& output,
VT const& value,
ParamsT const& params = mcc_serialization_params_t{})
{
if constexpr (std::formattable<VT, char>) {
} else if constexpr (std::convertible_to<VT, std::string>) {
@@ -205,8 +207,10 @@ struct MccSerializer<VT> : MccSerializerBase {
constexpr static std::string_view serializerName{"MCC-SYSTIME-SERIALIZER"};
template <typename ParamsT = std::nullptr_t>
error_t operator()(traits::mcc_output_char_range auto& output, VT const& value, ParamsT const& params = nullptr)
template <typename ParamsT = mcc_serialization_params_t>
error_t operator()(traits::mcc_output_char_range auto& output,
VT const& value,
ParamsT const& params = mcc_serialization_params_t{})
{
std::vformat_to(std::back_inserter(output), params.systime_format, std::make_format_args(value));
@@ -220,8 +224,10 @@ template <typename VT>
struct MccSerializer<VT> : MccSerializerBase {
constexpr static std::string_view serializerName{"MCC-ANGLE-SERIALIZER"};
template <typename ParamsT = std::nullptr_t>
error_t operator()(traits::mcc_output_char_range auto& output, VT const& value, ParamsT const& params = nullptr)
template <typename ParamsT = mcc_serialization_params_t>
error_t operator()(traits::mcc_output_char_range auto& output,
VT const& value,
ParamsT const& params = mcc_serialization_params_t{})
{
double v = (double)value; // radians (see mcc_angle_c concept)
std::string sgm;
@@ -264,8 +270,10 @@ template <mcc_coord_epoch_c VT>
struct MccSerializer<VT> : MccSerializerBase {
constexpr static std::string_view serializerName{"MCC-COORD-EPOCH-SERIALIZER"};
template <typename ParamsT = std::nullptr_t>
error_t operator()(traits::mcc_output_char_range auto& output, VT const& value, ParamsT const& params = nullptr)
template <typename ParamsT = mcc_serialization_params_t>
error_t operator()(traits::mcc_output_char_range auto& output,
VT const& value,
ParamsT const& params = mcc_serialization_params_t{})
{
double jd;
@@ -304,11 +312,12 @@ template <mcc_coord_pair_c VT>
struct MccSerializer<VT> : MccSerializerBase {
constexpr static std::string_view serializerName{"MCC-COORD-PAIR-SERIALIZER"};
template <typename ParamsT = std::nullptr_t>
error_t operator()(traits::mcc_output_char_range auto& output, VT const& value, ParamsT const& params = nullptr)
template <typename ParamsT = mcc_serialization_params_t>
error_t operator()(traits::mcc_output_char_range auto& output,
VT const& value,
ParamsT const& params = mcc_serialization_params_t{})
{
std::conditional_t<std::is_null_pointer_v<ParamsT>, std::nullptr_t, mcc_serialization_params_t> pars =
std::is_null_pointer_v<ParamsT> ? nullptr : params;
auto pars = params;
pars.norm_sxgm = true;
pars.coordpair_format = MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_SXGM_HOURDEG;
@@ -358,8 +367,10 @@ template <mcc_skypoint_c VT>
struct MccSerializer<VT> : MccSerializerBase {
constexpr static std::string_view serializerName{"MCC-SKYPOINT-SERIALIZER"};
template <typename ParamsT = std::nullptr_t>
error_t operator()(traits::mcc_output_char_range auto& output, VT const& value, ParamsT const& params = nullptr)
template <typename ParamsT = mcc_serialization_params_t>
error_t operator()(traits::mcc_output_char_range auto& output,
VT const& value,
ParamsT const& params = mcc_serialization_params_t{})
{
auto serialize_cpair = [&]<typename T>(T& cp) {
auto ccte_err = value.to(cp);
@@ -423,52 +434,256 @@ template <mcc_telemetry_data_c VT>
struct MccSerializer<VT> : MccSerializerBase {
constexpr static std::string_view serializerName{"MCC-TELEMETRY-DATA-SERIALIZER"};
template <typename ParamsT = std::nullptr_t>
error_t operator()(traits::mcc_output_char_range auto& output, VT const& value, ParamsT const& params = nullptr)
template <typename ParamsT = mcc_serialization_params_t>
error_t operator()(traits::mcc_output_char_range auto& output,
VT const& value,
ParamsT const& params = mcc_serialization_params_t{})
{
// FORMAT: RA_OBS_MOUNT, DEC_OBS_MOUNT, RA_APP_MOUNT, DEC_APP_MOUNT, HA_APP_MOUNT, AZ_MOUNT, ZD_MOUNT,
// REFR_CORR_MOUNT, LAST, ENC_X, ENC_Y, PCM_X, PCM_Y, RA_APP_TAG, DEC_APP_TAG, AZ_TAG, ZD_TAG, TIMEPOINT
// REFR_CORR_MOUNT, ENC_X, ENC_Y, PCM_X, PCM_Y, RA_APP_TAG, DEC_APP_TAG, AZ_TAG, ZD_TAG, LAST, EO, TIMEPOINT,
// STATUS
// NOTE: One must assume that the returned RA coordinates are in format of underlying celestial coordinate
// transformation engine used in the mcc_skypoint_c class implementation. E.g. ERFA-library uses the
// CIO-based representation of RA
std::conditional_t<std::is_null_pointer_v<ParamsT>, std::nullptr_t, mcc_serialization_params_t> pars =
std::is_null_pointer_v<ParamsT> ? nullptr : params;
auto pars_h = params;
pars.norm_sxgm = true;
pars.coordpair_format = MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_SXGM_HOURDEG;
auto pars_d = params;
std::string ra_obs, ra_app, ha, last, ra_app_tg;
MccSkyRADEC_OBS r_obs;
MccSkyRADEC_APP r_app;
pars_h.norm_sxgm = true;
pars_h.coordpair_format = MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_SXGM_HOURDEG;
pars_d.norm_sxgm = true;
pars_d.coordpair_format = MccSerializedCoordPairFormat::MCC_SERIALIZED_FORMAT_SXGM_HOURDEG;
MccSkyRADEC_OBS rd_obs;
MccSkyRADEC_APP rd_app;
MccSkyHADEC_APP hd_app;
MccSkyAZZD azzd;
// quantities in hour representation
MccSerializerBase::angleFormatFromCoordPairType<VT::pairKind, MccSerializerBase::CO_LON>(pars);
MccSerializerBase::angleFormatFromCoordPairType<VT::pairKind, MccSerializerBase::CO_LON>(pars_h);
// quantities in degree representation
MccSerializerBase::angleFormatFromCoordPairType<VT::pairKind, MccSerializerBase::CO_LON>(pars_d);
MccSerializer<MccAngle> ang_sr;
// RA_OBS_MOUNT
auto ccte_err = value.mountPos.toAtSameEpoch(r_obs);
// RA_OBS_MOUNT, DEC_OBS_MOUNT
auto ccte_err = value.mountPos.toAtSameEpoch(rd_obs);
if (ccte_err) {
return mcc_deduced_err(ccte_err, MccSerializerErrorCode::ERROR_COORD_TRANSFORM);
}
auto err = ang_sr(ra_obs, r_obs, pars);
auto err = ang_sr(output, rd_obs.x(), pars_h);
if (err) {
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
}
// RA_APP_MOUNT
ccte_err = value.mountPos.toAtSameEpoch(r_app);
MccSerializerBase::addElemDelimiter(output, pars_h);
err = ang_sr(output, rd_obs.y(), pars_h);
if (err) {
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
}
MccSerializerBase::addElemDelimiter(output, pars_h);
// RA_APP_MOUNT, DEC_APP_MOUNT
ccte_err = value.mountPos.toAtSameEpoch(rd_app);
if (ccte_err) {
return mcc_deduced_err(ccte_err, MccSerializerErrorCode::ERROR_COORD_TRANSFORM);
}
err = ang_sr(ra_app, r_app, pars);
err = ang_sr(output, rd_app.x(), pars_h);
if (err) {
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
}
MccSerializerBase::addElemDelimiter(output, pars_h);
err = ang_sr(output, rd_app.y(), pars_d);
if (err) {
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
}
MccSerializerBase::addElemDelimiter(output, pars_h);
// HA_APP_MOUNT
ccte_err = value.mountPos.toAtSameEpoch(hd_app);
if (ccte_err) {
return mcc_deduced_err(ccte_err, MccSerializerErrorCode::ERROR_COORD_TRANSFORM);
}
err = ang_sr(output, hd_app.x(), pars_h);
if (err) {
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
}
MccSerializerBase::addElemDelimiter(output, pars_h);
// AZ_MOUNT, ZD_MOUNT
ccte_err = value.mountPos.toAtSameEpoch(azzd);
if (ccte_err) {
return mcc_deduced_err(ccte_err, MccSerializerErrorCode::ERROR_COORD_TRANSFORM);
}
err = ang_sr(output, azzd.x(), pars_d);
if (err) {
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
}
MccSerializerBase::addElemDelimiter(output, pars_h);
err = ang_sr(output, azzd.y(), pars_d);
if (err) {
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
}
MccSerializerBase::addElemDelimiter(output, pars_h);
// refraction correction
MccAngle ang;
ccte_err = value.mountPos.refractCorrection(&ang);
if (ccte_err) {
return mcc_deduced_err(ccte_err, MccSerializerErrorCode::ERROR_COORD_TRANSFORM);
}
err = ang_sr(output, ang, pars_d);
if (err) {
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
}
MccSerializerBase::addElemDelimiter(output, pars_h);
// encoder X and Y
err = ang_sr(output, value.hwState.XY.x(), pars_d);
if (err) {
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
}
MccSerializerBase::addElemDelimiter(output, pars_h);
err = ang_sr(output, value.hwState.XY.y(), pars_d);
if (err) {
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
}
MccSerializerBase::addElemDelimiter(output, pars_h);
// PCM X and Y
err = ang_sr(output, value.pcmCorrection.pcmX(), pars_d);
if (err) {
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
}
MccSerializerBase::addElemDelimiter(output, pars_h);
err = ang_sr(output, value.pcmCorrection.pcmY(), pars_d);
if (err) {
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
}
MccSerializerBase::addElemDelimiter(output, pars_h);
// RA_APP_TAG, DEC_APP_TAG
ccte_err = value.targetPos.toAtSameEpoch(rd_app);
if (ccte_err) {
return mcc_deduced_err(ccte_err, MccSerializerErrorCode::ERROR_COORD_TRANSFORM);
}
err = ang_sr(output, rd_app.x(), pars_h);
if (err) {
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
}
MccSerializerBase::addElemDelimiter(output, pars_h);
err = ang_sr(output, rd_app.y(), pars_d);
if (err) {
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
}
MccSerializerBase::addElemDelimiter(output, pars_h);
// AZ_TAG, ZD_TAG
ccte_err = value.targetPos.toAtSameEpoch(azzd);
if (ccte_err) {
return mcc_deduced_err(ccte_err, MccSerializerErrorCode::ERROR_COORD_TRANSFORM);
}
err = ang_sr(output, azzd.x(), pars_d);
if (err) {
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
}
MccSerializerBase::addElemDelimiter(output, pars_h);
err = ang_sr(output, azzd.y(), pars_d);
if (err) {
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
}
MccSerializerBase::addElemDelimiter(output, pars_h);
// LAST, local apparent sideral time
ccte_err = value.mountPos.appSideralTime(&ang, true);
if (ccte_err) {
return mcc_deduced_err(ccte_err, MccSerializerErrorCode::ERROR_COORD_TRANSFORM);
}
err = ang_sr(output, ang, pars_h);
if (err) {
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
}
MccSerializerBase::addElemDelimiter(output, pars_h);
// EO, equation of origins
ccte_err = value.mountPos.EO(&ang);
if (ccte_err) {
return mcc_deduced_err(ccte_err, MccSerializerErrorCode::ERROR_COORD_TRANSFORM);
}
err = ang_sr(output, ang, pars_h);
if (err) {
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
}
MccSerializerBase::addElemDelimiter(output, pars_h);
// coordinates epoch
auto ep_err = MccSerializer<MccCelestialCoordEpoch>{}(output, value.mountPos.epoch(), pars_d);
if (ep_err) {
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
}
MccSerializerBase::addElemDelimiter(output, pars_h);
// status (it must be formattable, see mcc_concepts.h)
auto st_err =
MccSerializer<decltype(value.hwState.movementState)>{}(output, value.hwState.movementState, pars_d);
if (st_err) {
return mcc_deduced_err(err, MccSerializerErrorCode::ERROR_UNDERLYING_SERIALIZER);
}
return MccSerializerErrorCode::ERROR_OK;
}
};