#pragma once /* MOUNT CONTROL COMPONENTS LIBRARY */ /* AN GENERIC MOUNT CLASS IMPLEMENTATION BASED ON FINITE STATE MACHINE */ #include #include #include #include "spdlog/sinks/null_sink.h" #include "mcc_mount_concepts.h" #include "mcc_mount_coord.h" #include "mcc_spdlog.h" #include "mcc_traits.h" #include "mcc_finite_state_machine.h" #include "mcc_mount_events_states.h" namespace mcc { template class MccMount : public fsm::MccFiniteStateMachine, public utils::MccSpdlogLogger, protected MOUNT_CONTROLS { // declare these classes as friends to allow them access protected members 'slewModel' and 'guidingModel' friend class MccMountStateSlew; friend class MccMountStateGuiding; public: typedef MOUNT_CONTROLS mount_controls_t; typedef decltype(mount_controls_t::telemetry) mount_telemetry_t; typedef typename mount_telemetry_t::mount_telemetry_data_t mount_telemetry_data_t; typedef decltype(mount_controls_t::astrometryEngine) astrom_engine_t; typedef decltype(mount_controls_t::PEC) pec_t; typedef decltype(mount_controls_t::hardware) hardware_t; typedef decltype(mount_controls_t::slewModel) slew_model_t; typedef decltype(mount_controls_t::guidingModel) guiding_model_t; typedef typename slew_model_t::slew_params_t slew_params_t; /* constructors and destructor */ template MccMount(mount_controls_t mount_controls, InitStateT, std::shared_ptr logger = spdlog::null_logger_mt("NULL"), const LogMarkT& logger_mark = "[MOUNT]") : fsm::MccFiniteStateMachine(InitStateT{}), utils::MccSpdlogLogger(logger), mount_controls_t(std::move(mount_controls)) { addMarkToPatternIdx(logger_mark); logDebug("Create MccMount class instance: thread = {}", getThreadId()); auto ids = this->stateIDs(); auto r = ids | std::views::join_with(','); logDebug("{}", std::string(r.begin(), r.end())); } virtual ~MccMount() { logDebug("Delete MccMount class instance: thread = {}", getThreadId()); } /* public methods */ void initMount() { this->logInfo("STATE: {}", this->currentStateID()); } void stopMount() {} void shutdownMount() {} void slewMount(slew_params_t params) {} void startGuiding() {} mount_telemetry_data_t mountTelemetryData() const { mount_telemetry_data_t mnt_data; auto err = this->telemetry.data(); if (err) { // log .... } return mnt_data; } /* prohibited zone related public methods */ // add zones to mount control system template ZT, traits::mcc_prohibited_zone_c... ZTs> size_t pzAddZone(ZT zone, ZTs... zones) { auto zone_ptr = std::make_shared(std::move(zone)); _pzFuncs.emplace_back( {.coordPairKind = ZT::zoneCoordPairKind, .name = std::format("{}", zone_ptr->name()), .inZoneFunc = [zone_ptr, this](const mount_telemetry_data_t& tmry_data) { return zone_ptr->inZone(tmry_data); }, .timeToFunc = [zone_ptr, this](const mount_telemetry_data_t& tmry_data) { return zone_ptr->timeTo(tmry_data); }, .timeFromFunc = [zone_ptr, this](const mount_telemetry_data_t& tmry_data) { return zone_ptr->timeFrom(tmry_data); }}); if constexpr (sizeof...(ZTs)) { pzAddZone(std::move(zones)...); } return _pzFuncs.size(); } // delete all zones from mount control system void pzClearZone() { // stop mount here?!! _pzFuncs.clear(); } protected: // a type to which the result of calling prohibited zone class methods 'timeTo' and 'timeFrom' will be converted typedef std::chrono::duration pz_duration_t; // seconds as floating-point number typedef std::function pz_inzone_func_t; typedef std::function pz_timeto_func_t; typedef std::function pz_timefrom_func_t; struct pz_funcs_t { MccCoordPairKind coordPairKind; std::string name; pz_inzone_func_t inZoneFunc; pz_timeto_func_t timeToFunc; pz_timefrom_func_t timeFromFunc; }; std::vector _pzFuncs{}; template ... ZTs> auto forEachPZone(FuncT&& func, std::tuple& zones) { std::array, sizeof...(ZTs)> result; forEachPZoneHelper(std::forward(func), zones, result); } template ... ZTs> auto forEachPZoneHelper(FuncT&& func, std::tuple& zones, auto& result) requires(I < sizeof...(ZTs)) { std::get(result) = std::forward(func)(std::get(zones), mountTelemetryData()); forEachPZoneHelper(std::forward(func), zones, result); } }; // end of MccMount class // namespace traits // { // // given mount class must be a descendant of MccMount // template // concept mcc_mount_c = requires(T t) { [](MccMount*) {}(&t); }; // } // namespace traits } // namespace mcc