LCOV - code coverage report
Current view: top level - apps/zaberCtrl - zaberCtrl.hpp (source / functions) Coverage Total Hit
Test: MagAOX Lines: 10.1 % 199 20
Test Date: 2026-01-03 21:03:39 Functions: 30.0 % 30 9

            Line data    Source code
       1              : /** \file zaberCtrl.hpp
       2              :   * \brief The MagAO-X Zaber Stage Controller header file
       3              :   *
       4              :   * \ingroup zaberCtrl_files
       5              :   */
       6              : 
       7              : #ifndef zaberCtrl_hpp
       8              : #define zaberCtrl_hpp
       9              : 
      10              : 
      11              : #include "../../libMagAOX/libMagAOX.hpp" //Note this is included on command line to trigger pch
      12              : #include "../../magaox_git_version.h"
      13              : 
      14              : /** \defgroup zaberCtrl
      15              :   * \brief The MagAO-X application to control a single Zaber stage
      16              :   *
      17              :   * <a href="../handbook/operating/software/apps/zaberCtrl.html">Application Documentation</a>
      18              :   *
      19              :   * \ingroup apps
      20              :   *
      21              :   */
      22              : 
      23              : /** \defgroup zaberCtrl_files
      24              :   * \ingroup zaberCtrl
      25              :   */
      26              : 
      27              : namespace MagAOX
      28              : {
      29              : namespace app
      30              : {
      31              : 
      32              : /// The MagAO-X Zaber Stage Controller
      33              : /** Interacts with the stage through a zaberLowLevel process via INDI.
      34              :   *
      35              :   * \ingroup zaberCtrl
      36              :   */
      37              : class zaberCtrl : public MagAOXApp<>, public dev::stdMotionStage<zaberCtrl>, public dev::telemeter<zaberCtrl>
      38              : {
      39              : 
      40              :    //Give the test harness access.
      41              :    friend class zaberCtrl_test;
      42              : 
      43              :    friend class dev::stdMotionStage<zaberCtrl>;
      44              : 
      45              :    friend class dev::telemeter<zaberCtrl>;
      46              : 
      47              : protected:
      48              : 
      49              :    /** \name Configurable Parameters
      50              :      *@{
      51              :      */
      52              : 
      53              :    std::string m_lowLevelName {"zaberLowLevel"};
      54              : 
      55              :    std::string m_stageName; ///< The name of this stage used for accessing via zaberLowLevel
      56              : 
      57              :    double m_countsPerMillimeter {10078.740157480315}; ///< Counts per millimeter calibration of this stage.
      58              : 
      59              :    unsigned long m_maxRawPos {0}; ///< Maximum counts available on this stage.
      60              : 
      61              :    ///@}
      62              : 
      63              :    double m_rawPos {0};  ///< Current raw position in counts
      64              :    double m_tgtRawPos {0}; ///< Target raw position in counts
      65              :    double m_stageTemp{0}; ///< Temperature reported by the stage
      66              : 
      67              :    double m_maxPos {0};   ///< Maximum position in mm available on this stage
      68              :    double m_pos {0}; ///< Current position in mm
      69              :    double m_tgtPos {0}; ///< Target position in mm.
      70              : 
      71              :    int m_homingState{0}; ///< The homing state, tracks the stages of homing.
      72              : 
      73              : public:
      74              :    /// Default c'tor.
      75              :    zaberCtrl();
      76              : 
      77              :    /// D'tor, declared and defined for noexcept.
      78           33 :    ~zaberCtrl() noexcept
      79           33 :    {}
      80              : 
      81              :    /// Setup the configuration of this stage controller.
      82              :    virtual void setupConfig();
      83              : 
      84              :    /// Implementation of loadConfig logic, separated for testing.
      85              :    /** This is called by loadConfig().
      86              :      */
      87              :    int loadConfigImpl( mx::app::appConfigurator & _config /**< [in] an application configuration from which to load values*/);
      88              : 
      89              :    ///Load the stage configuration
      90              :    /** Calls loadConfigImpl()
      91              :      */
      92              :    virtual void loadConfig();
      93              : 
      94              :    /// Startup function
      95              :    /**
      96              :      *
      97              :      */
      98              :    virtual int appStartup();
      99              : 
     100              :    /// Implementation of the FSM for zaberCtrl.
     101              :    /**
     102              :      * \returns 0 on no critical error
     103              :      * \returns -1 on an error requiring shutdown
     104              :      */
     105              :    virtual int appLogic();
     106              : 
     107              :    /// Shutdown the app.
     108              :    /**
     109              :      *
     110              :      */
     111              :    virtual int appShutdown();
     112              : 
     113              :    /// Start a high-level homing sequence.
     114              :    /**
     115              :      *
     116              :      * \returns 0 on success.
     117              :      * \returns -1 on error.
     118              :      */
     119              :    int startHoming();
     120              : 
     121              :    /// Stop the stage motion immediately.
     122              :    /**
     123              :      * \returns 0 on success.
     124              :      * \returns -1 on error.
     125              :      */
     126              :    int stop();
     127              : 
     128              :    double presetNumber();
     129              : 
     130              :    /// Move to a new position in mm.
     131              :    /**  \todo this actually should move to a preset position by nearest integet..  A moveToMM should be used for the mm command.
     132              :      *
     133              :      * \returns 0 on success.
     134              :      * \returns -1 on error.
     135              :      */
     136              :    int moveTo( const double & pos /**< [in] The new position in mm*/ );
     137              : 
     138              : protected:
     139              : 
     140              :    //INDI properties for user interaction:
     141              :    pcf::IndiProperty m_indiP_pos;
     142              :    pcf::IndiProperty m_indiP_rawPos;
     143              :    pcf::IndiProperty m_indiP_maxPos;
     144              :    pcf::IndiProperty m_indiP_temp;
     145              : 
     146              : public:
     147              : 
     148            0 :    INDI_NEWCALLBACK_DECL(zaberCtrl, m_indiP_pos);
     149            0 :    INDI_NEWCALLBACK_DECL(zaberCtrl, m_indiP_rawPos);
     150              : 
     151              :    //INDI properties for interacting with Low-Level
     152              :    pcf::IndiProperty m_indiP_stageState;
     153              :    pcf::IndiProperty m_indiP_stageMaxRawPos;
     154              :    pcf::IndiProperty m_indiP_stageRawPos;
     155              :    pcf::IndiProperty m_indiP_stageTgtPos;
     156              :    pcf::IndiProperty m_indiP_stageTemp;
     157              : 
     158              : public:
     159            0 :    INDI_SETCALLBACK_DECL(zaberCtrl, m_indiP_stageState);
     160            0 :    INDI_SETCALLBACK_DECL(zaberCtrl, m_indiP_stageMaxRawPos);
     161            0 :    INDI_SETCALLBACK_DECL(zaberCtrl, m_indiP_stageRawPos);
     162            0 :    INDI_SETCALLBACK_DECL(zaberCtrl, m_indiP_stageTgtPos);
     163            0 :    INDI_SETCALLBACK_DECL(zaberCtrl, m_indiP_stageTemp);
     164              : 
     165              :    /** \name Telemeter Interface
     166              :      *
     167              :      * @{
     168              :      */
     169              :    int checkRecordTimes();
     170              : 
     171              :    int recordTelem( const telem_stage * );
     172              : 
     173              :    int recordTelem( const telem_zaber * );
     174              : 
     175              :    int recordZaber(bool force = false);
     176              : 
     177              :    ///@}
     178              : };
     179              : 
     180          165 : zaberCtrl::zaberCtrl() : MagAOXApp(MAGAOX_CURRENT_SHA1, MAGAOX_REPO_MODIFIED)
     181              : {
     182           33 :    m_fractionalPresets = false;
     183           33 :    m_defaultPositions = false;
     184              : 
     185           33 :    return;
     186            0 : }
     187              : 
     188            0 : void zaberCtrl::setupConfig()
     189              : {
     190            0 :    config.add("stage.lowLevelName", "", "stage.lowLevelName", argType::Required, "stage", "lowLevelName", false, "string", "The name of the low-level control process actually controlling this stage.  Default is zaberLowLevel.");
     191              : 
     192            0 :    config.add("stage.stageName", "", "stage.stageName", argType::Required, "stage", "stageName", false, "string", "the name of this stage in the low-level process INDI properties.  Default is the configuration name.");
     193              : 
     194            0 :    config.add("stage.countsPerMillimeter", "", "stage.countsPerMillimeter", argType::Required, "stage", "countsPerMillimeter", false, "float", "The counts per mm calibration of the stage.  Default is 10078.74, which applies tot he X-LRQ-DE.");
     195              : 
     196            0 :    config.add("stage.maxCounts", "", "stage.maxCounts", argType::Required, "stage", "maxCounts", false, "unsigned long", "The maximum counts possible for this stage.");
     197              : 
     198            0 :    dev::stdMotionStage<zaberCtrl>::setupConfig(config);
     199              : 
     200            0 :    dev::telemeter<zaberCtrl>::setupConfig(config);
     201            0 : }
     202              : 
     203              : 
     204            0 : int zaberCtrl::loadConfigImpl( mx::app::appConfigurator & _config )
     205              : {
     206            0 :    _config(m_lowLevelName, "stage.lowLevelName");
     207              : 
     208            0 :    m_stageName = m_configName;
     209            0 :    _config(m_stageName, "stage.stageName");
     210              : 
     211            0 :    _config(m_countsPerMillimeter, "stage.countsPerMillimeter");
     212              : 
     213            0 :    _config(m_maxRawPos, "stage.maxCounts");
     214            0 :    m_maxPos = ((double) m_maxRawPos)/ m_countsPerMillimeter;
     215              : 
     216            0 :    dev::stdMotionStage<zaberCtrl>::loadConfig(_config);
     217              : 
     218            0 :    dev::telemeter<zaberCtrl>::loadConfig(_config);
     219              : 
     220            0 :    return 0;
     221              : }
     222              : 
     223            0 : void zaberCtrl::loadConfig()
     224              : {
     225            0 :    loadConfigImpl(config);
     226            0 : }
     227              : 
     228            0 : int zaberCtrl::appStartup()
     229              : {
     230              : 
     231            0 :    createStandardIndiNumber<float>( m_indiP_pos, "position", 0.0, m_maxPos, 1/m_countsPerMillimeter, "%.4f");
     232            0 :    m_indiP_pos["current"].set(0);
     233            0 :    m_indiP_pos["target"].set(0);
     234            0 :    if( registerIndiPropertyNew( m_indiP_pos, INDI_NEWCALLBACK(m_indiP_pos)) < 0)
     235              :    {
     236              :       #ifndef ZABERCTRL_TEST_NOLOG
     237            0 :       log<software_error>({__FILE__,__LINE__});
     238              :       #endif
     239            0 :       return -1;
     240              :    }
     241              : 
     242            0 :    createStandardIndiNumber<unsigned long>( m_indiP_rawPos, "rawpos", 0.0, m_maxRawPos, 1, "%lu");
     243            0 :    m_indiP_rawPos["current"].set(0);
     244            0 :    m_indiP_rawPos["target"].set(0);
     245            0 :    if( registerIndiPropertyNew( m_indiP_rawPos, INDI_NEWCALLBACK(m_indiP_rawPos)) < 0)
     246              :    {
     247              :       #ifndef ZABERCTRL_TEST_NOLOG
     248            0 :       log<software_error>({__FILE__,__LINE__});
     249              :       #endif
     250            0 :       return -1;
     251              :    }
     252              : 
     253            0 :    createROIndiNumber( m_indiP_maxPos, "maxpos", "Maximum Position");
     254            0 :    indi::addNumberElement( m_indiP_maxPos, "value", m_maxPos, m_maxPos, 0.0, "%0.4f");
     255            0 :    m_indiP_maxPos["value"].set<double>(m_maxPos);
     256            0 :    registerIndiPropertyReadOnly(m_indiP_maxPos);
     257              : 
     258            0 :    createROIndiNumber( m_indiP_temp, "temp", "Stage Temperature [C]");
     259            0 :    indi::addNumberElement( m_indiP_temp, "current", -50,100, 0, "%0.1f");
     260            0 :    registerIndiPropertyReadOnly(m_indiP_temp);
     261              : 
     262              :    //Register for the low level status reports
     263            0 :    REG_INDI_SETPROP(m_indiP_stageState, m_lowLevelName, "curr_state");
     264            0 :    REG_INDI_SETPROP(m_indiP_stageMaxRawPos, m_lowLevelName, std::string("max_pos"));
     265            0 :    REG_INDI_SETPROP(m_indiP_stageRawPos, m_lowLevelName, std::string("curr_pos"));
     266            0 :    REG_INDI_SETPROP(m_indiP_stageTgtPos, m_lowLevelName, std::string("tgt_pos"));
     267            0 :    REG_INDI_SETPROP(m_indiP_stageTemp, m_lowLevelName, std::string("temp"));
     268              : 
     269              : 
     270            0 :    if(m_presetNames.size() != m_presetPositions.size())
     271              :    {
     272            0 :       return log<text_log,-1>("must set a position for each preset", logPrio::LOG_CRITICAL);
     273              :    }
     274              : 
     275            0 :    m_presetNames.insert(m_presetNames.begin(), "none");
     276            0 :    m_presetPositions.insert(m_presetPositions.begin(), -1);
     277              : 
     278            0 :    dev::stdMotionStage<zaberCtrl>::appStartup();
     279              : 
     280            0 :    if(dev::telemeter<zaberCtrl>::appStartup() < 0)
     281              :    {
     282            0 :       return log<software_error,-1>({__FILE__,__LINE__});
     283              :    }
     284              : 
     285            0 :    return 0;
     286              : }
     287              : 
     288            0 : int zaberCtrl::appLogic()
     289              : {
     290            0 :    if(state() == stateCodes::INITIALIZED)
     291              :    {
     292            0 :       state(stateCodes::NOTCONNECTED);
     293              :    }
     294              : 
     295            0 :    if(state() == stateCodes::NOTCONNECTED || state() == stateCodes::POWEROFF)
     296              :    {
     297              :       //Here do poweroff update
     298            0 :       if( stdMotionStage<zaberCtrl>::onPowerOff() < 0)
     299              :       {
     300            0 :          log<software_error>({__FILE__,__LINE__});
     301              :       }
     302              : 
     303            0 :       recordStage();
     304              : 
     305              :       //record telem if it's been longer than 10 sec:
     306            0 :       if(telemeter<zaberCtrl>::appLogic() < 0)
     307              :       {
     308            0 :          log<software_error>({__FILE__, __LINE__});
     309              :       }
     310              : 
     311            0 :       return 0;
     312              :    }
     313              : 
     314            0 :    if(state() == stateCodes::POWERON)
     315              :    {
     316            0 :       recordStage();
     317            0 :       return 0;
     318              :    }
     319              : 
     320            0 :    if(state() == stateCodes::NOTHOMED)
     321              :    {
     322            0 :       if(m_powerOnHome) startHoming();
     323              :    }
     324              : 
     325            0 :    if(state() == stateCodes::HOMING)
     326              :    {
     327            0 :       if(m_homingState == 2)
     328              :       {
     329            0 :          if(m_homePreset >= 0)
     330              :          {
     331            0 :             m_preset_target = m_presetPositions[m_homePreset];
     332            0 :             updateIfChanged(m_indiP_preset, "target",  m_preset_target, INDI_BUSY);
     333              : 
     334              :             //sleep(2); //pause to give time for controller to update itself and throw a warning
     335              : 
     336            0 :             moveTo(m_preset_target);
     337              :          }
     338              : 
     339            0 :          m_homingState = 0;
     340              :       }
     341              :    }
     342              :    //Otherwise we don't do anything differently
     343            0 :    std::lock_guard<std::mutex> guard(m_indiMutex);
     344              : 
     345              :    static int last_moving = -10;
     346              : 
     347            0 :    bool changed = false;
     348            0 :    if(last_moving != m_moving)
     349              :    {
     350            0 :       changed = true;
     351            0 :       last_moving = m_moving;
     352              :    }
     353              : 
     354            0 :    if(changed)
     355              :    {
     356            0 :       if(m_moving)
     357              :       {
     358            0 :          m_indiP_pos.setState(INDI_BUSY);
     359            0 :          m_indiP_rawPos.setState(INDI_BUSY);
     360              :       }
     361              :       else
     362              :       {
     363            0 :          m_indiP_pos.setState(INDI_IDLE);
     364            0 :          m_indiP_pos["target"] = m_pos;
     365            0 :          m_indiP_rawPos.setState(INDI_IDLE);
     366            0 :          m_indiP_rawPos["target"] = m_rawPos;
     367              :       }
     368              : 
     369            0 :       m_indiDriver->sendSetProperty(m_indiP_pos);
     370            0 :       m_indiDriver->sendSetProperty(m_indiP_rawPos);
     371              :    }
     372              : 
     373            0 :    if(m_moving && m_movingState < 1)
     374              :    {
     375            0 :       updateIfChanged(m_indiP_pos, "current", m_pos, INDI_BUSY);
     376            0 :       updateIfChanged(m_indiP_rawPos, "current", m_rawPos, INDI_BUSY);
     377              :    }
     378              :    else
     379              :    {
     380            0 :       updateIfChanged(m_indiP_pos, "current", m_pos,INDI_IDLE);
     381            0 :       updateIfChanged(m_indiP_rawPos, "current", m_rawPos,INDI_IDLE);
     382              :    }
     383              : 
     384            0 :    int n = presetNumber();
     385            0 :    if(n == -1)
     386              :    {
     387            0 :       m_preset = 0;
     388            0 :       m_preset_target = 0;
     389              :    }
     390              :    else
     391              :    {
     392            0 :       m_preset = n+1;
     393            0 :       m_preset_target = n+1;
     394              :    }
     395              : 
     396            0 :    recordStage();
     397            0 :    recordZaber();
     398              : 
     399            0 :    dev::stdMotionStage<zaberCtrl>::updateINDI();
     400              : 
     401            0 :    if(telemeter<zaberCtrl>::appLogic() < 0)
     402              :    {
     403            0 :       log<software_error>({__FILE__, __LINE__});
     404            0 :       return 0;
     405              :    }
     406              : 
     407            0 :    return 0;
     408            0 : }
     409              : 
     410            0 : int zaberCtrl::appShutdown()
     411              : {
     412            0 :    return 0;
     413              : }
     414              : 
     415            0 : int zaberCtrl::startHoming()
     416              : {
     417            0 :    updateSwitchIfChanged(m_indiP_home, "request", pcf::IndiElement::Off, INDI_IDLE);
     418              : 
     419            0 :    pcf::IndiProperty indiP_stageHome = pcf::IndiProperty(pcf::IndiProperty::Text);
     420            0 :    indiP_stageHome.setDevice(m_lowLevelName);
     421            0 :    indiP_stageHome.setName("req_home");
     422            0 :    indiP_stageHome.setPerm(pcf::IndiProperty::ReadWrite);
     423            0 :    indiP_stageHome.setState(pcf::IndiProperty::Idle);
     424            0 :    indiP_stageHome.add(pcf::IndiElement(m_stageName));
     425              : 
     426            0 :    m_moving = 2;
     427            0 :    m_homingState = 1;
     428            0 :    if( sendNewProperty(indiP_stageHome, m_stageName, "1") < 0 ) return log<software_error,-1>({__FILE__,__LINE__});
     429              : 
     430            0 :    return 0;
     431            0 : }
     432              : 
     433            0 : int zaberCtrl::stop()
     434              : {
     435            0 :    updateSwitchIfChanged(m_indiP_stop, "request", pcf::IndiElement::Off, INDI_IDLE);
     436              : 
     437            0 :    pcf::IndiProperty indiP_stageHalt = pcf::IndiProperty(pcf::IndiProperty::Text);
     438            0 :    indiP_stageHalt.setDevice(m_lowLevelName);
     439            0 :    indiP_stageHalt.setName("req_halt");
     440            0 :    indiP_stageHalt.setPerm(pcf::IndiProperty::ReadWrite);
     441            0 :    indiP_stageHalt.setState(pcf::IndiProperty::Idle);
     442            0 :    indiP_stageHalt.add(pcf::IndiElement(m_stageName));
     443              : 
     444            0 :    if( sendNewProperty(indiP_stageHalt, m_stageName, "1") < 0 ) return log<software_error,-1>({__FILE__,__LINE__});
     445              : 
     446            0 :    return 0;
     447            0 : }
     448              : 
     449            0 : double zaberCtrl::presetNumber()
     450              : {
     451            0 :    for( size_t n=1; n < m_presetPositions.size(); ++n)
     452              :    {
     453            0 :       if( fabs(m_pos-m_presetPositions[n]) < 1./m_countsPerMillimeter) return n;
     454              :    }
     455              : 
     456            0 :    return 0;
     457              : }
     458              : 
     459            0 : int zaberCtrl::moveTo( const double & target)
     460              : {
     461            0 :    if(target < 0) return 0;
     462              : 
     463            0 :    m_tgtRawPos = (target*m_countsPerMillimeter + 0.5);
     464              : 
     465            0 :    pcf::IndiProperty indiP_stageTgtPos = pcf::IndiProperty(pcf::IndiProperty::Number);
     466            0 :    indiP_stageTgtPos.setDevice(m_lowLevelName);
     467            0 :    indiP_stageTgtPos.setName("tgt_pos");
     468            0 :    indiP_stageTgtPos.setPerm(pcf::IndiProperty::ReadWrite);
     469            0 :    indiP_stageTgtPos.setState(pcf::IndiProperty::Idle);
     470            0 :    indiP_stageTgtPos.add(pcf::IndiElement(m_stageName));
     471              : 
     472            0 :    m_moving = 1;
     473            0 :    dev::stdMotionStage<zaberCtrl>::recordStage(true);
     474            0 :    recordZaber(true);
     475              : 
     476            0 :    if( sendNewProperty(indiP_stageTgtPos, m_stageName, m_tgtRawPos) < 0 ) return log<software_error,-1>({__FILE__,__LINE__});
     477              : 
     478            0 :    return 0;
     479            0 : }
     480              : 
     481            3 : INDI_NEWCALLBACK_DEFN( zaberCtrl, m_indiP_pos)(const pcf::IndiProperty &ipRecv)
     482              : {
     483            3 :     INDI_VALIDATE_CALLBACK_PROPS(m_indiP_pos, ipRecv);
     484              : 
     485              :    double target =-1;
     486              :    if( ipRecv.find("target") ) //Just not our stage.
     487              :    {
     488              :       target = ipRecv["target"].get<double>();
     489              :    }
     490              : 
     491              :    if(target < 0)
     492              :    {
     493              :       return 0;
     494              :       /*if( ipRecv.find("current") ) //Just not our stage.
     495              :       {
     496              :          target = ipRecv["current"].get<double>();
     497              :       }
     498              : 
     499              :       if(target < 0 )
     500              :       {
     501              :          return log<text_log,-1>("no valid target position provided", logPrio::LOG_ERROR);
     502              :       }*/
     503              :    }
     504              : 
     505              :    if(m_moving != 0)
     506              :    {
     507              :       log<text_log>("abs move to " + std::to_string(target) + " rejected due to already moving");
     508              :       return 0;
     509              :    }
     510              : 
     511              :    log<text_log>("moving stage to " + std::to_string(target));
     512              : 
     513              :    std::lock_guard<std::mutex> guard(m_indiMutex);
     514              : 
     515              :    m_tgtPos = target;
     516              : 
     517              :    moveTo(m_tgtPos);
     518              :    updateIfChanged(m_indiP_pos, "target", m_tgtPos, INDI_BUSY);
     519              :    updateIfChanged(m_indiP_rawPos, "target", m_tgtRawPos, INDI_BUSY);
     520              :    return 0;
     521              : }
     522              : 
     523            3 : INDI_NEWCALLBACK_DEFN( zaberCtrl, m_indiP_rawPos)(const pcf::IndiProperty &ipRecv)
     524              : {
     525            3 :     INDI_VALIDATE_CALLBACK_PROPS(m_indiP_rawPos, ipRecv);
     526              : 
     527              :    double target =-1;
     528              :    if( ipRecv.find("target") ) //Just not our stage.
     529              :    {
     530              :       target = ipRecv["target"].get<double>();
     531              :    }
     532              : 
     533              :    if(target < 0)
     534              :    {
     535              :       if( ipRecv.find("current") ) //Just not our stage.
     536              :       {
     537              :          target = ipRecv["current"].get<double>();
     538              :       }
     539              : 
     540              :       if(target < 0 )
     541              :       {
     542              :          return log<text_log,-1>("no valid target position provided", logPrio::LOG_ERROR);
     543              :       }
     544              :    }
     545              : 
     546              :    if(m_moving != 0)
     547              :    {
     548              :       log<text_log>("rel move rejected due to already moving");
     549              :       return 0;
     550              :    }
     551              : 
     552              :    log<text_log>("moving stage by " + std::to_string(target));
     553              : 
     554              :    std::lock_guard<std::mutex> guard(m_indiMutex);
     555              : 
     556              :    pcf::IndiProperty indiP_stageTgtPos = pcf::IndiProperty(pcf::IndiProperty::Text);
     557              :    indiP_stageTgtPos.setDevice(m_lowLevelName);
     558              :    indiP_stageTgtPos.setName("tgt_pos");
     559              :    indiP_stageTgtPos.setPerm(pcf::IndiProperty::ReadWrite);
     560              :    indiP_stageTgtPos.setState(pcf::IndiProperty::Idle);
     561              :    indiP_stageTgtPos.add(pcf::IndiElement(m_stageName));
     562              : 
     563              :    dev::stdMotionStage<zaberCtrl>::recordStage(true);
     564              : 
     565              :    if( sendNewProperty(indiP_stageTgtPos, m_stageName, target) < 0 ) return log<software_error,-1>({__FILE__,__LINE__});
     566              : 
     567              : 
     568              :    m_tgtRawPos = target;
     569              :    m_tgtPos = m_tgtRawPos / m_countsPerMillimeter;
     570              :    updateIfChanged(m_indiP_pos, "target", m_tgtPos, INDI_BUSY);
     571              :    updateIfChanged(m_indiP_rawPos, "target", m_tgtRawPos, INDI_BUSY);
     572              :    return 0;
     573              : }
     574              : 
     575              : 
     576              : 
     577            3 : INDI_SETCALLBACK_DEFN( zaberCtrl, m_indiP_stageState)(const pcf::IndiProperty &ipRecv)
     578              : {
     579            3 :     INDI_VALIDATE_CALLBACK_PROPS(m_indiP_stageState, ipRecv);
     580              : 
     581              :    if( ipRecv.find(m_stageName) != true ) //Just not our stage.
     582              :    {
     583              :       return 0;
     584              :    }
     585              : 
     586              :    m_indiP_stageState = ipRecv;
     587              : 
     588              :    std::string sstr = ipRecv[m_stageName].get<std::string>();
     589              : 
     590              :    std::lock_guard<std::mutex> guard(m_indiMutex);
     591              : 
     592              :    if(sstr == "POWEROFF")
     593              :    {
     594              :       state(stateCodes::POWEROFF);
     595              :       m_moving = -2;
     596              :    }
     597              :    else if(sstr == "POWERON")
     598              :    {
     599              :       state(stateCodes::POWERON);
     600              :       m_moving = -1;
     601              :    }
     602              :    else if(sstr == "NODEVICE")
     603              :    {
     604              :       state(stateCodes::NODEVICE);
     605              :       m_moving = -2;
     606              :    }
     607              :    else if(sstr == "NOTCONNECTED")
     608              :    {
     609              :       state(stateCodes::NOTCONNECTED);
     610              :       m_moving = -2;
     611              :    }
     612              :    else if(sstr == "CONNECTED")
     613              :    {
     614              :       state(stateCodes::CONNECTED);
     615              :       m_moving = -2;
     616              :    }
     617              :    else if(sstr == "NOTHOMED")
     618              :    {
     619              :       state(stateCodes::NOTHOMED);
     620              :       m_moving = -1;
     621              :    }
     622              :    else if(sstr == "HOMING")
     623              :    {
     624              :       state(stateCodes::HOMING);
     625              :       m_homingState = 1;
     626              :       m_moving = 2;
     627              :    }
     628              :    else if(sstr == "READY")
     629              :    {
     630              :       if(m_homingState == 0)
     631              :       {
     632              :          state(stateCodes::READY);
     633              :       }
     634              :       else
     635              :       {
     636              :          m_homingState = 2;
     637              :       }
     638              :       m_moving = 0;
     639              :    }
     640              :    else if(sstr == "OPERATING")
     641              :    {
     642              :       state(stateCodes::OPERATING);
     643              :       m_moving = 1;
     644              :    }
     645              :    else if(sstr == "SHUTDOWN")
     646              :    {
     647              :       state(stateCodes::NOTCONNECTED);
     648              :       m_moving = -2;
     649              :    }
     650              :    else if(sstr == "FAILURE")
     651              :    {
     652              :       state(stateCodes::FAILURE);
     653              :       m_moving = -2;
     654              :    }
     655              :    else if(sstr == "ERROR")
     656              :    {
     657              :       state(stateCodes::ERROR);
     658              :       m_moving = -2;
     659              :    }
     660              :    else
     661              :    {
     662              :       std::cerr << "else: " << sstr << "\n";
     663              :       state(stateCodes::UNINITIALIZED);
     664              :       m_moving = -2;
     665              :    }
     666              :    return 0;
     667              : }
     668              : 
     669            3 : INDI_SETCALLBACK_DEFN( zaberCtrl, m_indiP_stageMaxRawPos )(const pcf::IndiProperty &ipRecv)
     670              : {
     671            3 :     INDI_VALIDATE_CALLBACK_PROPS(m_indiP_stageMaxRawPos, ipRecv);
     672              : 
     673              :    if( ipRecv.find(m_stageName) != true ) //Just not our stage.
     674              :    {
     675              :       return 0;
     676              :    }
     677              : 
     678              :    std::lock_guard<std::mutex> guard(m_indiMutex);
     679              : 
     680              :    long maxRawPos = ipRecv[m_stageName].get<long>();
     681              : 
     682              :    if(maxRawPos > 10000000000000 || maxRawPos < 0) return 0; //Indicates a bad value
     683              : 
     684              :    if((unsigned long) maxRawPos != m_maxRawPos && (state() == stateCodes::CONNECTED|| state() == stateCodes::HOMING || state() == stateCodes::READY || state() == stateCodes::OPERATING))
     685              :    {
     686              :       log<text_log>("max position mismatch between config-ed value (" + std::to_string(m_maxRawPos) + ") and stage value (" + std::to_string(maxRawPos) + ")", logPrio::LOG_WARNING);
     687              :    }
     688              : 
     689              :    return 0;
     690              : }
     691              : 
     692            3 : INDI_SETCALLBACK_DEFN( zaberCtrl, m_indiP_stageRawPos )(const pcf::IndiProperty &ipRecv)
     693              : {
     694            3 :     INDI_VALIDATE_CALLBACK_PROPS(m_indiP_stageRawPos, ipRecv);
     695              : 
     696              :    if( ipRecv.find(m_stageName) != true ) //Just not our stage.
     697              :    {
     698              :       return 0;
     699              :    }
     700              : 
     701              :    std::lock_guard<std::mutex> guard(m_indiMutex);
     702              : 
     703              :    m_rawPos = ipRecv[m_stageName].get<double>();
     704              : 
     705              :    m_pos = m_rawPos / m_countsPerMillimeter;
     706              : 
     707              :    if(m_moving)
     708              :    {
     709              :       updateIfChanged(m_indiP_rawPos, "current", m_rawPos, INDI_BUSY);
     710              :       updateIfChanged(m_indiP_pos, "current", m_pos, INDI_BUSY);
     711              :    }
     712              :    else
     713              :    {
     714              :       updateIfChanged(m_indiP_rawPos, "current", m_rawPos, INDI_IDLE);
     715              :       updateIfChanged(m_indiP_pos, "current", m_pos, INDI_IDLE);
     716              :    }
     717              : 
     718              :    dev::stdMotionStage<zaberCtrl>::recordStage();
     719              : 
     720              :    return 0;
     721              : }
     722              : 
     723            3 : INDI_SETCALLBACK_DEFN( zaberCtrl, m_indiP_stageTgtPos )(const pcf::IndiProperty &ipRecv)
     724              : {
     725            3 :     INDI_VALIDATE_CALLBACK_PROPS(m_indiP_stageTgtPos, ipRecv);
     726              : 
     727              :    if( ipRecv.find(m_stageName) != true ) //Just not our stage.
     728              :    {
     729              :       return 0;
     730              :    }
     731              : 
     732              :    //Test for empty property to see if target reached
     733              :    std::string test = ipRecv[m_stageName].get<std::string>();
     734              : 
     735              :    if(test == "")
     736              :    {
     737              :       return 0;
     738              :    }
     739              : 
     740              :    std::lock_guard<std::mutex> guard(m_indiMutex);
     741              : 
     742              :    m_tgtRawPos = ipRecv[m_stageName].get<double>();
     743              :    m_tgtPos = m_tgtRawPos / m_countsPerMillimeter;
     744              : 
     745              :    if(m_moving)
     746              :    {
     747              :       updateIfChanged(m_indiP_rawPos, "target", m_tgtRawPos, INDI_BUSY);
     748              :       updateIfChanged(m_indiP_pos, "target", m_tgtPos, INDI_BUSY);
     749              :    }
     750              :    else
     751              :    {
     752              :       updateIfChanged(m_indiP_rawPos, "target", m_tgtRawPos, INDI_IDLE);
     753              :       updateIfChanged(m_indiP_pos, "target", m_tgtPos, INDI_IDLE);
     754              :    }
     755              : 
     756              :    return 0;
     757              : }
     758              : 
     759            3 : INDI_SETCALLBACK_DEFN( zaberCtrl, m_indiP_stageTemp )(const pcf::IndiProperty &ipRecv)
     760              : {
     761            3 :     INDI_VALIDATE_CALLBACK_PROPS(m_indiP_stageTemp, ipRecv);
     762              : 
     763              :     if( ipRecv.find(m_stageName) != true ) //Just not our stage.
     764              :     {
     765              :         return 0;
     766              :     }
     767              : 
     768              :     std::lock_guard<std::mutex> guard(m_indiMutex);
     769              : 
     770              :     m_stageTemp = ipRecv[m_stageName].get<double>();
     771              : 
     772              :     updateIfChanged(m_indiP_temp, "current", m_stageTemp);
     773              : 
     774              :     return 0;
     775              : }
     776              : 
     777            0 : int zaberCtrl::checkRecordTimes()
     778              : {
     779            0 :    return telemeter<zaberCtrl>::checkRecordTimes(telem_stage(), telem_zaber());
     780              : }
     781              : 
     782            0 : int zaberCtrl::recordTelem( const telem_stage * )
     783              : {
     784            0 :    return stdMotionStage<zaberCtrl>::recordStage(true);
     785              : }
     786              : 
     787            0 : int zaberCtrl::recordTelem( const telem_zaber * )
     788              : {
     789            0 :    return recordZaber(true);
     790              : }
     791              : 
     792            0 : int zaberCtrl::recordZaber(bool force)
     793              : {
     794            0 :    static double last_pos = m_pos - 1000;
     795            0 :    static double last_rawPos = m_rawPos;
     796            0 :    static double last_temp = m_stageTemp;
     797              : 
     798            0 :    if( m_pos != last_pos || m_rawPos != last_rawPos || m_stageTemp != last_temp || force)
     799              :    {
     800            0 :       telem<telem_zaber>({(float) m_pos, (float) m_rawPos, (float) m_stageTemp});
     801              : 
     802            0 :       last_pos = m_pos;
     803            0 :       last_rawPos = m_rawPos;
     804            0 :       last_temp = m_stageTemp;
     805              :    }
     806              : 
     807              : 
     808            0 :    return 0;
     809              : }
     810              : 
     811              : } //namespace app
     812              : } //namespace MagAOX
     813              : 
     814              : #endif //zaberCtrl_hpp
        

Generated by: LCOV version 2.0-1