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