LCOV - code coverage report
Current view: top level - include/ao/sim - leakyIntegrator.hpp (source / functions) Coverage Total Hit
Test: mxlib Lines: 17.3 % 110 19
Test Date: 2026-08-30 22:23:37 Functions: 16.7 % 18 3

            Line data    Source code
       1              : /** \file leakyIntegrator.hpp
       2              :  * \author Jared R. Males (jaredmales@gmail.com)
       3              :  * \brief Declares and defines the leaky integrator controller class for AO control.
       4              :  * \ingroup mxAO_sim_files
       5              :  *
       6              :  */
       7              : 
       8              : #ifndef __leakyIntegrator_hpp__
       9              : #define __leakyIntegrator_hpp__
      10              : 
      11              : #include <fstream>
      12              : #include <string>
      13              : #include <vector>
      14              : 
      15              : #include <Eigen/Dense>
      16              : 
      17              : #include "../../error/mxErrorOld.hpp"
      18              : #include "../../ioutils/stringUtils.hpp"
      19              : 
      20              : #include "wavefront.hpp"
      21              : 
      22              : namespace mx
      23              : {
      24              : namespace AO
      25              : {
      26              : namespace sim
      27              : {
      28              : 
      29              : template <typename _realT>
      30              : struct wfMeasurement
      31              : {
      32              :     typedef _realT realT;
      33              : 
      34              :     realT iterNo;
      35              : 
      36              :     typedef Eigen::Array<realT, Eigen::Dynamic, Eigen::Dynamic> commandT;
      37              : 
      38              :     commandT measurement;
      39              : };
      40              : 
      41              : /// Implements the leaky integrator controller.
      42              : /**
      43              :  * \tparam _realT is the floating point type for all calculations.
      44              :  */
      45              : template <typename _realT>
      46              : class leakyIntegrator
      47              : {
      48              : 
      49              :   public:
      50              :     /// The real data type
      51              :     typedef _realT realT;
      52              : 
      53              :     /// The wavefront data type
      54              :     typedef wavefront<realT> wavefrontT;
      55              : 
      56              :     /// The command type
      57              :     typedef wfMeasurement<realT> commandT;
      58              : 
      59              :     /// The image type, used here as a general storage array
      60              :     typedef Eigen::Array<realT, Eigen::Dynamic, Eigen::Dynamic> imageT;
      61              : 
      62              :     /// Default c'tor.
      63              :     leakyIntegrator();
      64              : 
      65              :   protected:
      66              :     int _nModes; ///< The number of modes being filtered.
      67              : 
      68              :     bool _openLoop; ///< If true, then commands are not integrated.
      69              : 
      70              :     int _closingDelay; ///< If > 0, then the gains are ramped linearly up to this value. Default = 0.
      71              : 
      72              :     int _lowOrders; ///< If > 0, then this sets the maximum mode number which is filtered. All remaining modes are set
      73              :                     ///< to 0.  Default = 0.
      74              : 
      75              :     imageT _gains; ///< Column-vector of gains
      76              : 
      77              :     imageT _leaks; ///< Column-vector of leaks
      78              : 
      79              :     imageT _commands; ///< Column-vector past commands
      80              : 
      81              :   public:
      82              :     int _lowOrderDelay;
      83              : 
      84              :     /// Allocate and initialize all state.
      85              :     /**
      86              :      * \returns 0 on success, a negative integer otherwise.
      87              :      */
      88              :     int initialize( int nModes /**< [in] the number of modes to be filtered */ );
      89              : 
      90              :     /// Get the number of modes
      91              :     /** nModes is only set by calling initialize.
      92              :      *
      93              :      * \returns the current value of _nModes
      94              :      */
      95              :     int nModes();
      96              : 
      97              :     /// Set the _openLoop flag.
      98              :     /** If _openLoop is true, then commands are not filtered.
      99              :      *
     100              :      * \returns 0 on success, a negative integer on error.
     101              :      */
     102              :     int openLoop( bool ol /**< The new value of _openLoop */ );
     103              : 
     104              :     /// Get the value of the _openLoop flag.
     105              :     /**
     106              :      * \returns the current value of _openLoop.
     107              :      */
     108              :     bool openLoop();
     109              : 
     110              :     /// Set _closingDelay.
     111              :     /** If _closingDelay  > 0, then the gains are ramped linearly up to this value.
     112              :      *
     113              :      * \returns 0 on success, a negative integer on error.
     114              :      */
     115              :     int closingDelay( int cd /**< The new value of _closingDelay */ );
     116              : 
     117              :     /// Get the value of the _closingDelay.
     118              :     /**
     119              :      * \returns the current value of _closingDelay.
     120              :      */
     121              :     int closingDelay();
     122              : 
     123              :     /// Set _lowOrders.
     124              :     /** If _lowOrders > 0, then this sets the maximum mode number which is filtered. All remaining modes are set to 0.
     125              :      *
     126              :      * \returns 0 on success, a negative integer on error.
     127              :      */
     128              :     int lowOrders( int lo /**< The new value of _lowOrders */ );
     129              : 
     130              :     /// Get the value of the _lowOrders.
     131              :     /**
     132              :      * \returns the current value of _lowOrders.
     133              :      */
     134              :     int lowOrders();
     135              : 
     136              :     /// Get the gain for a single mode.
     137              :     /** \returns the gain value if mode exists.
     138              :      */
     139              :     realT gain( int i /**< [in] the mode number*/ );
     140              : 
     141              :     /// Set the gain for a single mode.
     142              :     /**
     143              :      * \returns 0 on success, negative number on error.
     144              :      */
     145              :     int gain( int i,  ///< [in] the mode number
     146              :               realT g ///< [in] the new gain value
     147              :     );
     148              : 
     149              :     /// Set the gain for all modes to a single value
     150              :     /**
     151              :      * \returns 0 on success, negative number on error.
     152              :      */
     153              :     int gains( realT g /**< [in] the new gain value*/ );
     154              : 
     155              :     /// Set the gains for all modes, using a vector to specify each gain
     156              :     /** The vector must be exactly as long as _nModes.
     157              :      *
     158              :      * \returns 0 on success, negative number on error.
     159              :      */
     160              :     int gains( const std::vector<realT> &vgains /**< [in] vector of gains.*/ );
     161              : 
     162              :     /// Set the gains for all modes, using a file to specify each gain
     163              :     /** The file format is a simple ASCII single column, with 1 gain per line.
     164              :      * Must be exactly as long as _nModes.
     165              :      *
     166              :      * \returns 0 on success, negative number on error.
     167              :      */
     168              :     int gains( const std::string &ogainf /**< [in] the name of the file, full path */ );
     169              : 
     170              :     /// Set the leak for a single mode.
     171              :     /**
     172              :      * \returns 0 on success, negative number on error.
     173              :      */
     174              :     int leak( int i,  ///< [in] the mode number
     175              :               realT l ///< [in] the new leak value for this mode
     176              :     );
     177              : 
     178              :     /// Set a leak for all modes.
     179              :     /**
     180              :      * \returns 0 on success, negative number on error.
     181              :      */
     182              :     int leaks( realT l /**< [in] the new leak value to set for all modes */ );
     183              : 
     184              :     /// Allocate the provided command structures
     185              :     /** Used by the calling system to allocate the commands being passed between components.
     186              :      *
     187              :      * \returns 0 on success, negative number on error.
     188              :      */
     189              :     int initMeasurements( commandT &filtAmps, ///< The structure to contain the filtered commands
     190              :                           commandT &rawAmps   ///< The structure to contain the raw commands
     191              :     );
     192              : 
     193              :     /// Apply the leaky integrator
     194              :     /**
     195              :      * \returns 0 on success, negative number on error.
     196              :      */
     197              :     int filterCommands( commandT &filtAmps, ///< [out] the filtered commands
     198              :                         commandT &rawAmps,  ///< [in] the raw commands
     199              :                         int iterNo          ///< [in] The current iteration number
     200              :     );
     201              : };
     202              : 
     203              : template <typename realT>
     204            1 : leakyIntegrator<realT>::leakyIntegrator()
     205              : {
     206            1 :     _nModes = 0;
     207              : 
     208            1 :     _openLoop = false;
     209              : 
     210            1 :     _closingDelay = 0;
     211              : 
     212            1 :     _lowOrders = 0;
     213            1 :     _lowOrderDelay = 0;
     214            1 : }
     215              : 
     216              : template <typename realT>
     217            1 : int leakyIntegrator<realT>::initialize( int nModes )
     218              : {
     219            1 :     _nModes = nModes;
     220              : 
     221            1 :     _gains.resize( 1, nModes );
     222            1 :     _leaks.resize( 1, nModes );
     223            1 :     _commands.resize( 1, nModes );
     224              : 
     225            1 :     _gains.setZero();
     226              : 
     227            1 :     _leaks.setZero();
     228              : 
     229            1 :     _commands.setZero();
     230              : 
     231            1 :     return 0;
     232              : }
     233              : 
     234              : template <typename realT>
     235            0 : int leakyIntegrator<realT>::nModes()
     236              : {
     237            0 :     return _nModes;
     238              : }
     239              : 
     240              : template <typename realT>
     241            0 : int leakyIntegrator<realT>::openLoop( bool ol )
     242              : {
     243            0 :     _openLoop = ol;
     244            0 :     return 0;
     245              : }
     246              : 
     247              : template <typename realT>
     248            0 : bool leakyIntegrator<realT>::openLoop()
     249              : {
     250            0 :     return _openLoop;
     251              : }
     252              : 
     253              : template <typename realT>
     254            0 : int leakyIntegrator<realT>::closingDelay( int cd )
     255              : {
     256            0 :     _closingDelay = cd;
     257              : 
     258            0 :     return 0;
     259              : }
     260              : 
     261              : template <typename realT>
     262            0 : int leakyIntegrator<realT>::closingDelay()
     263              : {
     264            0 :     return _closingDelay;
     265              : }
     266              : 
     267              : template <typename realT>
     268            0 : int leakyIntegrator<realT>::lowOrders( int lo )
     269              : {
     270            0 :     _lowOrders = lo;
     271              : 
     272            0 :     return 0;
     273              : }
     274              : 
     275              : template <typename realT>
     276            0 : int leakyIntegrator<realT>::lowOrders()
     277              : {
     278            0 :     return _lowOrders;
     279              : }
     280              : 
     281              : template <typename realT>
     282            0 : realT leakyIntegrator<realT>::gain( int i )
     283              : {
     284            0 :     if( i < 0 || i >= _nModes )
     285              :     {
     286            0 :         mxError( "leakyIntegrator::gain", MXE_INVALIDARG, "mode index out of range" );
     287            0 :         return 0; ///\retval 0 if the mode doesn't exist.
     288              :     }
     289              : 
     290            0 :     return _gains( i );
     291              : }
     292              : 
     293              : template <typename realT>
     294            0 : int leakyIntegrator<realT>::gain( int i, realT g )
     295              : {
     296            0 :     if( i < 0 || i >= _nModes )
     297              :     {
     298            0 :         mxError( "leakyIntegrator::gain", MXE_INVALIDARG, "mode index out of range" );
     299            0 :         return 0; ///\retval 0 if the mode doesn't exist.
     300              :     }
     301              : 
     302            0 :     _gains( 0, i ) = g;
     303              : 
     304            0 :     return 0;
     305              : }
     306              : 
     307              : template <typename realT>
     308            0 : int leakyIntegrator<realT>::gains( realT g )
     309              : {
     310            0 :     for( int i = 0; i < _gains.cols(); ++i )
     311              :     {
     312            0 :         _gains( 0, i ) = g;
     313              :     }
     314              : 
     315            0 :     return 0;
     316              : }
     317              : 
     318              : template <typename realT>
     319            0 : int leakyIntegrator<realT>::gains( const std::vector<realT> &gains )
     320              : {
     321              : 
     322            0 :     if( gains.size() != _gains.cols() )
     323              :     {
     324            0 :         mxError( "leakyIntegrator::gain", MXE_SIZEERR, "input gain vector not same size as number of modes" );
     325            0 :         return -1; ///\retval -1 on vector size mismatch
     326              :     }
     327              : 
     328            0 :     for( int i = 0; i < _gains.cols(); ++i )
     329              :     {
     330            0 :         _gains( 0, i ) = gains[i];
     331              :     }
     332              : 
     333            0 :     return 0;
     334              : }
     335              : 
     336              : template <typename realT>
     337            0 : int leakyIntegrator<realT>::gains( const std::string &ogainf )
     338              : {
     339            0 :     std::ifstream fin;
     340            0 :     fin.open( ogainf );
     341              : 
     342            0 :     if( !fin.good() )
     343              :     {
     344            0 :         mxError( "leakyIntegrator::gains", MXE_FILEOERR, "could not open gan file" );
     345            0 :         return -1; /// \retval -1 if file open fails
     346              :     }
     347              : 
     348            0 :     std::string tmpstr;
     349              :     realT g;
     350            0 :     for( int i = 0; i < _gains.cols(); ++i )
     351              :     {
     352            0 :         fin >> tmpstr;
     353            0 :         g = mx::ioutils::convertFromString<realT>( tmpstr );
     354            0 :         gain( i, g );
     355              :     }
     356              : 
     357            0 :     return 0;
     358            0 : }
     359              : 
     360              : template <typename realT>
     361            1 : int leakyIntegrator<realT>::leak( int i, realT l )
     362              : {
     363            1 :     _leaks( 0, i ) = l;
     364              : 
     365            1 :     return 0;
     366              : }
     367              : 
     368              : template <typename realT>
     369            0 : int leakyIntegrator<realT>::leaks( realT l )
     370              : {
     371            0 :     for( int i = 0; i < _leaks.cols(); ++i )
     372            0 :         _leaks( 0, i ) = l;
     373              : 
     374            0 :     return 0;
     375              : }
     376              : 
     377              : template <class realT>
     378            0 : int leakyIntegrator<realT>::initMeasurements( commandT &filtAmps, commandT &rawAmps )
     379              : {
     380            0 :     filtAmps.measurement.resize( 1, _nModes );
     381            0 :     filtAmps.measurement.setZero();
     382              : 
     383            0 :     rawAmps.measurement.resize( 1, _nModes );
     384            0 :     rawAmps.measurement.setZero();
     385              : 
     386            0 :     return 0;
     387              : }
     388              : 
     389              : template <class realT>
     390            0 : int leakyIntegrator<realT>::filterCommands( commandT &filtAmps, commandT &rawAmps, int iterNo )
     391              : {
     392            0 :     filtAmps.iterNo = rawAmps.iterNo;
     393              : 
     394            0 :     if( _openLoop )
     395              :     {
     396            0 :         filtAmps.measurement.setZero();
     397            0 :         return 0;
     398              :     }
     399              : 
     400            0 :     int topN = rawAmps.measurement.cols();
     401              : 
     402            0 :     realT gainF = 1.0;
     403            0 :     realT HOgainF = 0.0;
     404              : 
     405              :     // leaks(0.01);
     406              : 
     407            0 :     if( iterNo < _closingDelay )
     408            0 :         gainF = ( (realT)iterNo ) / _closingDelay;
     409              : 
     410              :     // if( iterNo < 0.55*_closingDelay) leaks(0.1);
     411              : 
     412            0 :     if( _lowOrders > 0 )
     413              :     {
     414            0 :         if( iterNo >= _closingDelay + _lowOrderDelay )
     415              :         {
     416            0 :             _lowOrders = 0;
     417              :         }
     418              :         else
     419              :         {
     420            0 :             topN = _lowOrders;
     421              : 
     422            0 :             if( iterNo >= _closingDelay )
     423              :             {
     424            0 :                 HOgainF = ( (realT)( iterNo - _closingDelay ) ) / ( _lowOrderDelay );
     425              :             }
     426              :         }
     427              :     }
     428              : 
     429            0 :     for( int i = 0; i < topN; ++i )
     430              :     {
     431            0 :         if( std::isnan( rawAmps.measurement( 0, i ) ) || !std::isfinite( rawAmps.measurement( 0, i ) ) )
     432            0 :             rawAmps.measurement( 0, i ) = 0.0;
     433              : 
     434            0 :         _commands( 0, i ) =
     435            0 :             ( 1.0 - _leaks( 0, i ) ) * _commands( 0, i ) + gainF * _gains( 0, i ) * rawAmps.measurement( 0, i );
     436              : 
     437            0 :         filtAmps.measurement( 0, i ) = _commands( 0, i );
     438              :     }
     439              : 
     440            0 :     for( int i = topN; i < rawAmps.measurement.cols(); ++i )
     441              :     {
     442            0 :         if( std::isnan( rawAmps.measurement( 0, i ) ) || !std::isfinite( rawAmps.measurement( 0, i ) ) )
     443            0 :             rawAmps.measurement( 0, i ) = 0.0;
     444              : 
     445            0 :         _commands( 0, i ) =
     446            0 :             ( 1.0 - _leaks( 0, i ) ) * _commands( 0, i ) + HOgainF * _gains( 0, i ) * rawAmps.measurement( 0, i );
     447              : 
     448            0 :         filtAmps.measurement( 0, i ) = _commands( 0, i );
     449              : 
     450              :         // filtAmps.measurement(0,i) = 0;
     451              :     }
     452              : 
     453            0 :     return 0;
     454              : }
     455              : 
     456              : } // namespace sim
     457              : } // namespace AO
     458              : } // namespace mx
     459              : 
     460              : #endif //__leakyIntegrator_hpp__
        

Generated by: LCOV version 2.0-1