/*! \file \brief DataSource for experiments with realistic simulator of the PMSM model \author Vaclav Smidl. ----------------------------------- BDM++ - C++ library for Bayesian Decision Making under Uncertainty Using IT++ for numerical operations ----------------------------------- */ #include #include #include "simulator_zdenek/simulator.h" #include "pmsm.h" using namespace bdm; //! Simulator of PMSM machine with predefined profile on omega class pmsmDS : public DS { protected: //! indeces of logged variables int L_x, L_ou, L_oy, L_iu, L_optu; //! Setpoints of omega in timespans given by dt_prof vec profileWw; //! Setpoints of Mz in timespans given by dt_prof vec profileMz; //! time-step for profiles double dt_prof; //! Number of miliseconds per discrete time step int Dt; //! options for logging, - log predictions of 'true' voltage bool opt_modu; //! options for logging, - public: //! Constructor with fixed sampling period pmsmDS () { Dt=125; Drv=RV ( "{o_ua o_ub o_ia o_ib t_ua t_ub o_om o_th Mz }" ); } void set_parameters ( double Rs0, double Ls0, double Fmag0, double Bf0, double p0, double kp0, double J0, double Uc0, double DT0, double dt0 ) { pmsmsim_set_parameters ( Rs0, Ls0, Fmag0, Bf0, p0, kp0, J0, Uc0, DT0, dt0 ); } //! parse options: "modelu" => opt_modu=true; void set_options ( string &opt ) { opt_modu = ( opt.find ( "modelu" ) !=string::npos ); } void getdata ( vec &dt ) { dt.set_subvector(0,vec ( KalmanObs,6 )); dt(6)=x[2]; dt(7)=x[3]; dt(8)=x[8]; } void write ( vec &ut ) {} void step() { static int ind=0; static double dW; // increase of W static double Ww; // W static double Mz; // W if ( t>=dt_prof*ind ) { ind++; // check omega profile and set dW if ( ind <2 && profileWw.length() ==1 ) { Ww=profileWw ( 0 ); dW=0.0; } if ( ind0.3 ) - double ( i1<-0.3 ) ) +0.2*i1; double du2=1.4* ( double ( i2>0.3 ) - double ( i2<-0.3 ) ) +0.2*i2; double du3=1.4* ( double ( i3>0.3 ) - double ( i3<-0.3 ) ) +0.2*i3; ua = ( 2.0* ( u1-du1 )- ( u2-du2 )- ( u3-du3 ) ) /3.0; ub = ( ( u2-du2 )- ( u3-du3 ) ) /sq3; L.logit ( L_optu , vec_2 ( ua,ub ) ); } } void set_profile ( double dt, const vec &Ww, const vec &Mz ) { dt_prof=dt; profileWw=Ww; profileMz=Mz; } void from_setting( const Setting &root ) { const SettingResolver& params_l(root["params"]); const Setting ¶ms = params_l.result; set_parameters ( params["Rs"], params["Ls"], params["Fmag"], \ params["Bf"], params["p"], params["kp"], \ params["J"], params["Uc"], params["DT"], 1.0e-6 ); // Default values of profiles for omega and Mz vec profW=vec("1.0"); vec profM=vec("0.0"); double tstep=1.0; root.lookupValue( "tstep", tstep ); UI::get( profW, root, "profileW" ); UI::get( profM, root, "profileM" ); set_profile (tstep , profW, profM); string opts; if ( root.lookupValue( "options", opts ) ) set_options(opts); } // TODO dodelat void to_setting( Setting &root ) const; }; UIREGISTER ( pmsmDS ); //! This class behaves like BM but it is evaluating EKF class pmsmCRB : public EKFfull { protected: vec interr; vec old_true; vec secder; int L_CRB; int L_err; int L_sec; public: //! constructor pmsmCRB():EKFfull() { old_true=zeros(6); } void bayes(const vec &dt) { static vec umin(2); vec u(2); vec &mu = est->_mu(); //assume we know state exactly: vec true_state=vec(x,4); // read from pmsm mu=true_state; //integration error old_true(4)=KalmanObs[4]; old_true(5)=KalmanObs[5];// add U u(0) = KalmanObs[0]; // use the required value for derivatives u(1) = KalmanObs[1]; interr = (true_state - pfxu->eval(old_true)); //second derivative IMpmsm2o* pf = dynamic_cast(pfxu.get()); if (pf) { secder=pf->eval2o(u-umin); } umin =u; EKFfull::bayes(dt); old_true.set_subvector(0,true_state); } void log_add(logger &L, const string &name="" ) { L_CRB=L.add(rx,"crb"); L_err=L.add(rx,"err"); L_sec=L.add(rx,"d2"); } void logit(logger &L) { L.logit(L_err, interr); L.logit(L_CRB,diag(_R())); L.logit(L_sec,secder); } void from_setting( const Setting &root ) { shared_ptr IM = UI::build(root, "IM"); shared_ptr OM = UI::build(root, "OM"); //parameters //statistics int dim=IM->dimension(); vec mu0; if(root.exists("mu0")) UI::get( mu0, root, "mu0"); else mu0=zeros(dim); mat P0; if(root.exists( "dP0" )) { vec dP0; UI::get(dP0,root, "dP0"); P0=diag(dP0); } else if (root.exists("P0")) UI::get(P0,root, "P0"); else P0=eye(dim); set_statistics(mu0,P0); vec dQ; UI::get( dQ, root, "dQ"); vec dR; UI::get( dR, root, "dR"); set_parameters(IM, OM, diag(dQ) , diag(dR)); //connect shared_ptr drv = UI::build(root, "drv"); set_drv(*drv); shared_ptr rv = UI::build(root, "rv"); set_rv(*rv); } // TODO dodelat void to_setting( Setting &root ) const; }; UIREGISTER ( pmsmCRB ); //! This class behaves like BM but it is evaluating EKF class pmsmCRBMz : public EKFfull { protected: int L_CRB; public: //! constructor pmsmCRBMz():EKFfull() {} void bayes(const vec &dt) { //assume we know state exactly: vec true_state(5); true_state.set_subvector(0,vec(x,4)); // read from pmsm true_state(4)=x[8]; vec &mu = est->_mu(); mu = true_state; //hack for ut EKFfull::bayes(dt); } void log_add(logger &L, const string &name="" ) { L_CRB=L.add(concat(rx,RV("Mz",1,0)),"crbz"); } void logit(logger &L) { L.logit(L_CRB,diag(_R())); } void from_setting( const Setting &root ) { shared_ptr IM = UI::build(root,"IM"); shared_ptr OM = UI::build(root,"OM"); //statistics int dim=IM->dimension(); vec mu0; if( root.exists( "mu0")) UI::get(mu0, root, "mu0"); else mu0=zeros(dim); mat P0; if(root.exists("dP0")) { vec dP0; UI::get(dP0, root, "dP0"); P0=diag(dP0); } else if(root.exists("P0")) UI::get( P0, root, "P0" ); else P0=eye(dim); set_statistics(mu0,P0); vec dQ; UI::get(dQ, root, "dQ"); vec dR; UI::get(dR, root, "dR"); set_parameters(IM, OM, diag(dQ), diag(dR)); //connect shared_ptr drv = UI::build(root, "drv"); set_drv(*drv); shared_ptr rv = UI::build(root, "rv"); set_rv(*rv); } // TODO dodelat void to_setting( Setting &root ) const; }; UIREGISTER ( pmsmCRBMz );