11 #include "../../libMagAOX/libMagAOX.hpp"
12 #include "../../magaox_git_version.h"
136 int moveTo(
const double & pos );
190 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.");
192 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.");
194 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.");
196 config.add(
"stage.maxCounts",
"",
"stage.maxCounts", argType::Required,
"stage",
"maxCounts",
false,
"unsigned long",
"The maximum counts possible for this stage.");
236 #ifndef ZABERCTRL_TEST_NOLOG
237 log<software_error>({__FILE__,__LINE__});
247 #ifndef ZABERCTRL_TEST_NOLOG
248 log<software_error>({__FILE__,__LINE__});
300 log<software_error>({__FILE__,__LINE__});
308 log<software_error>({__FILE__, __LINE__});
345 static int last_moving = -10;
347 bool changed =
false;
403 log<software_error>({__FILE__, __LINE__});
419 pcf::IndiProperty indiP_stageHome = pcf::IndiProperty(pcf::IndiProperty::Text);
421 indiP_stageHome.setName(
"req_home");
422 indiP_stageHome.setPerm(pcf::IndiProperty::ReadWrite);
423 indiP_stageHome.setState(pcf::IndiProperty::Idle);
424 indiP_stageHome.add(pcf::IndiElement(
m_stageName));
437 pcf::IndiProperty indiP_stageHalt = pcf::IndiProperty(pcf::IndiProperty::Text);
439 indiP_stageHalt.setName(
"req_halt");
440 indiP_stageHalt.setPerm(pcf::IndiProperty::ReadWrite);
441 indiP_stageHalt.setState(pcf::IndiProperty::Idle);
442 indiP_stageHalt.add(pcf::IndiElement(
m_stageName));
461 if(target < 0)
return 0;
465 pcf::IndiProperty indiP_stageTgtPos = pcf::IndiProperty(pcf::IndiProperty::Number);
467 indiP_stageTgtPos.setName(
"tgt_pos");
468 indiP_stageTgtPos.setPerm(pcf::IndiProperty::ReadWrite);
469 indiP_stageTgtPos.setState(pcf::IndiProperty::Idle);
470 indiP_stageTgtPos.add(pcf::IndiElement(
m_stageName));
486 if(
ipRecv.find(
"target") )
488 target =
ipRecv[
"target"].get<
double>();
507 log<text_log>(
"abs move to " + std::to_string(target) +
" rejected due to already moving");
511 log<text_log>(
"moving stage to " + std::to_string(target));
513 std::lock_guard<std::mutex> guard(m_indiMutex);
528 if(
ipRecv.find(
"target") )
530 target =
ipRecv[
"target"].get<
double>();
535 if(
ipRecv.find(
"current") )
537 target =
ipRecv[
"current"].get<
double>();
548 log<text_log>(
"rel move rejected due to already moving");
552 log<text_log>(
"moving stage by " + std::to_string(target));
554 std::lock_guard<std::mutex> guard(m_indiMutex);
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));
565 if( sendNewProperty(indiP_stageTgtPos, m_stageName, target) < 0 )
return log<
software_error,-1>({__FILE__,__LINE__});
568 m_tgtRawPos = target;
569 m_tgtPos = m_tgtRawPos / m_countsPerMillimeter;
581 if(
ipRecv.find(m_stageName) !=
true )
586 m_indiP_stageState =
ipRecv;
588 std::string sstr =
ipRecv[m_stageName].get<std::string>();
590 std::lock_guard<std::mutex> guard(m_indiMutex);
592 if(sstr ==
"POWEROFF")
597 else if(sstr ==
"POWERON")
602 else if(sstr ==
"NODEVICE")
607 else if(sstr ==
"NOTCONNECTED")
612 else if(sstr ==
"CONNECTED")
617 else if(sstr ==
"NOTHOMED")
622 else if(sstr ==
"HOMING")
628 else if(sstr ==
"READY")
630 if(m_homingState == 0)
640 else if(sstr ==
"OPERATING")
645 else if(sstr ==
"SHUTDOWN")
650 else if(sstr ==
"FAILURE")
655 else if(sstr ==
"ERROR")
673 if(
ipRecv.find(m_stageName) !=
true )
678 std::lock_guard<std::mutex> guard(m_indiMutex);
680 long maxRawPos =
ipRecv[m_stageName].get<
long>();
682 if(maxRawPos > 10000000000000 || maxRawPos < 0)
return 0;
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);
696 if(
ipRecv.find(m_stageName) !=
true )
701 std::lock_guard<std::mutex> guard(m_indiMutex);
703 m_rawPos =
ipRecv[m_stageName].get<
double>();
705 m_pos = m_rawPos / m_countsPerMillimeter;
727 if(
ipRecv.find(m_stageName) !=
true )
733 std::string test =
ipRecv[m_stageName].get<std::string>();
740 std::lock_guard<std::mutex> guard(m_indiMutex);
742 m_tgtRawPos =
ipRecv[m_stageName].get<
double>();
743 m_tgtPos = m_tgtRawPos / m_countsPerMillimeter;
763 if(
ipRecv.find(m_stageName) !=
true )
768 std::lock_guard<std::mutex> guard(m_indiMutex);
770 m_stageTemp =
ipRecv[m_stageName].get<
double>();
794 static double last_pos =
m_pos - 1000;
795 static double last_rawPos =
m_rawPos;
The base-class for MagAO-X applications.
void updateIfChanged(pcf::IndiProperty &p, const std::string &el, const T &newVal, pcf::IndiProperty::PropertyStateType ipState=pcf::IndiProperty::Ok)
Update an INDI property element value if it has changed.
std::string m_configName
The name of the configuration file (minus .conf).
stateCodes::stateCodeT state()
Get the current state code.
int registerIndiPropertyNew(pcf::IndiProperty &prop, int(*)(void *, const pcf::IndiProperty &))
Register an INDI property which is exposed for others to request a New Property for.
indiDriver< MagAOXApp > * m_indiDriver
The INDI driver wrapper. Constructed and initialized by execute, which starts and stops communication...
void updateSwitchIfChanged(pcf::IndiProperty &p, const std::string &el, const pcf::IndiElement::SwitchStateType &newVal, pcf::IndiProperty::PropertyStateType ipState=pcf::IndiProperty::Ok)
Update an INDI switch element value if it has changed.
static int log(const typename logT::messageT &msg, logPrioT level=logPrio::LOG_DEFAULT)
Make a log entry.
int createROIndiNumber(pcf::IndiProperty &prop, const std::string &propName, const std::string &propLabel="", const std::string &propGroup="")
Create a ReadOnly INDI Number property.
int registerIndiPropertyReadOnly(pcf::IndiProperty &prop)
Register an INDI property which is read only.
std::mutex m_indiMutex
Mutex for locking INDI communications.
int sendNewProperty(const pcf::IndiProperty &ipSend, const std::string &el, const T &newVal)
Send a newProperty command to another device (using the INDI Client interface)
MagAO-X standard motion stage interface.
int loadConfig(mx::app::appConfigurator &config)
load the configuration system results
int onPowerOff()
Actions on power off.
std::vector< std::string > m_presetNames
The names of each position on the stage.
bool m_powerOnHome
If true, then the motor is homed at startup (by this software or actual power on)
float m_preset_target
The target numerical preset position [1.0 is index 0 in the preset name vector].
pcf::IndiProperty m_indiP_home
Command the stage to home. .
bool m_defaultPositions
Flag controlling whether the default preset positions (the vector index) are set in loadConfig.
int updateINDI()
Update the INDI properties for this device controller.
int setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
int m_homePreset
If >=0, this preset position is moved to after homing.
int8_t m_moving
Whether or not the stage is moving. -2 means powered off, -1 means not homed, 0 means not moving,...
pcf::IndiProperty m_indiP_stop
Command the stage to halt.
pcf::IndiProperty m_indiP_preset
The position of the stage in presets.
float m_preset
The current numerical preset position [1.0 is index 0 in the preset name vector].
bool m_fractionalPresets
Flag to set in constructor determining if fractional presets are allowed. Used for INDI/GUIs.
int appStartup()
Startup function.
std::vector< float > m_presetPositions
The positions, in arbitrary units, of each preset. If 0, then the integer position number (starting f...
int recordStage(bool force=false)
int8_t m_movingState
Used to track the type of command. If > 1 this is a command to move to a preset. If 0 then it is a mo...
The MagAO-X Zaber Stage Controller.
double m_pos
Current position in mm.
pcf::IndiProperty m_indiP_stageMaxRawPos
virtual int appLogic()
Implementation of the FSM for zaberCtrl.
virtual int appStartup()
Startup function.
std::string m_lowLevelName
virtual void setupConfig()
Setup the configuration of this stage controller.
friend class zaberCtrl_test
int moveTo(const double &pos)
Move to a new position in mm.
zaberCtrl()
Default c'tor.
pcf::IndiProperty m_indiP_maxPos
INDI_NEWCALLBACK_DECL(zaberCtrl, m_indiP_rawPos)
pcf::IndiProperty m_indiP_stageTemp
unsigned long m_maxRawPos
Maximum counts available on this stage.
double m_tgtRawPos
Target raw position in counts.
int stop()
Stop the stage motion immediately.
std::string m_stageName
The name of this stage used for accessing via zaberLowLevel.
double m_maxPos
Maximum position in mm available on this stage.
virtual int appShutdown()
Shutdown the app.
pcf::IndiProperty m_indiP_rawPos
int m_homingState
The homing state, tracks the stages of homing.
int startHoming()
Start a high-level homing sequence.
~zaberCtrl() noexcept
D'tor, declared and defined for noexcept.
pcf::IndiProperty m_indiP_temp
int loadConfigImpl(mx::app::appConfigurator &_config)
Implementation of loadConfig logic, separated for testing.
pcf::IndiProperty m_indiP_stageState
virtual void loadConfig()
Load the stage configuration.
pcf::IndiProperty m_indiP_stageTgtPos
INDI_NEWCALLBACK_DECL(zaberCtrl, m_indiP_pos)
int recordZaber(bool force=false)
double m_countsPerMillimeter
Counts per millimeter calibration of this stage.
double m_tgtPos
Target position in mm.
pcf::IndiProperty m_indiP_pos
INDI_SETCALLBACK_DECL(zaberCtrl, m_indiP_stageTgtPos)
double m_stageTemp
Temperature reported by the stage.
pcf::IndiProperty m_indiP_stageRawPos
double m_rawPos
Current raw position in counts.
INDI_SETCALLBACK_DECL(zaberCtrl, m_indiP_stageState)
INDI_SETCALLBACK_DECL(zaberCtrl, m_indiP_stageRawPos)
int recordTelem(const telem_stage *)
INDI_SETCALLBACK_DECL(zaberCtrl, m_indiP_stageTemp)
INDI_SETCALLBACK_DECL(zaberCtrl, m_indiP_stageMaxRawPos)
#define INDI_NEWCALLBACK(prop)
Get the name of the static callback wrapper for a new property.
#define REG_INDI_SETPROP(prop, devName, propName)
Register a SET INDI property with the class, using the standard callback name.
@ OPERATING
The device is operating, other than homing.
@ POWEROFF
The device power is off.
@ NODEVICE
No device exists for the application to control.
@ NOTHOMED
The device has not been homed.
@ HOMING
The device is homing.
@ FAILURE
The application has failed, should be used when m_shutdown is set for an error.
@ ERROR
The application has encountered an error, from which it is recovering (with or without intervention)
@ READY
The device is ready for operation, but is not operating.
@ CONNECTED
The application has connected to the device or service.
@ UNINITIALIZED
The application is unitialized, the default.
@ INITIALIZED
The application has been initialized, set just before calling appStartup().
@ NOTCONNECTED
The application is not connected to the device or service.
@ POWERON
The device power is on.
int addNumberElement(pcf::IndiProperty &prop, const std::string &name, const T &min, const T &max, const T &step, const std::string &format, const std::string &label="")
Add a standard INDI Number element.
INDI_VALIDATE_CALLBACK_PROPS(function, ipRecv)
const pcf::IndiProperty & ipRecv
INDI_SETCALLBACK_DEFN(adcTracker, m_indiP_teldata)(const pcf
updateIfChanged(m_indiP_angle, "target", m_angle)
INDI_NEWCALLBACK_DEFN(acesxeCtrl, m_indiP_windspeed)(const pcf
constexpr static logPrioT LOG_CRITICAL
The process can not continue and will shut down (fatal)
constexpr static logPrioT LOG_ERROR
An error has occured which the software will attempt to correct.
constexpr static logPrioT LOG_WARNING
A condition has occurred which may become an error, but the process continues.
A device base class which saves telemetry.
int loadConfig(appConfigurator &config)
Load the device section from an application configurator.
int appLogic()
Perform telemeter application logic.
int setupConfig(appConfigurator &config)
Setup an application configurator for the device section.
int checkRecordTimes(const telT &tel, telTs... tels)
Check the time of the last record for each telemetry type and make an entry if needed.
Log entry recording stdMotionStage status.
Log entry recording zaber stage specific status.
A simple text log, a string-type log.