7 #ifndef t2wOffloader_hpp
8 #define t2wOffloader_hpp
12 #include <mx/improc/eigenCube.hpp>
13 #include <mx/improc/eigenImage.hpp>
14 #include <mx/sigproc/gramSchmidt.hpp>
15 #include <mx/math/templateBLAS.hpp>
17 #include "../../libMagAOX/libMagAOX.hpp"
18 #include "../../magaox_git_version.h"
205 config.add(
"integrator.fpsSource",
"",
"integrator.fpsSource", argType::Required,
"integrator",
"fpsSource",
false,
"string",
"Device name for getting fps of the loop. This device should have *.fps.current. Default is camwfs");
206 config.add(
"integrator.navgSource",
"",
"integrator.navgSource", argType::Required,
"integrator",
"navgSource",
false,
"string",
"Device name for getting navg of tweeter-ave. This device should have *.fps.current. Default is dmtweeter-avg.");
208 config.add(
"offload.respMPath",
"",
"offload.respMPath", argType::Required,
"offload",
"respMPath",
false,
"string",
"The path to the response matrix.");
209 config.add(
"offload.channel",
"",
"offload.channel", argType::Required,
"offload",
"channel",
false,
"string",
"The DM channel to offload to.");
211 config.add(
"offload.gain",
"",
"offload.gain", argType::Required,
"offload",
"gain",
false,
"float",
"The starting offload gain. Default is 0.1.");
212 config.add(
"offload.leak",
"",
"offload.leak", argType::Required,
"offload",
"leak",
false,
"float",
"The starting offload leak. Default is 0.0.");
213 config.add(
"offload.startupOffloading",
"",
"offload.startupOffloading", argType::Required,
"offload",
"startupOffloading",
false,
"bool",
"Flag controlling whether offloading is on at startup. Default is false.");
214 config.add(
"offload.actLim",
"",
"offload.actLim", argType::Required,
"offload",
"actLim",
false,
"float",
"The woofer actuator command limit. Default is 7.0.");
216 config.add(
"offload.tweeterModes",
"",
"offload.tweeterModes", argType::Required,
"offload",
"tweeterModes",
false,
"string",
"File containing the tweeter modes to use for offloading");
217 config.add(
"offload.tweeterMask",
"",
"offload.tweeterMask", argType::Required,
"offload",
"tweeterMask",
false,
"string",
"File containing the tweeter mask.");
218 config.add(
"offload.maxModes",
"",
"offload.maxModes", argType::Required,
"offload",
"maxModes",
false,
"string",
"Maximum number of modes for modal offloading.");
219 config.add(
"offload.numModes",
"",
"offload.numModes", argType::Required,
"offload",
"numModes",
false,
"string",
"Number of modes to offload. 0 means use actuator offloading.");
233 _config(
m_gain,
"offload.gain");
234 _config(
m_leak,
"offload.leak");
235 _config(
m_actLim,
"offload.actLim");
241 bool startupOffloading =
false;
243 if(_config.isSet(
"offload.startupOffloading"))
245 _config(startupOffloading,
"offload.startupOffloading");
262 createStandardIndiNumber<float>(
m_indiP_gain,
"gain", 0, 1, 0,
"%0.2f");
268 log<software_error>({__FILE__,__LINE__});
273 createStandardIndiNumber<float>(
m_indiP_leak,
"leak", 0, 1, 0,
"%0.2f");
279 log<software_error>({__FILE__,__LINE__});
283 createStandardIndiNumber<float>(
m_indiP_actLim,
"actLim", 0, 8, 0,
"%0.2f");
289 log<software_error>({__FILE__,__LINE__});
295 log<software_error>({__FILE__,__LINE__});
307 log<software_error>({__FILE__,__LINE__});
311 createStandardIndiNumber<int>(
m_indiP_numModes,
"numModes", 0, 97, 0,
"%d");
317 log<software_error>({__FILE__,__LINE__});
324 log<software_error>({__FILE__,__LINE__});
335 log<software_error>({__FILE__,__LINE__});
357 log<software_error>({__FILE__, __LINE__});
391 static_cast<void>(dummy);
425 log<software_error>({__FILE__, __LINE__,
m_dmChannel +
" not opened."});
456 static_cast<void>(dummy);
482 for(
int ii = 0; ii <
m_woofer.rows(); ++ii)
484 for(
int jj = 0; jj <
m_woofer.cols(); ++jj)
532 mx::improc::eigenCube<float> tmodes;
534 mx::fits::fitsFile<float> ff;
537 std::cerr <<
"Tweeter modes: " << tmodes.rows() <<
" x " << tmodes.cols() <<
" x " << tmodes.planes() <<
"\n";
547 for(
int p=0; p < tmodes.planes(); ++p)
550 float norm = (tmodes.image(p)).square().sum();
551 tmodes.image(p) /= sqrt(norm);
564 mx::improc::eigenImage<realT> win, wout;
572 Eigen::Map<Eigen::Matrix<float,-1,-1>>(wout.data(), wout.rows()*wout.cols(),1) =
m_twRespM.matrix() * Eigen::Map<Eigen::Matrix<float,-1,-1>>(win.data(), win.rows()*win.cols(),1);
576 ff.write(
"/tmp/wModes.fits",
m_wModes);
584 if(
ipRecv.getName() != m_indiP_gain.getName())
586 log<software_error>({__FILE__, __LINE__,
"invalid indi property received"});
592 if( indiTargetUpdate( m_indiP_gain, target,
ipRecv,
true) < 0)
594 log<software_error>({__FILE__,__LINE__});
610 if(
ipRecv.getName() != m_indiP_leak.getName())
612 log<software_error>({__FILE__, __LINE__,
"invalid indi property received"});
618 if( indiTargetUpdate( m_indiP_leak, target,
ipRecv,
true) < 0)
620 log<software_error>({__FILE__,__LINE__});
636 if(
ipRecv.getName() != m_indiP_actLim.getName())
638 log<software_error>({__FILE__, __LINE__,
"invalid indi property received"});
644 if( indiTargetUpdate( m_indiP_actLim, target,
ipRecv,
true) < 0)
646 log<software_error>({__FILE__,__LINE__});
662 if(
ipRecv.getName() != m_indiP_zero.getName())
664 log<software_error>({__FILE__, __LINE__,
"invalid indi property received"});
668 if(
ipRecv[
"request"].getSwitchState() == pcf::IndiElement::On)
678 if(
ipRecv.getName() != m_indiP_numModes.getName())
680 log<software_error>({__FILE__, __LINE__,
"invalid indi property received"});
686 if( indiTargetUpdate( m_indiP_numModes, target,
ipRecv,
true) < 0)
688 log<software_error>({__FILE__,__LINE__});
697 log<text_log>(
"set number of modes to " + std::to_string(m_numModes),
logPrio::LOG_NOTICE);
704 if(
ipRecv.getName() != m_indiP_offloadToggle.getName())
706 log<software_error>({__FILE__, __LINE__,
"invalid indi property received"});
711 if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::On)
726 if(
ipRecv[
"toggle"].getSwitchState() == pcf::IndiElement::Off)
730 m_offloading =
false;
742 if(
ipRecv.getName() != m_indiP_fpsSource.getName())
744 log<software_error>({__FILE__, __LINE__,
"Invalid INDI property."});
748 if(
ipRecv.find(
"current") !=
true )
753 std::lock_guard<std::mutex> guard(m_indiMutex);
755 realT fps =
ipRecv[
"current"].get<
float>();
760 std::cout <<
"Got fps: " << m_fps <<
"\n";
769 if(
ipRecv.getName() != m_indiP_navgSource.getName())
771 log<software_error>({__FILE__, __LINE__,
"Invalid INDI property."});
775 if(
ipRecv.find(
"current") !=
true )
780 std::lock_guard<std::mutex> guard(m_indiMutex);
782 realT navg =
ipRecv[
"current"].get<
float>();
787 std::cout <<
"Got navg: " << m_navg <<
"\n";
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.
int createStandardIndiRequestSw(pcf::IndiProperty &prop, const std::string &name, const std::string &label="", const std::string &group="")
Create a standard R/W INDI switch with a single request element.
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.
int createStandardIndiToggleSw(pcf::IndiProperty &prop, const std::string &name, const std::string &label="", const std::string &group="")
Create a standard R/W INDI switch with a single toggle element.
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 appStartup()
Startup function.
uint32_t m_width
The width of the images in the stream.
int setupConfig(mx::app::appConfigurator &config)
Setup the configuration system.
int updateINDI()
Update the INDI properties for this device controller.
int appLogic()
Checks the shmimMonitor thread.
uint32_t m_height
The height of the images in the stream.
int appShutdown()
Shuts down the shmimMonitor thread.
uint8_t m_dataType
The ImageStreamIO type code.
int loadConfig(mx::app::appConfigurator &config)
load the configuration system results
size_t m_typeSize
The size of the type, in bytes. Result of sizeof.
int allocate(const dev::shmimT &dummy)
t2wOffloader()
Default c'tor.
mx::improc::eigenImage< realT > m_twRespM
mx::improc::eigenImage< realT > m_tweeterMask
INDI_NEWCALLBACK_DECL(t2wOffloader, m_indiP_actLim)
mx::improc::eigenImage< realT > m_tweeter
mx::improc::eigenImage< realT > m_modeAmps
pcf::IndiProperty m_indiP_leak
int processImage(void *curr_src, const dev::shmimT &dummy)
uint32_t m_dmHeight
The height of the image.
friend class t2wOffloader_test
~t2wOffloader() noexcept
D'tor, declared and defined for noexcept.
pcf::IndiProperty m_indiP_fps
pcf::IndiProperty m_indiP_fpsSource
pcf::IndiProperty m_indiP_numModes
int m_navg
Current navg from the averager.
virtual int appLogic()
Implementation of the FSM for t2wOffloader.
mx::improc::eigenCube< float > m_tModesOrtho
INDI_SETCALLBACK_DECL(t2wOffloader, m_indiP_navgSource)
std::string m_tweeterModeFile
File containing the tweeter modes to use for offloading.
virtual int appStartup()
Startup function.
float realT
Floating point type in which to do all calculations.
pcf::IndiProperty m_indiP_offloadToggle
pcf::IndiProperty m_indiP_navgSource
INDI_NEWCALLBACK_DECL(t2wOffloader, m_indiP_gain)
virtual void setupConfig()
int loadConfigImpl(mx::app::appConfigurator &_config)
Implementation of loadConfig logic, separated for testing.
float m_actLim
the upper limit on woofer actuator commands. default is 7.0.
INDI_NEWCALLBACK_DECL(t2wOffloader, m_indiP_leak)
INDI_NEWCALLBACK_DECL(t2wOffloader, m_indiP_offloadToggle)
mx::improc::eigenImage< realT > m_woofer
uint32_t m_dmWidth
The width of the image.
mx::improc::eigenImage< realT > m_wooferDelta
INDI_NEWCALLBACK_DECL(t2wOffloader, m_indiP_zero)
INDI_SETCALLBACK_DECL(t2wOffloader, m_indiP_fpsSource)
std::string m_tweeterMaskFile
float m_fps
Current FPS from the FPS source.
virtual void loadConfig()
dev::shmimMonitor< t2wOffloader > shmimMonitorT
virtual int appShutdown()
Shutdown the app.
INDI_NEWCALLBACK_DECL(t2wOffloader, m_indiP_numModes)
pcf::IndiProperty m_indiP_gain
uint8_t m_dmDataType
The ImageStreamIO type code.
pcf::IndiProperty m_indiP_actLim
mx::improc::eigenCube< float > m_wModes
std::string m_twRespMPath
size_t m_dmTypeSize
The size of the type, in bytes.
pcf::IndiProperty m_indiP_zero
#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.
void updateSwitchIfChanged(pcf::IndiProperty &p, const std::string &el, const pcf::IndiElement::SwitchStateType &newVal, indiDriverT *indiDriver, pcf::IndiProperty::PropertyStateType newState=pcf::IndiProperty::Ok)
Update the value of the INDI element, but only if it has changed.
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
std::unique_lock< std::mutex > lock(m_indiMutex)
constexpr static logPrioT LOG_NOTICE
A normal but significant condition.