#ifndef ARX_CTRL_H #define ARX_CTRL_H #include using namespace bdm; /*! exact controller for system \f$ y_{t+1} = y_{t} + b u_{t} + \sigma e_t \f$ From \f$ E\{y_{ref}\} = E\{ y_{t} + b u_{t} \} \f$, the optimal control action is: \f[ u_t = (y_{ref} - y_{t})/b \f] */ class exact_ctrl: public Controller { protected: //! target value of y double yr; //! parameter b (or its estimate) double b; public: void set_b (const double b0){b=b0;} //! data in ctrlaction are only past outputs yt vec ctrlaction(const vec &yt)const{ vec ut(1); if (abs(b)<1e-2) { ut= 0.1*randn(); } else { ut = (yr-yt)/b; } return ut; } void from_setting(const Setting &set){ Controller::from_setting(set); UI::get(yr,set,"yr",UI::compulsory); UI::get(b,set,"b",UI::compulsory); validate(); } void validate() { } }; UIREGISTER(exact_ctrl); /*! adaptive CE controller for \f$ y_{t+1} = y_{t} + b u_{t} + \sigma e_t \f$ From \f$ E\{y_{ref}\} = E\{ y_{t} + b u_{t} \} \f$, the optimal control action is: \f[ u_t = (y_{ref} - y_{t})/b \f] Using certainty equivalent approach, i.e. \f$ b= E(b|y_t, u_t, \ldots )\f$, which is estimated using ARX model. This class is not truly appropriate since it estimates also \f$ \sigma \f$ */ class ce_ctrl: public exact_ctrl { protected: //! estimator ARX est; //! vector of "dyad" for estimation vec Psi; //! remember last action - for estimation double utm; //! remember last input - for estimation double ytm; public: //! expected input is yt virtual void adapt(const vec &dt){ //prepare data for ARX // do estimation est.bayes(vec_1(dt(0)-ytm),vec_1(dt(1))); ytm = dt(0); // save estimate b = E(b); b = est.posterior().mean()(0); // first } //! same as exact control, but stores ut as utm vec ctrlaction(const vec &dt)const{ vec ut(1); mat P = est.posterior().variance(); ut(0) =(yr - dt(0))/(b + (b<0 ? P(0,0) : -P(0,0)));; // remember last ut for estimation return ut; } void from_setting(const Setting &set){ Controller::from_setting(set); UI::get(yr,set,"yr",UI::compulsory); double b0; UI::get(b0,set,"b0",UI::compulsory); double P0; UI::get(P0,set,"P0",UI::compulsory); mat V0(2,2); V0(0,0) = 0.1; V0(1,0) = b0; V0(0,1) = b0; V0(1,1) = P0/6; est.set_statistics(1,V0,6); est.set_constant(false); est.validate(); validate(); } void validate(){ Psi = zeros(2); } void log_register( logger& L, const string& prefix ){ est.set_log_level(1); est.log_register(L,""); }; void log_write() const{ est.log_write(); } }; UIREGISTER(ce_ctrl); #endif //ARX_CTRL