9#include <tl/expected.hpp>
28 template<
class T,
int XRows,
int XCols,
int XOpt,
int XMaxRows,
int XMaxCols>
29 requires((XRows >= XCols) || (XRows == Eigen::Dynamic) || (XCols == Eigen::Dynamic))
31 Eigen::Vector<T, XCols> result = X.colPivHouseholderQr().solve(y).eval();
44 default :
return "dft_estimate_error::error";
75 template<
class T,
int NumOrder,
int DenOrder>
76 requires((NumOrder != Eigen::Dynamic) && (DenOrder != Eigen::Dynamic))
79 const Eigen::Vector<T, Eigen::Dynamic>& u,
80 const Eigen::Vector<T, Eigen::Dynamic>& y,
81 const T& regularization = T(0),
84 if(y.size() != u.size()){
88 constexpr int P = NumOrder + 1 + DenOrder;
89 Eigen::Vector<T, P> s;
93 auto s_u = s.head(NumOrder + 1);
96 auto s_y = s.tail(DenOrder);
98 const std::size_t start = std::max(s_u.size()-1, s_y.size());
100 if(
static_cast<std::size_t
>(y.size()) <= start ||
static_cast<std::size_t
>(u.size()) <= start){
105 for(std::size_t k = 0; k < static_cast<std::size_t>(s_u.size()); ++k){
106 s_u(k) = u(start - k);
108 for(std::size_t k = 0; k < static_cast<std::size_t>(s_y.size()); ++k){
109 s_y(k) = -y(start - k - 1);
113 Eigen::Matrix<T, P, P> S;
116 Eigen::Vector<T, P> r;
120 S.noalias() += s * s.transpose();
121 r.noalias() += y(start) * s;
124 for(std::size_t k = start+1; (k < static_cast<std::size_t>(y.size())) && (k <
static_cast<std::size_t
>(u.size())); ++k){
129 S.noalias() += s * s.transpose();
130 r.noalias() += y(k) * s;
134 S = (S + S.transpose()) * T(0.5);
137 S.diagonal().array() += regularization;
140 const T hint_a0 = hint.
den(0);
142 const Eigen::Vector<T, NumOrder + 1> hint_scaled_num = (hint.
num().vector() / hint_a0);
143 const Eigen::Vector<T, DenOrder + 1> hint_scaled_den = (hint.
den().vector() / hint_a0);
144 const Eigen::Vector<T, DenOrder> hint_scaled_den_tail = hint_scaled_den.template tail<DenOrder>();
147 r += regularization * hint_v;
151 std::cout <<
"S:\n" << S << std::endl;
152 std::cout <<
"r:\n" << r.transpose() << std::endl;
153 const Eigen::Vector<T, P> params = S.ldlt().solve(r);
156 const Eigen::Vector<T, NumOrder + 1> num = params.head(NumOrder + 1);
157 Eigen::Vector<T, DenOrder + 1> den;
159 den.tail(DenOrder) = params.tail(DenOrder);
162 DiscreteTransferFunction<T, NumOrder, DenOrder> result(num, den);
194 template<
class T,
size_t NParams,
size_t NMeasurements = 1>
198 Eigen::Matrix<T, NParams, NParams> _cov;
199 Eigen::Vector<T, NParams> _param;
200 Eigen::Vector<T, NParams> _K;
202 T _cov_regularisation = 1e-9;
250 const Eigen::Vector<T, NParams>& param_hint = Eigen::Vector<T, NParams>().setOne(),
264 this->_cov = (Eigen::Matrix<T, NParams, NParams>::Identity() * T(1000));
274 void input(
const T& y,
const Eigen::Matrix<T, NMeasurements, NParams>& s) {
275 this->_cov.diagonal().array() += this->_cov_regularisation;
278 const auto A = (this->_cov * s.transpose()).eval();
279 const Eigen::Matrix<T, NMeasurements, NMeasurements> I_m = Eigen::Matrix<T, NMeasurements, NMeasurements>::Identity();
280 auto B1 = (s * this->_cov * s.transpose()).eval();
281 B1.diagonal().array() += this->_memory;
282 const auto B = ((B1 + B1.transpose())/2).eval();
285 this->_K = B.transpose().llt().solve(A.transpose()).transpose().eval();
288 for(
int i = 0; i < this->_K.size(); ++i){
289 this->_K.at(i) = std::clamp(this->_K.at(i), -this->_gain_clamp, this->_gain_clamp);
293 this->_param += this->_K * (y - s * this->_param);
296 this->_cov -= this->_K * s * this->_cov;
297 this->_cov /= this->_memory;
304 inline const Eigen::Vector<T, NParams>&
estimate()
const {
return this->_param;}
313 [[nodiscard]]
inline const Eigen::Matrix<T, NParams, NParams>&
cov()
const {
return this->_cov;}
315 inline void set_cov(
const Eigen::Matrix<T, NParams, NParams>&
cov) {
327 this->_cov_regularisation = reg;
331 return this->_cov_regularisation;
356 [[nodiscard]]
inline const T&
memory()
const {
357 return this->_memory;
379 return this->_gain_clamp;
391 inline const Eigen::Vector<T, NParams>&
gain()
const {
return this->_K;}
424 template<
class T,
size_t NParams>
428 Eigen::Matrix<T, NParams, NParams> _cov;
429 Eigen::Vector<T, NParams> _param;
430 Eigen::Vector<T, NParams> _K;
432 T _cov_regularisation = 1e-9;
461 const Eigen::Vector<T, NParams>& param_hint = Eigen::Vector<T, NParams>().setOnes(),
462 const Eigen::Matrix<T, NParams, NParams>& cov_hint = (Eigen::Matrix<T, NParams, NParams>::Identity() * T(1000)),
472 throw std::invalid_argument(
"Error: ReccursiveLeastSquares::ReccursiveLeastSquares(): memory has to be in the open-closed range of: (0, 1]");
477 inline void set_cov(
const Eigen::Matrix<T, NParams, NParams>&
cov){
481 inline void set_param(
const Eigen::Vector<T, NParams>& param){
482 this->_param = param;
494 return this->_gain_clamp;
503 void input(
const T& y,
const Eigen::Vector<T, NParams>& s) {
504 this->_cov.diagonal().array() += this->_cov_regularisation;
507 const auto A = (this->_cov * s).eval();
508 const T B = this->_memory + s.transpose() * this->_cov * s;
511 for(
int i = 0; i < this->_K.size(); ++i){
512 this->_K(i) = std::clamp(this->_K(i), -this->_gain_clamp, this->_gain_clamp);
516 this->_param += this->_K * (y - s.transpose() * this->_param);
518 this->_cov -= this->_K * s.transpose() * this->_cov;
519 this->_cov /= this->_memory;
526 inline const Eigen::Vector<T, NParams>&
estimate()
const {
return this->_param;}
535 inline const Eigen::Matrix<T, NParams, NParams>&
cov()
const {
return this->_cov;}
544 inline const Eigen::Vector<T, NParams>&
gain()
const {
return this->_K;}
567 template<
class T,
size_t NumOrder,
size_t DenOrder,
size_t Measurements=1>
581 Eigen::Vector<T, NumOrder> uk = Eigen::Vector<T, NumOrder>::Zero();
582 Eigen::Vector<T, DenOrder> neg_yk = Eigen::Vector<T, DenOrder>::Zero();
597 const Eigen::Vector<T, NumOrder+1> NumeratorUncertainty,
598 const Eigen::Vector<T, DenOrder> DenominatorUncertainty,
599 const T& memory = 0.995)
601 T a_0 = hint.
den().at(0);
602 if(a_0 !=
static_cast<T
>(0)){
607 auto param = controlpp::join_to_vector<T, NumOrder+1, DenOrder>(hint.
num().vector(), hint.
den().vector().tail(DenOrder).eval());
608 this->rls.set_param(param);
610 auto cov = controlpp::join_to_diagonal<T, NumOrder+1, DenOrder>(NumeratorUncertainty, DenominatorUncertainty);
615 static_assert(NumOrder <= DenOrder,
"The Discrete Transfer Function has to be propper. Meaning `NumOrder <= DenOrder` has to be true.");
620 const T& uncertainty = 1000,
621 const T& memory = 0.995)
624 Eigen::Vector<T, NumOrder+1>().setOnes()*T(uncertainty),
625 Eigen::Vector<T, DenOrder>().setOnes()*T(uncertainty),
648 Eigen::Vector<T, 1 + NumOrder + DenOrder> s;
650 s.segment(1, NumOrder) = this->uk;
651 s.tail(DenOrder) = this->neg_yk;
652 this->rls.
input(y, s);
655 std::copy_backward(this->uk.data(), this->uk.data()+this->uk.size(), this->uk.data()+1);
659 std::copy_backward(this->neg_yk.data(), this->neg_yk.data()+this->neg_yk.size(), this->neg_yk.data()+1);
660 this->neg_yk(0) = -y;
669 Eigen::Vector<T, NumOrder+1 + DenOrder> est = rls.
estimate();
670 result.
num().vector() = est.head(NumOrder+1);
671 result.
den().vector()(0) = T(1);
672 result.
den().vector().tail(DenOrder) = est.tail(DenOrder);
676 const Eigen::Matrix<T, NumOrder+1 + DenOrder, NumOrder+1 + DenOrder>
cov(){
677 return this->rls.
cov();
680 const Eigen::Vector<T, NumOrder+1 + DenOrder>&
gain(){
681 return this->rls.
gain();
General algorithms that are used in multiple places in the library.
Continuous transfer functions in the s lapace plain.
Definition DiscreteTransferFunction.hpp:23
constexpr den_type & den()
Definition DiscreteTransferFunction.hpp:117
constexpr num_type & num()
Definition DiscreteTransferFunction.hpp:111
Estimates a discrete transfer function from online data points.
Definition Estimators.hpp:568
const Eigen::Vector< T, NumOrder+1+DenOrder > & gain()
Definition Estimators.hpp:680
DtfEstimator(DiscreteTransferFunction< T, NumOrder, DenOrder > hint, const T &uncertainty=1000, const T &memory=0.995)
Definition Estimators.hpp:618
const T & gain_clamp() const
Definition Estimators.hpp:688
DiscreteTransferFunction< T, NumOrder, DenOrder > estimate()
returns the current estimate
Definition Estimators.hpp:667
void set_cov_regularisation(const T ®)
Definition Estimators.hpp:692
DtfEstimator()
Definition Estimators.hpp:628
void set_gain_clamp(const T &g)
Definition Estimators.hpp:684
const Eigen::Matrix< T, NumOrder+1+DenOrder, NumOrder+1+DenOrder > cov()
Definition Estimators.hpp:676
void input(const T &y, const T &u)
Adds an interation step to the estimate.
Definition Estimators.hpp:646
T cov_regularisation() const
Definition Estimators.hpp:696
DtfEstimator(DiscreteTransferFunction< T, NumOrder, DenOrder > hint, const Eigen::Vector< T, NumOrder+1 > NumeratorUncertainty, const Eigen::Vector< T, DenOrder > DenominatorUncertainty, const T &memory=0.995)
Initialises a discrete transfer function estimator with optional hints and memory/decay parameters.
Definition Estimators.hpp:595
ReccursiveLeastSquares(const Eigen::Vector< T, NParams > ¶m_hint=Eigen::Vector< T, NParams >().setOnes(), const Eigen::Matrix< T, NParams, NParams > &cov_hint=(Eigen::Matrix< T, NParams, NParams >::Identity() *T(1000)), T memory=0.99, T cov_regularisation=1e-9)
Creates a recursive least square object with start parameters/covariance and a memory factor.
Definition Estimators.hpp:460
const Eigen::Vector< T, NParams > & gain() const
Returns the gain used for the updata.
Definition Estimators.hpp:544
void input(const T &y, const Eigen::Vector< T, NParams > &s)
Adds a new input output pair that updates the estimate.
Definition Estimators.hpp:503
const T & gain_clamp() const
Definition Estimators.hpp:493
void set_cov(const Eigen::Matrix< T, NParams, NParams > &cov)
Definition Estimators.hpp:477
void set_gain_clamp(const T &gain_clamp)
Definition Estimators.hpp:489
void set_memory(const T &memory)
Definition Estimators.hpp:485
const Eigen::Vector< T, NParams > & estimate() const
returns the current best estimate
Definition Estimators.hpp:526
const Eigen::Matrix< T, NParams, NParams > & cov() const
returns the current covariance
Definition Estimators.hpp:535
void set_param(const Eigen::Vector< T, NParams > ¶m)
Definition Estimators.hpp:481
Calculates the recursive least square for online parameter estimation.
Definition Estimators.hpp:195
void set_gain_clamp(const T &gain_clamp)
Limits the update gain K.
Definition Estimators.hpp:370
void set_memory(const T &memory)
Sets the memory factor.
Definition Estimators.hpp:343
const Eigen::Matrix< T, NParams, NParams > & cov() const
returns the current covariance
Definition Estimators.hpp:313
T cov_regularisation() const
Definition Estimators.hpp:330
const Eigen::Vector< T, NParams > & gain() const
Returns the gain K used in the parameter update.
Definition Estimators.hpp:391
const T & memory() const
Returns the memory factor.
Definition Estimators.hpp:356
const T & gain_clamp()
Returns the currect gain clamp factor.
Definition Estimators.hpp:378
ReccursiveLeastSquares(const Eigen::Vector< T, NParams > ¶m_hint=Eigen::Vector< T, NParams >().setOne(), T memory=0.99, T cov_regularisation=1e-9, T gain_clamp=10)
Creates a recursive least square object with start parameters/covariance and a memory factor.
Definition Estimators.hpp:249
const Eigen::Vector< T, NParams > & estimate() const
returns the current best estimate
Definition Estimators.hpp:304
void input(const T &y, const Eigen::Matrix< T, NMeasurements, NParams > &s)
Adds a new input output pair that updates the estimate.
Definition Estimators.hpp:274
void set_cov_regularisation(const T ®)
Set the value for the covariant regularisation.
Definition Estimators.hpp:326
void set_cov(const Eigen::Matrix< T, NParams, NParams > &cov)
Definition Estimators.hpp:315
Definition Polynom.hpp:1012
The main namespace for the Control++ library.
Definition Bode.cpp:3
void shift_up(Iterator first, Iterator last, const T &v0=T(0))
Shifts the values in a range up by one position and inserts a new value (copy operation) at the begin...
Definition algorithm.hpp:68
std::ostream & operator<<(std::ostream &stream, EBodeCsvReadError val)
Definition Bode.cpp:5
Eigen::Vector< T, XCols > least_squares(const Eigen::Matrix< T, XRows, XCols, XOpt, XMaxRows, XMaxCols > &X, const Eigen::Vector< T, XRows > &y)
Solves the overdefined system for p.
Definition Estimators.hpp:30
Eigen::Vector< T, LSize+RSize > join_to_vector(const Eigen::Vector< T, LSize > &l, const Eigen::Vector< T, RSize > &r)
Definition math.hpp:225
std::string_view to_string(dft_estimate_error err)
Definition Estimators.hpp:40
tl::expected< DiscreteTransferFunction< T, NumOrder, DenOrder >, dft_estimate_error > dft_estimate(const Eigen::Vector< T, Eigen::Dynamic > &u, const Eigen::Vector< T, Eigen::Dynamic > &y, const T ®ularization=T(0), const DiscreteTransferFunction< T, NumOrder, DenOrder > &hint=DiscreteTransferFunction< T, NumOrder, DenOrder >({T(0)}, {T(1)}))
Estimates a discrete time transfer function of a specific order for the input (u) and output (y) data...
Definition Estimators.hpp:78
dft_estimate_error
Definition Estimators.hpp:35
@ data_ranges_different_lenth