mxlib
c++ tools for analyzing astronomical data and other tasks by Jared R. Males. [git repo]
generalIntegrator.hpp
Go to the documentation of this file.
1 /** \file generalIntegrator.hpp
2  * \author Jared R. Males (jaredmales@gmail.com)
3  * \brief Declares and defines a general integrator controller class for AO control.
4  * \ingroup mxAO_sim_files
5  *
6  */
7 
8 #ifndef __generalIntegrator_hpp__
9 #define __generalIntegrator_hpp__
10 
11 namespace mx
12 {
13 namespace AO
14 {
15 namespace sim
16 {
17 
18 template<typename _realT>
19 struct wfMeasurement
20 {
21  typedef _realT realT;
22 
23  realT iterNo;
24 
25  //typedef Eigen::Array< realT, Eigen::Dynamic, Eigen::Dynamic> commandT;
26  typedef std::vector<realT> commandT;
27 
28  commandT measurement;
29 };
30 
31 ///Implements a general integrator controller.
32 /** \todo document the math for the G.I.
33  * \todo document the filter coefficients, etc.
34  *
35  * \tparam _realT is the floating point type for all calculations.
36  */
37 template<typename _realT>
39 {
40 
41 public:
42 
43  ///The real data type
44  typedef _realT realT;
45 
46  ///The real data type
47  typedef std::complex<realT> complexT;
48 
49  ///The wavefront data type
50 // typedef wavefront<realT> wavefrontT;
51 
52  ///The command type
53  typedef wfMeasurement<realT> commandT;
54 
55  ///The image type, used here as a general storage array
56  typedef Eigen::Array< realT, Eigen::Dynamic, Eigen::Dynamic> imageT;
57 
58  ///Default c'tor.
60 
61 
62 protected:
63 
64  int m_nModes {0}; ///< The number of modes being filtered.
65 
66  bool m_openLoop {false}; ///< If true, then commands are not integrated. Default is false.
67 
68  int m_openLoopDelay {0}; ///< If > 0, then the loop is open for this time in time steps. Default is 0.
69 
70  int m_closingRamp {0}; ///< If > 0, then gains are famped linearly up to m_closingGains over this interval in time steps. Default is 0. This is relative m_openLoopDelay.
71 
72  int m_closingDelay {0}; ///< If > 0, then the simple integrator,with m_closingGains is used up to this timestep. This is relative m_openLoopDelay. Default = 0.
73 
74  imageT m_closingGains; ///< Column-vector of gains used for loop closing as simple integrator
75 
76  int m_lowOrders {0}; ///< If > 0, then this sets the maximum mode number which is filtered. All remaining modes are set to 0. Default = 0.
77 
78  imageT m_a;
79  int m_currA;
80 
81  imageT m_b;
82  int m_currB;
83 
84  imageT m_gains; ///< Column-vector of gains
85 
86  imageT m_commandsIn;
87  imageT m_commandsOut;
88 
89 public:
90 
91  ///Allocate and initialize all state.
92  /**
93  * \returns 0 on success, a negative integer otherwise.
94  */
95  int initialize(int nModes /**< [in] the number of modes to be filtered */);
96 
97  ///Get the number of modes
98  /** nModes is only set by calling initialize.
99  *
100  * \returns the current value of m_nModes
101  */
102  int nModes();
103 
104  ///Set the m_openLoop flag.
105  /** If m_openLoop is true, then commands are not filtered.
106  *
107  * \returns 0 on success, a negative integer on error.
108  */
109  int openLoop(bool ol /**< [in] the new value of m_openLoop */ );
110 
111  ///Get the value of the m_openLoop flag.
112  /**
113  * \returns the current value of m_openLoop.
114  */
115  bool openLoop();
116 
117  ///Set the open loop delay.
118  /** If m_openLoopDelay > 0, then the loop is open for this period in time-steps
119  * Requires m_closingDelay > 0.
120  *
121  * \returns 0 on success, a negative integer on error.
122  */
123  int openLoopDelay( int cr /**< [in] The new value of m_openLoopDelay */);
124 
125  ///Get the value of the m_openLoopDelay.
126  /**
127  * \returns the current value of m_openLoopDelay.
128  */
129  int openLoopDelay();
130 
131  ///Set the closing ramp.
132  /** If m_closingRamp > 0, then the gains are ramped linearly up to m_closingGains over this timer interval in timesteps.
133  * Requires m_closingDelay > 0.
134  *
135  * \returns 0 on success, a negative integer on error.
136  */
137  int closingRamp( int cr /**< [in] The new value of m_closingRamp */);
138 
139  ///Get the value of the m_closingRamp.
140  /**
141  * \returns the current value of m_closingRamp.
142  */
143  int closingRamp();
144 
145  ///Set the closing delay.
146  /** If m_closingDelay > 0, then the simple integragor is used until this timestep.
147  *
148  * \returns 0 on success, a negative integer on error.
149  */
150  int closingDelay( int cd /**< [in] The new value of m_closingDelay */);
151 
152  ///Get the value of the m_closingDelay.
153  /**
154  * \returns the current value of m_closingDelay.
155  */
156  int closingDelay();
157 
158  /// Set the simple integrator gains to use during closing.
159  /**
160  * \returns 0 on success
161  * \returns < 0 on error
162  */
163  int closingGains( const std::vector<realT> & gains /**< [in] vector of gains.*/);
164 
165  /// Set the simple integrator gain to use for all modes during closing.
166  /**
167  * \returns 0 on success
168  * \returns < 0 on error
169  */
170  int closingGains(realT g);
171 
172 
173  ///Set m_lowOrders.
174  /** If m_lowOrders > 0, then this sets the maximum mode number which is filtered. All remaining modes are set to 0.
175  *
176  * \returns 0 on success, a negative integer on error.
177  */
178  int lowOrders( int lo /**< [in] The new value of m_lowOrders */);
179 
180  ///Get the value of the m_lowOrders.
181  /**
182  * \returns the current value of m_lowOrders.
183  */
184  int lowOrders();
185 
186  ///Set the size of the IIR vector (the a coefficients)
187  /** This allocates m_a to be m_nModes X n in size.
188  *
189  * \returns 0 on success, negative number on error.
190  */
191  int setASize(int n /**< [in] the number of IIR coefficients */ );
192 
193  ///Set the IIR coefficients for one mode.
194  /**
195  * \returns 0 on success, negative number on error.
196  */
197  int setA( int i, ///< [in] the mode number
198  const imageT & a ///< [in] the IIR coefficients for this mode
199  );
200 
201  ///Set the size of the FIR vector (the b coefficients)
202  /** This allocates m_b to be m_nModes X n in size.
203  *
204  * \returns 0 on success, negative number on error.
205  */
206  int setBSize(int n /**< [in] the number of FIR coefficients */ );
207 
208  ///Set the FIR coefficients for one mode.
209  /**
210  * \returns 0 on success, negative number on error.
211  */
212  int setB( int i, ///< [in] the mode number
213  const imageT & b ///< [in] the IIR coefficients for this mode
214  );
215 
216  ///Get the gain for a single mode.
217  /**
218  * \returns the gain value if mode exists.
219  */
220  realT gain( int i /**< The mode number*/);
221 
222  ///Set the gain for a single mode.
223  /**
224  * \returns 0 on success, negative number on error.
225  */
226  int gain( int i, ///< The mode number
227  realT g ///< The new gain value
228  );
229 
230  ///Set the gain for all modes to a single value
231  /**
232  * \returns 0 on success, negative number on error.
233  */
234  int gains(realT g /**< The new gain value*/ );
235 
236  ///Set the gains for all modes, using a vector to specify each gain
237  /** The vector must be exactly as long as m_nModes.
238  *
239  * \returns 0 on success, negative number on error.
240  */
241  int gains( const std::vector<realT> & gains /**< [in] vector of gains.*/);
242 
243 
244  ///Set the gains for all modes, using a file to specify each gain
245  /** The file format is a simple ASCII single column, with 1 gain per line.
246  * Must be exactly as long as m_nModes.
247  *
248  * \returns 0 on success, negative number on error.
249  */
250  int gains( const std::string & ogainf /**< [in] the name of the file, full path */ );
251 
252 
253  ///Allocate the provided command structures
254  /** Used by the calling system to allocate the commands being passed between components.
255  *
256  * \returns 0 on success, negative number on error.
257  */
258  int initMeasurements( commandT & filtAmps, ///< The structure to contain the filtered commands
259  commandT & rawAmps ///< The structure to contain the raw commands
260  );
261 
262  int filterCommands( commandT & filtAmps,
263  commandT & rawAmps,
264  int iterNo
265  );
266 
267 
268 
269 
270 };
271 
272 
273 template<typename realT>
275 {
276 }
277 
278 
279 
280 template<typename realT>
282 {
283  m_nModes = nModes;
284 
285  //If m_a has been sized, resize it
286  if(m_a.cols() > 0)
287  {
288  int n = m_a.cols();
289  m_a.resize(m_nModes, n);
290  m_a.setZero();
291  m_currA = 0;
292 
293  m_commandsOut.resize( m_nModes, n);
294  m_commandsOut.setZero();
295  }
296 
297  //If m_b has been sized, resize it
298  if(m_b.cols() > 0)
299  {
300  int n = m_b.cols();
301  m_b.resize(m_nModes, n);
302  m_b.setZero();
303  m_currB = 0;
304 
305  m_commandsIn.resize( m_nModes, n);
306  m_commandsIn.setZero();
307  }
308 
309  m_closingGains.resize(1,m_nModes);
310 
311  m_closingGains.setZero();
312 
313  m_gains.resize(1,m_nModes);
314 
315  m_gains.setZero();
316 
317 
318  return 0;
319 }
320 
321 template<typename realT>
323 {
324  return m_nModes;
325 }
326 
327 template<typename realT>
329 {
330  m_openLoop = ol;
331  return 0;
332 }
333 
334 template<typename realT>
336 {
337  return m_openLoop;
338 }
339 
340 template<typename realT>
342 {
343  m_openLoopDelay = old;
344 
345  return 0;
346 }
347 
348 template<typename realT>
350 {
351  return m_openLoopDelay;
352 }
353 
354 template<typename realT>
356 {
357  m_closingRamp = cr;
358 
359  return 0;
360 }
361 
362 template<typename realT>
364 {
365  return m_closingRamp;
366 }
367 
368 template<typename realT>
370 {
371  m_closingDelay = cd;
372 
373  return 0;
374 }
375 
376 template<typename realT>
378 {
379  return m_closingDelay;
380 }
381 
382 template<typename realT>
383 int generalIntegrator<realT>::closingGains( const std::vector<realT> & gains )
384 {
385 
386  if( gains.size() != (size_t) m_closingGains.cols())
387  {
388  mxError("generalIntegrator::closingGains", MXE_SIZEERR, "input gain vector not same size as number of modes");
389  return -1; ///\retval -1 on vector size mismatch
390  }
391 
392  for(int i=0;i<m_closingGains.cols(); ++i)
393  {
394  m_closingGains(0,i) = gains[i];
395  }
396 
397  return 0;
398 }
399 
400 template<typename realT>
402 {
403  for(int i=0;i<m_closingGains.cols(); ++i)
404  {
405  m_closingGains(0,i) = g;
406  }
407 
408  return 0;
409 }
410 
411 template<typename realT>
413 {
414  m_lowOrders = lo;
415 
416  return 0;
417 }
418 
419 template<typename realT>
421 {
422  return m_lowOrders;
423 }
424 
425 template<typename realT>
427 {
428  //Resize with m_nModes if set
429  if( m_nModes > 0)
430  {
431  m_a.resize(m_nModes, n);
432  m_commandsOut.resize(m_nModes, n);
433  }
434  else
435  {
436  m_a.resize(1,n);
437  m_commandsOut.resize(1, n);
438  }
439 
440  m_a.setZero();
441  m_currA = 0;
442  m_commandsOut.setZero();
443 
444  return 0;
445 }
446 
447 template<typename realT>
449 {
450  m_a.row(i) = a;
451 
452  return 0;
453 }
454 
455 template<typename realT>
457 {
458  //Resize with m_nModes if set
459  if( m_nModes > 0)
460  {
461  m_b.resize(m_nModes, n);
462  m_commandsIn.resize(m_nModes,n);
463  }
464  else
465  {
466  m_b.resize(1,n);
467  m_commandsIn.resize(1,n);
468  }
469 
470  m_b.setZero();
471  m_currB = 0;
472  m_commandsIn.setZero();
473 
474  return 0;
475 }
476 
477 template<typename realT>
479 {
480  m_b.row(i) = b;
481 
482  return 0;
483 }
484 
485 
486 template<class realT>
488 {
489  if(i < 0 || i >= m_nModes)
490  {
491  mxError("generalIntegrator::gain", MXE_INVALIDARG, "mode index out of range");
492  return 0; ///\retval 0 if the mode doesn't exist.
493  }
494 
495  return m_gains(i);
496 }
497 
498 template<typename realT>
500 {
501  if(i < 0 || i >= m_nModes)
502  {
503  mxError("generalIntegrator::gain", MXE_INVALIDARG, "mode index out of range");
504  return 0; ///\retval 0 if the mode doesn't exist.
505  }
506 
507  m_gains(0,i) = g;
508 
509  return 0;
510 }
511 
512 
513 template<typename realT>
515 {
516  for(int i=0;i<m_gains.cols(); ++i)
517  {
518  m_gains(0,i) = g;
519  }
520 
521  return 0;
522 }
523 
524 template<typename realT>
525 int generalIntegrator<realT>::gains( const std::vector<realT> & gains )
526 {
527 
528  if( gains.size() != (size_t) m_gains.cols())
529  {
530  mxError("generalIntegrator::gains", MXE_SIZEERR, "input gain vector not same size as number of modes");
531  return -1; ///\retval -1 on vector size mismatch
532  }
533 
534  for(int i=0;i<m_gains.cols(); ++i)
535  {
536  m_gains(0,i) = gains[i];
537  }
538 
539  return 0;
540 }
541 
542 
543 
544 
545 template<typename realT>
546 int generalIntegrator<realT>::gains(const std::string & ogainf)
547 {
548  std::ifstream fin;
549  fin.open(ogainf);
550 
551  if(!fin.good())
552  {
553  mxError("generalIntegrator::gains", MXE_FILEOERR, "could not open gan file");
554  return -1; /// \retval -1 if file open fails
555  }
556 
557  std::string tmpstr;
558  realT g;
559  for(int i=0;i<m_gains.cols();++i)
560  {
561  fin >> tmpstr;
562  g = ioutils::convertFromString<realT>(tmpstr);
563  gain(i, g);
564 
565  }
566 
567  return 0;
568 }
569 
570 template<class realT>
572 {
573  filtAmps.measurement.resize(m_nModes);
574  for(size_t n=0; n<m_nModes; ++n) filtAmps.measurement[n] = 0;
575  //filtAmps.measurement.setZero();
576 
577  rawAmps.measurement.resize(m_nModes);
578  for(size_t n=0; n<m_nModes; ++n) rawAmps.measurement[n] = 0;
579  //rawAmps.measurement.resize(1, m_nModes);
580  //rawAmps.measurement.setZero();
581 
582  return 0;
583 }
584 
585 template<typename realT>
586 int generalIntegrator<realT>::filterCommands( commandT & filtAmps,
587  commandT & rawAmps,
588  int iterNo )
589 {
590  filtAmps.iterNo = rawAmps.iterNo;
591 
592  if(m_openLoop || iterNo < m_openLoopDelay)
593  {
594  for(size_t n=0; n<m_nModes; ++n) filtAmps.measurement[n] = 0;
595  //filtAmps.measurement.setZero();
596  return 0;
597  }
598 
599 
600  realT aTot, bTot;
601 
602  if( iterNo - m_openLoopDelay < m_closingDelay)
603  {
604  BREAD_CRUMB;
605 
606  for(int i=0; i< m_nModes; ++i)
607  {
608  //if( std::isnan( rawAmps.measurement(0,i) ) || !std::isfinite(rawAmps.measurement(0,i))) rawAmps.measurement(0,i) = 0.0;
609  if( std::isnan( rawAmps.measurement[i] ) || !std::isfinite(rawAmps.measurement[i])) rawAmps.measurement[i] = 0.0;
610 
611  //m_commandsIn(i, m_currB) = rawAmps.measurement(0,i);
612  m_commandsIn(i, m_currB) = rawAmps.measurement[i];
613 
614  aTot = m_commandsOut(i, m_currA);
615  //std::cerr << m_currA << " " << aTot << "\n";
616 
617 
618  int cA = m_currA + 1;
619  if(cA >= m_a.cols()) cA = 0;
620 
621 
622  realT gf = 1.0;
623 
624  if( iterNo - m_openLoopDelay < m_closingRamp) gf = ((realT) iterNo - m_openLoopDelay)/m_closingRamp;
625 
626 
627  //m_commandsOut(i, cA) = aTot + gf*m_closingGains(i) * rawAmps.measurement(0,i);
628  m_commandsOut(i, cA) = aTot + gf*m_closingGains(i) * rawAmps.measurement[i];
629 
630  //std::cerr << cA << " " << m_commandsOut(i, cA) << "\n";
631 
632  if( i <= m_lowOrders || m_lowOrders <= 0)
633  {
634  filtAmps.measurement[i] = m_commandsOut(i, cA);
635  }
636  else
637  {
638  filtAmps.measurement[i] = 0;
639  }
640  }
641 
642  ++m_currB;
643  if(m_currB >= m_b.cols()) m_currB = 0;
644 
645 
646  ++m_currA;
647  if(m_currA >= m_a.cols()) m_currA = 0;
648 
649  return 0;
650  }
651 
652 
653 
654 
655  for(int i=0; i< m_nModes; ++i)
656  {
657  if(m_gains(i) == 0)
658  {
659  //filtAmps.measurement(0,i) = 0;
660  filtAmps.measurement[i] = 0;
661  continue;
662  }
663 
664 
665  //if( std::isnan( rawAmps.measurement(0,i) ) || !std::isfinite(rawAmps.measurement(0,i))) rawAmps.measurement(0,i) = 0.0;
666  if( std::isnan( rawAmps.measurement[i] ) || !std::isfinite(rawAmps.measurement[i])) rawAmps.measurement[i] = 0.0;
667 
668  aTot = 0;
669  for(int j = 0; j < m_a.cols(); ++j)
670  {
671  int k = m_currA - j;
672  if(k < 0) k += m_a.cols();
673  aTot += m_a(i,j) * m_commandsOut(i,k);
674  }
675 
676  m_commandsIn(i, m_currB) = rawAmps.measurement[i];
677 
678  bTot = 0;
679  for(int j = 0; j < m_b.cols(); ++j)
680  {
681  int k = m_currB - j;
682  if(k < 0) k += m_b.cols();
683 
684  bTot += m_b(i,j) * m_commandsIn(i,k);
685  }
686 
687 
688  int cA= m_currA + 1;
689  if( cA >= m_a.cols()) cA = 0;
690 
691  m_commandsOut(i, cA) = aTot + m_gains(i) * bTot;
692 
693  filtAmps.measurement[i] = m_commandsOut(i, cA);
694  }
695 
696  ++m_currB;
697  if(m_currB >= m_b.cols()) m_currB = 0;
698 
699  ++m_currA;
700  if(m_currA >= m_a.cols()) m_currA = 0;
701 
702  return 0;
703 }
704 
705 
706 } //namespace sim
707 } //namespace AO
708 } //namespace mx
709 
710 #endif //__generalIntegrator_hpp__
Implements a general integrator controller.
imageT m_closingGains
Column-vector of gains used for loop closing as simple integrator.
int nModes()
Get the number of modes.
int m_openLoopDelay
If > 0, then the loop is open for this time in time steps. Default is 0.
int m_closingRamp
If > 0, then gains are famped linearly up to m_closingGains over this interval in time steps....
int closingDelay()
Get the value of the m_closingDelay.
int setA(int i, const imageT &a)
Set the IIR coefficients for one mode.
bool openLoop()
Get the value of the m_openLoop flag.
wfMeasurement< realT > commandT
The wavefront data type.
bool m_openLoop
If true, then commands are not integrated. Default is false.
Eigen::Array< realT, Eigen::Dynamic, Eigen::Dynamic > imageT
The image type, used here as a general storage array.
int m_lowOrders
If > 0, then this sets the maximum mode number which is filtered. All remaining modes are set to 0....
int gains(realT g)
Set the gain for all modes to a single value.
int closingGains(const std::vector< realT > &gains)
Set the simple integrator gains to use during closing.
int openLoopDelay()
Get the value of the m_openLoopDelay.
std::complex< realT > complexT
The real data type.
int setB(int i, const imageT &b)
Set the FIR coefficients for one mode.
int initialize(int nModes)
Allocate and initialize all state.
int initMeasurements(commandT &filtAmps, commandT &rawAmps)
Allocate the provided command structures.
_realT realT
The real data type.
int lowOrders()
Get the value of the m_lowOrders.
int setBSize(int n)
Set the size of the FIR vector (the b coefficients)
int m_closingDelay
If > 0, then the simple integrator,with m_closingGains is used up to this timestep....
int setASize(int n)
Set the size of the IIR vector (the a coefficients)
realT gain(int i)
Get the gain for a single mode.
int closingRamp()
Get the value of the m_closingRamp.
imageT m_gains
Column-vector of gains.
int m_nModes
The number of modes being filtered.
constexpr units::realT k()
Boltzmann Constant.
Definition: constants.hpp:71
The mxlib c++ namespace.
Definition: mxError.hpp:107