Documentation
Tools for embedded systems
Loading...
Searching...
No Matches
ltisys.hpp
1
8
9#ifndef QLIBS_LTISYS
10#define QLIBS_LTISYS
11
12#include <include/qlibs_types.hpp>
13#include <include/tdl.hpp>
14#include <include/numa.hpp>
15
16
20namespace qlibs {
26
28 /*only for continuousSystem*/
29 #if !defined( LTISYS_EVAL_MODEL_CONTROLLABLE ) || !defined( LTISYS_EVAL_MODEL_OBSERVABLE )
30 #define LTISYS_EVAL_MODEL_CONTROLLABLE
31 #endif
33
42
46 template<size_t order>
47 using continuousStates = nState[ order ];
48
52 template<size_t order>
53 using discreteStates = real_t[ order ];
54
60 template<size_t order>
61 struct continuousTF {
63 real_t num[ order+1 ];
64 real_t den[ order+1 ];
65 continuousStates<order> states = {};
67
75 continuousTF( const real_t ( &numerator )[ order + 1 ], const real_t ( &denominator )[ order + 1 ] )
76 {
77 static_assert( order >= 1 , "Order should be greater than 0" );
78 for ( size_t i = 0; i <= order; ++i ) {
79 num[ i ] = numerator[ i ];
80 den[ i ] = denominator[ i ];
81 }
82 }
83 };
84
85
97 struct timeDelay {
100
105 constexpr explicit timeDelay(real_t v) : value(v) {}
106
112 constexpr size_t operator()(const real_t dt) const {
113 return static_cast<size_t>( ( value/dt ) + 0.5_re);
114 }
115
121 constexpr size_t operator[](const real_t dt) const {
122 return static_cast<size_t>( ( value/dt ) + 0.5_re);
123 }
124 };
125
137 constexpr timeDelay operator"" _td(long double v) {
138 return timeDelay(static_cast<real_t>(v));
139 }
140
154 constexpr size_t operator,(const timeDelay td, const real_t dt) {
155 return static_cast<size_t>( ( td.value/dt ) + 0.5_re );
156 }
157
167 constexpr size_t delayFromTime( const real_t Time, const real_t dt )
168 {
169 return static_cast<size_t>( ( Time/dt ) + 0.5_re );
170 }
171
181 constexpr size_t delayFromTime( const timeDelay Time, const real_t dt )
182 {
183 return static_cast<size_t>( ( Time.value/dt ) + 0.5_re );
184 }
185
187 class ITransportDelay {
188 public:
189 virtual ~ITransportDelay() = default;
190 virtual real_t delay(const real_t xInput) noexcept = 0;
191 virtual real_t operator()(const real_t xInput) noexcept = 0;
192 virtual size_t getNumberOfDelays() const noexcept = 0;
193 };
195
211 template<size_t numberOfDelays>
212 class transportDelay : public ITransportDelay {
213 private:
214 real_t buf[ numberOfDelays + 1 ];
215 tdl dl;
216 public:
217 virtual ~transportDelay() {}
223 transportDelay( const real_t initValue = 0.0_re )
224 {
225 static_assert( numberOfDelays >= 1 , "Delay taps should be greater than 0" );
226 dl.setup( buf, initValue);
227 }
228
234 real_t delay( const real_t xInput ) noexcept override
235 {
236 dl.insertSample( xInput );
237 return dl.getOldest();
238 }
239
245 real_t operator()( const real_t xInput ) noexcept override
246 {
247 return delay( xInput );
248 }
249
255 size_t getNumberOfDelays() const noexcept {
256 return numberOfDelays;
257 }
258 };
259
265 template<size_t delay>
267
268
275 template<size_t NB, size_t NA>
276 struct discreteTF {
278 real_t num[ NB ];
279 real_t den[ NA ];
280 discreteStates<(NA>NB)? NA:NB> states = {};
282
290 discreteTF( const real_t ( &numerator )[ NB ], const real_t ( &denominator)[ NA ] ) {
291 for ( size_t i = 0; i < NB; ++i ) {
292 num[ i ] = numerator[ i ];
293 }
294 for ( size_t i = 0; i < NA; ++i ) {
295 den[ i ] = denominator[ i ];
296 }
297 }
298 };
299
300
304 class ltisys : public tdl {
305 protected:
307 real_t *a{ nullptr };
308 real_t *b{ nullptr };
309 size_t n{ 0U };
310 size_t na{ 0U };
311 size_t nb{ 0U };
312 real_t b0{ 0.0_re };
313 real_t min{ -REAL_MAX };
314 real_t max{ +REAL_MAX };
315 void normalizeTransferFunction( real_t *num,
316 real_t *den,
317 size_t n_num,
318 size_t n_den );
319 real_t saturate( real_t y );
321 virtual real_t update( const real_t u ) = 0;
323 public:
324 virtual ~ltisys() {}
325 ltisys() = default;
326
345 real_t excite( real_t u ) noexcept;
346
366 return excite( u );
367 }
368
374 virtual bool isInitialized( void ) const noexcept = 0;
375
376
382 explicit operator bool() const noexcept {
383 return isInitialized();
384 }
385
393 virtual bool setInitStates( const real_t *xi = nullptr ) = 0;
394
400 ltisysType getType( void ) const
401 {
402 return type;
403 }
404
414 bool setDelay( real_t * const w,
415 const size_t nD,
416 const real_t initVal = 0.0_re ) noexcept;
417
424 bool setSaturation( const real_t minV,
425 const real_t maxV ) noexcept;
426 };
427
433 class discreteSystem : public ltisys {
434 private:
435 real_t *xd{ nullptr };
436 real_t update( const real_t u ) override;
437 public:
438 virtual ~discreteSystem() {}
439
465 real_t *den,
466 real_t *x,
467 const size_t n_b,
468 const size_t n_a ) noexcept
469 {
470 (void)setup( num, den, x, n_b, n_a );
471 }
472
491 template<size_t NB, size_t NA>
492 discreteSystem( real_t (&num)[ NB ],
493 real_t (&den)[ NA ],
494 real_t *x ) noexcept
495 {
496 (void)setup( num, den, x, NB, NA );
497 }
498
504 template<size_t NB, size_t NA>
506 {
507 (void)setup( dtf.num, dtf.den, dtf.states, NB, NA );
508 }
509
535 bool setup( real_t *num,
536 real_t *den,
537 real_t *x,
538 const size_t n_b,
539 const size_t n_a ) noexcept;
540
560 template<size_t NB, size_t NA>
561 bool setup( real_t (&num)[ NB ],
562 real_t (&den)[ NA ],
563 real_t *x )
564 {
565 return setup( num, den, x, NB, NA );
566 }
567
574 template<size_t NB, size_t NA>
575 bool setup( discreteTF<NB, NA>& dtf ) noexcept
576 {
577 return setup( dtf.num, dtf.den, dtf.states, NB, NA );
578 }
579
585 bool isInitialized( void ) const noexcept override
586 {
587 return ( nullptr != xd ) && ( LTISYS_TYPE_DISCRETE == type );
588 }
589
595 explicit operator bool() const noexcept {
596 return isInitialized();
597 }
598
607 bool setInitStates( const real_t *xi = nullptr ) override;
608
624 static real_t updateFIR( real_t *w,
625 const size_t wsize,
626 const real_t x,
627 const real_t * const c = nullptr );
628 };
629
635 class continuousSystem : public ltisys {
636 private:
637 real_t dt{ 1.0_re };
638 nState *xc{ nullptr };
639 real_t update( const real_t u ) override;
640 public:
641 virtual ~continuousSystem() {}
642
667 real_t *den,
668 nState *x,
669 const size_t nD,
670 const real_t dT ) noexcept
671 {
672 (void)setup( num, den, x, nD, dT );
673 }
674
681 template<size_t order>
683 {
684 (void)setup( ctf.num, ctf.den, ctf.states, order, dT );
685 }
686
707 template<size_t systemOrder>
708 continuousSystem( real_t (&num)[ systemOrder+1 ],
709 real_t (&den)[ systemOrder+1 ],
710 nState (&x)[ systemOrder ],
711 const real_t dT ) noexcept
712 {
713 (void)setup( num, den, x, systemOrder, dT );
714 }
715
740 bool setup( real_t *num,
741 real_t *den,
742 nState *x,
743 const size_t nD,
744 const real_t dT ) noexcept;
745
767 template<size_t systemOrder>
768 bool setup( real_t (&num)[ systemOrder+1 ],
769 real_t (&den)[ systemOrder+1 ],
770 nState (&x)[ systemOrder ],
771 const real_t dT ) noexcept
772 {
773 return setup( num, den, x, systemOrder, dT );
774 }
775
783 template<size_t order>
784 bool setup( continuousTF<order>& ctf, const real_t dT )
785 {
786 return setup( ctf.num, ctf.den, ctf.states, order, dT );
787 }
788
794 bool isInitialized( void ) const noexcept override
795 {
796 return ( nullptr != xc ) && ( LTISYS_TYPE_CONTINUOUS == type );
797 }
798
807 bool setInitStates( const real_t *xi = nullptr ) override;
808
821 bool setIntegrationMethod( integrationMethod m );
822 };
823
824
825 using customProcessModel = real_t(*)(real_t, void*);
826
827
837 private:
838 ltisys *model{nullptr};
839 customProcessModel modelAlternate{ nullptr };
840 ITransportDelay *modelDelay;
841 ltisys *filter{ nullptr };
842 real_t yp_hat;
843 void *alternateData{ nullptr };
844 public:
845 virtual ~smithPredictor() {}
859 ITransportDelay& mDelay,
860 const real_t initialCondition = 0.0_re )
861 : model(&modelTf), modelDelay(&mDelay), yp_hat(initialCondition) {}
862
875 ITransportDelay& mDelay,
876 const real_t initialCondition = 0.0_re )
877 : modelAlternate(modelCustom), modelDelay(&mDelay), yp_hat(initialCondition) {}
878
894 ITransportDelay& mDelay,
895 ltisys& filterTf,
896 const real_t initialCondition = 0.0_re )
897 : model(&modelTf), modelDelay(&mDelay), filter(&filterTf), yp_hat(initialCondition) {}
898
915 ITransportDelay& mDelay,
916 ltisys& filterTf,
917 const real_t initialCondition = 0.0_re )
918 : modelAlternate(modelCustom), modelDelay(&mDelay), filter(&filterTf), yp_hat(initialCondition) {}
919
935 bool updatePrediction( const real_t ut,
936 const real_t yt ) noexcept;
937
942 real_t getPrediction() const noexcept {
943 return yp_hat;
944 }
945
959 bool setFilter( ltisys& filterTf ) noexcept {
960 bool retValue = filter != &filterTf;
961 if ( retValue ) {
962 filter = &filterTf;
963 }
964 return retValue;
965 }
966
975 bool setModelData( void* data ) noexcept {
976 bool retValue = data != alternateData;
977 if ( retValue ) {
978 alternateData = data;
979 }
980 return retValue;
981 }
982 };
983
985}
986
987#endif /*QLIBS_LTISYS*/
virtual ~continuousSystem()
Definition ltisys.hpp:641
continuousSystem(real_t(&num)[systemOrder+1], real_t(&den)[systemOrder+1], nState(&x)[systemOrder], const real_t dT) noexcept
Constructor for an instance of a LTI continuous system.
Definition ltisys.hpp:708
continuousSystem(real_t *num, real_t *den, nState *x, const size_t nD, const real_t dT) noexcept
Constructor for an instance of a LTI continuous system.
Definition ltisys.hpp:666
bool setup(real_t(&num)[systemOrder+1], real_t(&den)[systemOrder+1], nState(&x)[systemOrder], const real_t dT) noexcept
Setup and initialize an instance of a LTI continuous system.
Definition ltisys.hpp:768
continuousSystem(continuousTF< order > &ctf, const real_t dT)
Constructor for an instance of a LTI continuous system from a transfer function definition.
Definition ltisys.hpp:682
bool isInitialized(void) const noexcept override
Check if the LTI continuous system is initialized.
Definition ltisys.hpp:794
bool setup(real_t *num, real_t *den, nState *x, const size_t nD, const real_t dT) noexcept
Setup and initialize an instance of a LTI continuous system.
Definition ltisys.cpp:156
bool setup(continuousTF< order > &ctf, const real_t dT)
Setup and initialize an instance of a LTI continuous system from a transfer function definition.
Definition ltisys.hpp:784
virtual ~discreteSystem()
Definition ltisys.hpp:438
bool isInitialized(void) const noexcept override
Check if the LTI discrete system is initialized.
Definition ltisys.hpp:585
bool setup(real_t *num, real_t *den, real_t *x, const size_t n_b, const size_t n_a) noexcept
Setup and initialize an instance of the discrete LTI system.
Definition ltisys.cpp:121
discreteSystem(discreteTF< NB, NA > &dtf) noexcept
Constructor for a the discrete LTI system from a transfer function definition.
Definition ltisys.hpp:505
bool setup(discreteTF< NB, NA > &dtf) noexcept
Setup and initialize an instance of the discrete LTI system from a transfer function definition.
Definition ltisys.hpp:575
bool setup(real_t(&num)[NB], real_t(&den)[NA], real_t *x)
Setup and initialize an instance of the discrete LTI system.
Definition ltisys.hpp:561
discreteSystem(real_t *num, real_t *den, real_t *x, const size_t n_b, const size_t n_a) noexcept
Constructor for a the discrete LTI system.
Definition ltisys.hpp:464
discreteSystem(real_t(&num)[NB], real_t(&den)[NA], real_t *x) noexcept
Constructor for a the discrete LTI system.
Definition ltisys.hpp:492
A LTI system base class.
Definition ltisys.hpp:304
virtual ~ltisys()
Definition ltisys.hpp:324
ltisysType getType(void) const
Get the LTI system type.
Definition ltisys.hpp:400
real_t excite(real_t u) noexcept
Drives the LTI system recursively using the provided input sample.
Definition ltisys.cpp:58
virtual bool setInitStates(const real_t *xi=nullptr)=0
Set the initial states for the given system.
ltisys()=default
virtual bool isInitialized(void) const noexcept=0
Check if the LTI system is initialized.
real_t operator()(const real_t u)
Drives the LTI system recursively using the provided input sample.
Definition ltisys.hpp:365
A numerical state object.
Definition numa.hpp:50
smithPredictor(ltisys &modelTf, ITransportDelay &mDelay, ltisys &filterTf, const real_t initialCondition=0.0_re)
Constructs a Smith Predictor with a plant model, delay model, and optional initial output estimate.
Definition ltisys.hpp:893
bool setModelData(void *data) noexcept
Sets the model data when alternate when a custom delay-free plant model is used.
Definition ltisys.hpp:975
smithPredictor(customProcessModel modelCustom, ITransportDelay &mDelay, ltisys &filterTf, const real_t initialCondition=0.0_re)
Constructs a Smith Predictor with a plant model, delay model, and optional initial output estimate.
Definition ltisys.hpp:914
smithPredictor(ltisys &modelTf, ITransportDelay &mDelay, const real_t initialCondition=0.0_re)
Constructs a Smith Predictor with a plant model, delay model, and optional initial output estimate.
Definition ltisys.hpp:858
real_t getPrediction() const noexcept
Retrieves the current delay-free predicted output of the system.
Definition ltisys.hpp:942
virtual ~smithPredictor()
Definition ltisys.hpp:845
bool setFilter(ltisys &filterTf) noexcept
Sets an optional filter for the internal Smith Predictor model.
Definition ltisys.hpp:959
smithPredictor(customProcessModel modelCustom, ITransportDelay &mDelay, const real_t initialCondition=0.0_re)
Constructs a Smith Predictor with a plant model, delay model, and optional initial output estimate.
Definition ltisys.hpp:874
A Tapped Delay Line (TDL) object.
Definition tdl.hpp:32
tdl()=default
Delays the input by a specified amount of time. You can use this class to simulate a time delay.
Definition ltisys.hpp:212
virtual ~transportDelay()
Definition ltisys.hpp:217
transportDelay(const real_t initValue=0.0_re)
Constructor for the transportDelay class.
Definition ltisys.hpp:223
real_t delay(const real_t xInput) noexcept override
Delays the input by a specified amount of time.
Definition ltisys.hpp:234
size_t getNumberOfDelays() const noexcept
Returns the number of delay steps configured for this instance.
Definition ltisys.hpp:255
real_t operator()(const real_t xInput) noexcept override
Delays the input by a specified amount of time.
Definition ltisys.hpp:245
ltisysType
All the possible natures of a LTI system.
Definition ltisys.hpp:37
transportDelay< delay > discreteDelay
Delays the input by a specified amount of samples. You can use this class to simulate a discrete time...
Definition ltisys.hpp:266
constexpr size_t delayFromTime(const real_t Time, const real_t dt)
Computes the number of discrete delays required for a specified amount of time using a defined time-s...
Definition ltisys.hpp:167
nState[order] continuousStates
Type to specify continuous states.
Definition ltisys.hpp:47
constexpr size_t operator,(const timeDelay td, const real_t dt)
Computes the delay in discrete steps using the comma operator.
Definition ltisys.hpp:154
real_t[order] discreteStates
Type to specify discrete states.
Definition ltisys.hpp:53
real_t(*)(real_t, void *) customProcessModel
Definition ltisys.hpp:825
@ LTISYS_TYPE_CONTINUOUS
Definition ltisys.hpp:39
@ LTISYS_TYPE_DISCRETE
Definition ltisys.hpp:40
@ LTISYS_TYPE_UNKNOWN
Definition ltisys.hpp:38
integrationMethod
An enum with all the available integration methods.
Definition numa.hpp:28
The qLibs++ library namespace.
Definition mat.hpp:18
float real_t
A type to instantiate a real variable double-precision of 64-bits IEEE 754.
Definition qlibs_types.hpp:43
Continuous transfer function for easy LTI system definition.
Definition ltisys.hpp:61
continuousTF(const real_t(&numerator)[order+1], const real_t(&denominator)[order+1])
Constructor for the continuousTF class.
Definition ltisys.hpp:75
Discrete transfer function for easy LTI system definition.
Definition ltisys.hpp:276
discreteTF(const real_t(&numerator)[NB], const real_t(&denominator)[NA])
Constructor for the discreteTF class.
Definition ltisys.hpp:290
Represents a time delay value for use in transportDelay constructor.
Definition ltisys.hpp:97
constexpr timeDelay(real_t v)
Construct a new timeDelay object.
Definition ltisys.hpp:105
real_t value
Delay duration in seconds.
Definition ltisys.hpp:99
constexpr size_t operator()(const real_t dt) const
Computes the number of discrete steps equivalent to the delay.
Definition ltisys.hpp:112
constexpr size_t operator[](const real_t dt) const
Alternate syntax to compute delay in steps using indexing operator.
Definition ltisys.hpp:121