#ifndef PMSM_H #define PMSM_H #include #include "base/user_info.h" #include "ekf_example/reference_Q15.h" /*! \defgroup PMSM @{ */ using namespace bdm; //TODO hardcoded RVs!!! // RV rx ( "{ia ib om th }"); // RV ru ( "{o_ua o_ub }"); // RV ry ( "{oia oib }"); // class uipmsm : public uibase{ // double Rs, Ls, dt, Ypm, kp, p, J, Mz; // }; inline double va_drop_interp(double i){ //double va_char[16]={0,10,50,100,200,300,500,1000, 0,1,1.8,2.4,3.2,3.8,4.8,6.8}; //* double si = sign(i); i = abs(i); double du; if(i < 0.1) du = 5.0*i; else if(i < 0.5) du = 1.0*(i-0.1) + 0.5; else if(i < 1.0) du = 0.6*(i-0.5) + 0.9; else if(i < 2.0) du = 0.4*(i-1.0) + 1.2; else if(i < 3.0) du = 0.3*(i-2.0) + 1.6; else if(i < 5.0) du = 0.25*(i-3.0) + 1.9; else du = 0.2*(i - 5.0) + 2.4; return si*du*1.0; /*/ double msi = sign(i); i = abs(i) - 0.3; double si = sign(i); i = abs(i); double du; if(i < 0.0654) du = 5.0*i; else if(i < 0.3225) du = 1.0*(i-0.0654) + 0.3225; else if(i < 0.654) du = 0.6*(i-0.3225) + 0.5805; else if(i < 1.29) du = 0.4*(i-0.654) + 0.774; else if(i < 1.935) du = 0.3*(i-1.29) + 1.032; else if(i < 3.225) du = 0.25*(i-1.935) + 1.2255; else du = 0.2*(i - 3.225) + 1.548; return msi*(si*du+0.558); /*/ } //! State evolution model for a PMSM drive and its derivative with respect to \f$x\f$ class IMpmsm : public diffbifn { protected: double Rs, Ls, dt, Ypm, kp, p, J, Mz; bool compensate; bool cutoff; public: IMpmsm() :diffbifn ( ) {dimy=4; dimx = 4; dimu=2; dimc=6;compensate=false;cutoff=true;}; //! Set mechanical and electrical variables virtual void set_parameters ( double Rs0, double Ls0, double dt0, double Ypm0, double kp0, double p0, double J0, double Mz0 ) {Rs=Rs0; Ls=Ls0; dt=dt0; Ypm=Ypm0; kp=kp0; p=p0; J=J0; Mz=Mz0;} void modelpwm(const vec &x0, const vec u0, double &ua, double &ub){ /* ua=u0[0]; ub=u0[1]; return;*/ double sq3=sqrt ( 3.0 ); double i1=x0(0); double i2=0.5* ( -i1+sq3*x0[1] ); double i3=0.5* ( -i1-sq3*x0[1] ); double u1=u0(0); double u2=0.5* ( -u1+sq3*u0(1) ); double u3=0.5* ( -u1-sq3*u0(1) ); // double du1=va_drop_interp(i1); double du2=va_drop_interp(i2); double du3=va_drop_interp(i3); /*/ double du1=1.4* ( double ( i1>0.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; } vec eval ( const vec &x0, const vec &u0 ) { // last state const double &iam = x0 ( 0 ); const double &ibm = x0 ( 1 ); const double &omm = x0 ( 2 ); const double &thm = x0 ( 3 ); double uam; double ubm; if (compensate){ modelpwm(x0,u0,uam,ubm); } else { uam = u0(0); ubm = u0(1); } vec xk( 4 ); //ia xk ( 0 ) = ( 1.0- Rs/Ls*dt ) * iam + Ypm/Ls*dt*omm * sin ( thm ) + uam*dt/Ls; //ib xk ( 1 ) = ( 1.0- Rs/Ls*dt ) * ibm - Ypm/Ls*dt*omm * cos ( thm ) + ubm*dt/Ls; //om xk ( 2 ) = omm + kp*p*p * Ypm/J*dt* ( ibm * cos ( thm )-iam * sin ( thm ) ) - p/J*dt*Mz; //th xk ( 3 ) = thm + omm*dt; // <0..2pi> if (cutoff) { if ( xk ( 3 ) >pi ) xk ( 3 )-=2*pi; if ( xk ( 3 ) <-pi ) xk ( 3 ) +=2*pi; } return xk; } void dfdx_cond ( const vec &x0, const vec &u0, mat &A, bool full=true ) { const double &iam = x0 ( 0 ); const double &ibm = x0 ( 1 ); const double &omm = x0 ( 2 ); const double &thm = x0 ( 3 ); // d ia A ( 0,0 ) = ( 1.0- Rs/Ls*dt ); A ( 0,1 ) = 0.0; A ( 0,2 ) = Ypm/Ls*dt* sin ( thm ); A ( 0,3 ) = Ypm/Ls*dt*omm * ( cos ( thm ) ); // d ib A ( 1,0 ) = 0.0 ; A ( 1,1 ) = ( 1.0- Rs/Ls*dt ); A ( 1,2 ) = -Ypm/Ls*dt* cos ( thm ); A ( 1,3 ) = Ypm/Ls*dt*omm * ( sin ( thm ) ); // d om A ( 2,0 ) = kp*p*p * Ypm/J*dt* ( - sin ( thm ) ); A ( 2,1 ) = kp*p*p * Ypm/J*dt* ( cos ( thm ) ); A ( 2,2 ) = 1.0; A ( 2,3 ) = kp*p*p * Ypm/J*dt* ( -ibm * sin ( thm )-iam * cos ( thm ) ); // d th A ( 3,0 ) = 0.0; A ( 3,1 ) = 0.0; A ( 3,2 ) = dt; A ( 3,3 ) = 1.0; } void dfdu_cond ( const vec &x0, const vec &u0, mat &A, bool full=true ) {it_error ( "not needed" );}; void from_setting( const Setting &root ) { const SettingResolver& params_b=root["params"]; const Setting& params=params_b.result; set_parameters ( params["Rs"], params["Ls"], 125e-6, params["Fmag"], \ params["kp"], params["p"], params["J"], 0.0); int comp=0; if (UI::get(comp,root,"compensate",UI::optional)){compensate=(comp==1);} int cuto=0; if (UI::get(cuto,root,"cutoff",UI::optional)){cutoff=(cuto==1);} }; // TODO dodelat void to_setting( Setting &root ) const; }; UIREGISTER ( IMpmsm ); //! Evolution model of \f$ \omega, \vartheta\f$ for a PMSM drive and its derivative with respect to \f$x\f$ class IMpmsmOT : public diffbifn { protected: double Rs, Ls, dt, Ypm, kp, p, J, Mz; bool compensate; bool cutoff; public: IMpmsmOT() :diffbifn ( ) {dimy=2; dimx = 2; dimu=4; dimc=6;compensate=false;cutoff=true;}; //! Set mechanical and electrical variables virtual void set_parameters ( double Rs0, double Ls0, double dt0, double Ypm0, double kp0, double p0, double J0, double Mz0 ) {Rs=Rs0; Ls=Ls0; dt=dt0; Ypm=Ypm0; kp=kp0; p=p0; J=J0; Mz=Mz0;} void modelpwm(const vec &x0, const vec u0, double &ua, double &ub){ /* ua=u0[0]; * ub=u0[1]; * return;*/ double sq3=sqrt ( 3.0 ); double i1=x0(0); double i2=0.5* ( -i1+sq3*x0[1] ); double i3=0.5* ( -i1-sq3*x0[1] ); double u1=u0(0); double u2=0.5* ( -u1+sq3*u0(1) ); double u3=0.5* ( -u1-sq3*u0(1) ); double du1=1.4* ( double ( i1>0.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; } vec eval ( const vec &x0, const vec &u0 ) { // last state const double &omm = x0 ( 0 ); const double &thm = x0 ( 1 ); double uam; double ubm; if (compensate){ modelpwm(x0,u0,uam,ubm); } else { uam = u0(0); ubm = u0(1); } const double &iam = u0 ( 2 ); const double &ibm = u0 ( 3 ); vec xk( 2 ); //ia //om xk ( 0 ) = omm + kp*p*p * Ypm/J*dt* ( ibm * cos ( thm )-iam * sin ( thm ) ) - p/J*dt*Mz; //th xk ( 1 ) = thm + omm*dt; // <0..2pi> if (cutoff) { if ( xk ( 1 ) >pi ) xk ( 1 )-=2*pi; if ( xk ( 1 ) <-pi ) xk ( 1 ) +=2*pi; } return xk; } void dfdx_cond ( const vec &x0, const vec &u0, mat &A, bool full=true ) { // const double &omm = x0 ( 0 ); const double &thm = x0 ( 1 ); const double &iam = u0 ( 2 ); const double &ibm = u0 ( 3 ); // d ia // d om A ( 0,0 ) = 1.0; A ( 0,1 ) = kp*p*p * Ypm/J*dt* ( -ibm * sin ( thm )-iam * cos ( thm ) ); // d th A ( 1,0 ) = dt; A ( 1,1 ) = 1.0; } void dfdu_cond ( const vec &x0, const vec &u0, mat &A, bool full=true ) {it_error ( "not needed" );}; void from_setting( const Setting &root ) { const SettingResolver& params_b=root["params"]; const Setting& params=params_b.result; set_parameters ( params["Rs"], params["Ls"], 125e-6, params["Fmag"], \ params["kp"], params["p"], params["J"], 0.0); int comp=0; if (UI::get(comp,root,"compensate",UI::optional)){compensate=(comp==1);} int cuto=0; if (UI::get(cuto,root,"cutoff",UI::optional)){cutoff=(cuto==1);} }; // TODO dodelat void to_setting( Setting &root ) const; }; UIREGISTER ( IMpmsmOT ); //! Evolution model of \f$ \omega, \vartheta\f$ for a PMSM drive and its derivative with respect to \f$x\f$ class IMpmsmOTM : public diffbifn { protected: double Rs, Ls, dt, Ypm, kp, p, J, Mz; bool compensate; bool cutoff; public: IMpmsmOTM() :diffbifn ( ) {dimy=2; dimx = 3; dimu=4; dimc=6;compensate=false;cutoff=true;}; //! Set mechanical and electrical variables virtual void set_parameters ( double Rs0, double Ls0, double dt0, double Ypm0, double kp0, double p0, double J0, double Mz0 ) {Rs=Rs0; Ls=Ls0; dt=dt0; Ypm=Ypm0; kp=kp0; p=p0; J=J0; Mz=Mz0;} void modelpwm(const vec &x0, const vec u0, double &ua, double &ub){ /* ua=u0[0]; * ub=u0[1]; * return;*/ double sq3=sqrt ( 3.0 ); double i1=x0(0); double i2=0.5* ( -i1+sq3*x0[1] ); double i3=0.5* ( -i1-sq3*x0[1] ); double u1=u0(0); double u2=0.5* ( -u1+sq3*u0(1) ); double u3=0.5* ( -u1-sq3*u0(1) ); double du1=1.4* ( double ( i1>0.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; } vec eval ( const vec &x0, const vec &u0 ) { // last state const double &omm = x0 ( 0 ); const double &thm = x0 ( 1 ); const double &Mm = x0 ( 2 ); double uam; double ubm; if (compensate){ modelpwm(x0,u0,uam,ubm); } else { uam = u0(0); ubm = u0(1); } const double &iam = u0 ( 2 ); const double &ibm = u0 ( 3 ); vec xk( 3 ); //ia //om xk ( 0 ) = omm + kp*p*p * Ypm/J*dt* ( ibm * cos ( thm )-iam * sin ( thm ) ) - p/J*dt*Mm; //th xk ( 1 ) = thm + omm*dt; // <0..2pi> xk (2) = Mm; if (cutoff) { if ( xk ( 1 ) >pi ) xk ( 1 )-=2*pi; if ( xk ( 1 ) <-pi ) xk ( 1 ) +=2*pi; } return xk; } void dfdx_cond ( const vec &x0, const vec &u0, mat &A, bool full=true ) { // const double &omm = x0 ( 0 ); const double &thm = x0 ( 1 ); // const double &Mm = x0 ( 2 ); const double &iam = u0 ( 2 ); const double &ibm = u0 ( 3 ); // d ia // d om A ( 0,0 ) = 1.0; A ( 0,1 ) = kp*p*p * Ypm/J*dt* ( -ibm * sin ( thm )-iam * cos ( thm ) ); A ( 0,2 ) = -p/J*dt; // d th A ( 1,0 ) = dt; A ( 1,1 ) = 1.0; A ( 1,2 ) = 0.0; // d M A ( 2,0 ) = 0.0; A ( 2,1 ) = 0.0; A ( 2,2 ) = 1.0; } void dfdu_cond ( const vec &x0, const vec &u0, mat &A, bool full=true ) {it_error ( "not needed" );}; void from_setting( const Setting &root ) { const SettingResolver& params_b=root["params"]; const Setting& params=params_b.result; set_parameters ( params["Rs"], params["Ls"], 125e-6, params["Fmag"], \ params["kp"], params["p"], params["J"], 0.0); int comp=0; if (UI::get(comp,root,"compensate",UI::optional)){compensate=(comp==1);} int cuto=0; if (UI::get(cuto,root,"cutoff",UI::optional)){cutoff=(cuto==1);} }; // TODO dodelat void to_setting( Setting &root ) const; }; UIREGISTER ( IMpmsmOTM ); //! Evolution model of \f$ \omega, \vartheta\f$ for a PMSM drive and its derivative with respect to \f$x\f$ -- Scaled to [-1,1] class IMpmsmOTsc : public diffbifn { protected: double Rs, Ls, dt, Ypm, kp, p, J, Mz; bool cutoff; public: IMpmsmOTsc() :diffbifn ( ) {dimy=2; dimx = 2; dimu=4; dimc=6;cutoff=true;}; //! Set mechanical and electrical variables virtual void set_parameters ( double Rs0, double Ls0, double dt0, double Ypm0, double kp0, double p0, double J0, double Mz0 ) {Rs=Rs0; Ls=Ls0; dt=dt0; Ypm=Ypm0; kp=kp0; p=p0; J=J0; Mz=Mz0;} vec eval ( const vec &x0, const vec &u0 ) { // last state const double &omm = x0 ( 0 ); const double &thm = x0 ( 1 ); double uam; double ubm; uam = u0(0); ubm = u0(1); const double &iam = u0 ( 2 ); const double &ibm = u0 ( 3 ); vec xk( 2 ); //ia //om xk ( 0 ) = omm + kp*p*p * Ypm/J*dt *Iref/Wref* ( ibm * cos ( thm*Thetaref/(1<<15) )-iam * sin ( thm*Thetaref/(1<<15) ) ); //th xk ( 1 ) = thm + omm*Wref/Thetaref*dt; // <0..2pi> if (cutoff) { if ( xk ( 1 ) >(1<<15) ) xk ( 1 )=-(1<<15); if ( xk ( 1 ) <-(1<<15) ) xk ( 1 ) =(1<<15); } return xk; } void dfdx_cond ( const vec &x0, const vec &u0, mat &A, bool full=true ) { const double &omm = x0 ( 0 ); const double &thm = x0 ( 1 ); const double &iam = u0 ( 2 ); const double &ibm = u0 ( 3 ); // d ia // d om A ( 0,0 ) = 1.0; A ( 0,1 ) = 0.0;//kp*p*p * Ypm/J*dt* ( -ibm * sin ( thm )-iam * cos ( thm ) ); // d th A ( 1,0 ) = dt*Wref/Thetaref; A ( 1,1 ) = 1.0; } void dfdu_cond ( const vec &x0, const vec &u0, mat &A, bool full=true ) {it_error ( "not needed" );}; void from_setting( const Setting &root ) { const SettingResolver& params_b=root["params"]; const Setting& params=params_b.result; set_parameters ( params["Rs"], params["Ls"], 125e-6, params["Fmag"], \ params["kp"], params["p"], params["J"], 0.0); int cuto=0; if (UI::get(cuto,root,"cutoff",UI::optional)){cutoff=(cuto==1);} }; // TODO dodelat void to_setting( Setting &root ) const; }; UIREGISTER ( IMpmsmOTsc ); //! State evolution model for a PMSM drive and its derivative with respect to \f$x\f$ class IMpmsmDQ : public diffbifn { protected: double Rs, Ld, Lq, dt, Ypm, kp, p, J, Mz; bool compensate; bool cutoff; public: IMpmsmDQ() :diffbifn ( ) {dimy=4; dimx = 4; dimu=2; dimc=6;compensate=true;cutoff=true;}; //! Set mechanical and electrical variables virtual void set_parameters ( double Rs0, double Ld0, double Lq0, double dt0, double Ypm0, double kp0, double p0, double J0, double Mz0 ) {Rs=Rs0; Ld=Ld0; Lq=Lq0; dt=dt0; Ypm=Ypm0; kp=kp0; p=p0; J=J0; Mz=Mz0;} void modelpwm(const vec &x0, const vec u0, double &ua, double &ub){ /* ua=u0[0]; * ub=u0[1]; * return;*/ double sq3=sqrt ( 3.0 ); double i1=x0(0); double i2=0.5* ( -i1+sq3*x0[1] ); double i3=0.5* ( -i1-sq3*x0[1] ); double u1=u0(0); double u2=0.5* ( -u1+sq3*u0(1) ); double u3=0.5* ( -u1-sq3*u0(1) ); double du1=1.4* ( double ( i1>0.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; } vec eval ( const vec &x0, const vec &u0 ) { // last state const double &idm = x0 ( 0 ); const double &iqm = x0 ( 1 ); const double &omm = x0 ( 2 ); const double &thm = x0 ( 3 ); double uam; double ubm; if (compensate){ modelpwm(x0,u0,uam,ubm); } else { uam = u0(0); ubm = u0(1); } vec xk( 4 ); //id xk ( 0 ) = ( 1.0- Rs/Ld*dt ) * idm + Lq/Ld*iqm*dt*omm + dt/Ld*(cos(thm)*uam+sin(thm)*ubm); //iq xk ( 1 ) = ( 1.0- Rs/Lq*dt ) * iqm - Ypm/Lq*dt*omm - Ld/Lq*dt*idm*omm + dt/Lq*(-sin(thm)*uam+cos(thm)*ubm); //om xk ( 2 ) = omm + kp*p*p /J*dt* ( (Ld-Lq)*idm+ Ypm)*iqm - p/J*dt*Mz; //th xk ( 3 ) = thm + omm*dt; // <0..2pi> if (cutoff) { if ( xk ( 3 ) >pi ) xk ( 3 )-=2*pi; if ( xk ( 3 ) <-pi ) xk ( 3 ) +=2*pi; } return xk; } void dfdx_cond ( const vec &x0, const vec &u0, mat &A, bool full=true ) { const double &idm = x0 ( 0 ); const double &iqm = x0 ( 1 ); const double &omm = x0 ( 2 ); const double &thm = x0 ( 3 ); double uam; double ubm; if (compensate){ modelpwm(x0,u0,uam,ubm); } else { uam = u0(0); ubm = u0(1); } // d id A ( 0,0 ) = ( 1.0- Rs/Ld*dt ); A ( 0,1 ) = Lq/Ld*dt*omm; A ( 0,2 ) = Lq/Ld*iqm*dt; A ( 0,3 ) = dt/Ld*(-sin(thm)*uam+cos(thm)*ubm); // d iq A ( 1,0 ) = -Ld/Lq*omm*dt ; A ( 1,1 ) = ( 1.0- Rs/Lq*dt ); A ( 1,2 ) = -Ypm/Lq*dt- Ld/Lq*dt*idm; A ( 1,3 ) = dt/Lq*(-cos(thm)*uam-sin(thm)*ubm); // d om A ( 2,0 ) = kp*p*p /J*dt* ( Ld-Lq)*iqm; A ( 2,1 ) = kp*p*p /J*dt* ((Ld-Lq)*idm+Ypm); A ( 2,2 ) = 1.0; A ( 2,3 ) = 0; // d th A ( 3,0 ) = 0.0; A ( 3,1 ) = 0.0; A ( 3,2 ) = dt; A ( 3,3 ) = 1.0; } void dfdu_cond ( const vec &x0, const vec &u0, mat &A, bool full=true ) {it_error ( "not needed" );}; void from_setting( const Setting &root ) { const SettingResolver& params_b=root["params"]; const Setting& params=params_b.result; set_parameters ( params["Rs"], params["Ld"],params["Lq"], 125e-6, params["Fmag"], \ params["kp"], params["p"], params["J"], 0.0); int comp=0; if (UI::get(comp,root,"compensate",UI::optional)){compensate=(comp==1);} int cuto=0; if (UI::get(cuto,root,"cutoff",UI::optional)){ cutoff=(cuto==1); } }; // TODO dodelat void to_setting( Setting &root ) const; }; UIREGISTER ( IMpmsmDQ ); //! State evolution model for a PMSM drive and its derivative with respect to \f$x\f$ class IMpmsm2o : public IMpmsm { protected: // double Rs, Ls, dt, Ypm, kp, p, J, Mz; //! store first derivatives for the use in second derivatives double dia, dib, dom, dth; //! d2t = dt^2/2, cth = cos(th), sth=sin(th) double d2t, cth, sth; double iam, ibm, omm, thm, uam, ubm; public: IMpmsm2o() :IMpmsm () {}; //! Set mechanical and electrical variables void set_parameters ( double Rs0, double Ls0, double dt0, double Ypm0, double kp0, double p0, double J0, double Mz0 ) {Rs=Rs0; Ls=Ls0; dt=dt0; Ypm=Ypm0; kp=kp0; p=p0; J=J0; Mz=Mz0; d2t=dt*dt/2;} vec eval ( const vec &x0, const vec &u0 ) { // last state iam = x0 ( 0 ); ibm = x0 ( 1 ); omm = x0 ( 2 ); thm = x0 ( 3 ); uam = u0 ( 0 ); ubm = u0 ( 1 ); cth = cos(thm); sth = sin(thm); dia = (- Rs/Ls*iam + Ypm/Ls*omm * sth + uam/Ls); dib = (- Rs/Ls*ibm - Ypm/Ls*omm * cth + ubm/Ls); dom = kp*p*p * Ypm/J *( ibm * cth-iam * sth ) - p/J*Mz; dth = omm; vec xk=zeros ( 4 ); xk ( 0 ) = iam + dt*dia;// +d2t*d2ia; xk ( 1 ) = ibm + dt*dib;// +d2t*d2ib; xk ( 2 ) = omm +dt*dom;// +d2t*d2om; xk ( 3 ) = thm + dt*dth;// +d2t*dom; // <0..2pi> if ( xk ( 3 ) >pi ) xk ( 3 )-=2*pi; if ( xk ( 3 ) <-pi ) xk ( 3 ) +=2*pi; return xk; } //! eval 2nd order Taylor expansion, MUST be used only as a follow up AFTER eval()!! vec eval2o(const vec &du){ double dua = du ( 0 )/dt; double dub = du ( 1 )/dt; vec xth2o(4); xth2o(0) = (- Rs/Ls*dia + Ypm/Ls*(dom * sth + omm*cth) + dua/Ls); xth2o(1) = (- Rs/Ls*dib - Ypm/Ls*(dom * cth - omm*sth) + dub/Ls); xth2o(2) = kp*p*p * Ypm/J *( dib * cth-ibm*sth - (dia * sth + iam *cth)); xth2o(3) = dom; // multiply by dt^2/2 xth2o*=d2t/2; return xth2o; } void dfdx_cond ( const vec &x0, const vec &u0, mat &A, bool full=true ) { iam = x0 ( 0 ); ibm = x0 ( 1 ); omm = x0 ( 2 ); thm = x0 ( 3 ); // d ia A ( 0,0 ) = ( 1.0- Rs/Ls*dt ); A ( 0,1 ) = 0.0; A ( 0,2 ) = Ypm/Ls*dt* sin ( thm ); A ( 0,3 ) = Ypm/Ls*dt*omm * ( cos ( thm ) ); // d ib A ( 1,0 ) = 0.0 ; A ( 1,1 ) = ( 1.0- Rs/Ls*dt ); A ( 1,2 ) = -Ypm/Ls*dt* cos ( thm ); A ( 1,3 ) = Ypm/Ls*dt*omm * ( sin ( thm ) ); // d om A ( 2,0 ) = kp*p*p * Ypm/J*dt* ( - sin ( thm ) ); A ( 2,1 ) = kp*p*p * Ypm/J*dt* ( cos ( thm ) ); A ( 2,2 ) = 1.0; A ( 2,3 ) = kp*p*p * Ypm/J*dt* ( -ibm * sin ( thm )-iam * cos ( thm ) ); // d th A ( 3,0 ) = 0.0; A ( 3,1 ) = 0.0; A ( 3,2 ) = dt; A ( 3,3 ) = 1.0; // FOR d2t*dom!!!!!!!!! /* A ( 3,0 ) = dt* kp*p*p * Ypm/J*dt* ( - sin ( thm ) ); A ( 3,1 ) = dt* kp*p*p * Ypm/J*dt* ( cos ( thm ) ); A ( 3,2 ) = dt; A ( 3,3 ) = 1.0 + dt* kp*p*p * Ypm/J*dt* ( -ibm * sin ( thm )-iam * cos ( thm ) );*/ } void dfdu_cond ( const vec &x0, const vec &u0, mat &A, bool full=true ) {it_error ( "not needed" );}; }; UIREGISTER ( IMpmsm2o ); //! State evolution model for a PMSM drive and its derivative with respect to \f$x\f$, equation for \f$\omega\f$ is omitted.$ class IMpmsmStat : public IMpmsm { public: IMpmsmStat() :IMpmsm() {}; //! Set mechanical and electrical variables void set_parameters ( double Rs0, double Ls0, double dt0, double Ypm0, double kp0, double p0, double J0, double Mz0 ) {Rs=Rs0; Ls=Ls0; dt=dt0; Ypm=Ypm0; kp=kp0; p=p0; J=J0; Mz=Mz0;} vec eval ( const vec &x0, const vec &u0 ) { // last state double iam = x0 ( 0 ); double ibm = x0 ( 1 ); double omm = x0 ( 2 ); double thm = x0 ( 3 ); double uam = u0 ( 0 ); double ubm = u0 ( 1 ); vec xk=zeros ( 4 ); //ia xk ( 0 ) = ( 1.0- Rs/Ls*dt ) * iam + Ypm/Ls*dt*omm * sin ( thm ) + uam*dt/Ls; //ib xk ( 1 ) = ( 1.0- Rs/Ls*dt ) * ibm - Ypm/Ls*dt*omm * cos ( thm ) + ubm*dt/Ls; //om xk ( 2 ) = omm - p/J*dt*Mz;// + kp*p*p * Ypm/J*dt* ( ibm * cos ( thm )-iam * sin ( thm ) ); //th xk ( 3 ) = rem(thm + omm*dt,2*pi); // <0..2pi> return xk; } void dfdx_cond ( const vec &x0, const vec &u0, mat &A, bool full=true ) { // double iam = x0 ( 0 ); // double ibm = x0 ( 1 ); double omm = x0 ( 2 ); double thm = x0 ( 3 ); // d ia A ( 0,0 ) = ( 1.0- Rs/Ls*dt ); A ( 0,1 ) = 0.0; A ( 0,2 ) = Ypm/Ls*dt* sin ( thm ); A ( 0,3 ) = Ypm/Ls*dt*omm * ( cos ( thm ) ); // d ib A ( 1,0 ) = 0.0 ; A ( 1,1 ) = ( 1.0- Rs/Ls*dt ); A ( 1,2 ) = -Ypm/Ls*dt* cos ( thm ); A ( 1,3 ) = Ypm/Ls*dt*omm * ( sin ( thm ) ); // d om A ( 2,0 ) = 0.0;//kp*p*p * Ypm/J*dt* ( - sin ( thm ) ); A ( 2,1 ) = 0.0;//kp*p*p * Ypm/J*dt* ( cos ( thm ) ); A ( 2,2 ) = 1.0; A ( 2,3 ) = 0.0;//kp*p*p * Ypm/J*dt* ( -ibm * sin ( thm )-iam * cos ( thm ) ); // d th A ( 3,0 ) = 0.0; A ( 3,1 ) = 0.0; A ( 3,2 ) = dt; A ( 3,3 ) = 1.0; } void dfdu_cond ( const vec &x0, const vec &u0, mat &A, bool full=true ) {it_error ( "not needed" );}; }; UIREGISTER ( IMpmsmStat ); //! State for PMSM with unknown Mz class IMpmsmMz: public IMpmsm{ public: IMpmsmMz() {dimy=5; dimx = 5; dimu=2;}; //! extend eval by Mz vec eval ( const vec &x0, const vec &u0 ) { vec x(4); Mz = x0(4); //last of the state is Mz //teh first 4 states are same as before (given that Mz is set) x=IMpmsm::eval(x0,u0); // including model of drops! return concat(x,Mz); } void dfdx_cond ( const vec &x0, const vec &u0, mat &A, bool full=true ) { //call initial if (full) A.clear(); IMpmsm::dfdx_cond(x0,u0,A,full); A(2,4)=- p/J*dt; A(4,4)=1.0; } }; UIREGISTER ( IMpmsmMz ); //! State for PMSM with unknown Mz class IMpmsmStatMz: public IMpmsmStat{ public: IMpmsmStatMz() {dimy=5; dimx = 5; dimu=2;}; //! extend eval by Mz vec eval ( const vec &x0, const vec &u0 ) { vec x(4); Mz = x0(4); //last of the state is Mz //teh first 4 states are same as before (given that Mz is set) x=IMpmsmStat::eval(x0,u0); // including model of drops! return concat(x,Mz); } void dfdx_cond ( const vec &x0, const vec &u0, mat &A, bool full=true ) { //call initial if (full) A.clear(); IMpmsmStat::dfdx_cond(x0,u0,A,full); A(2,4)=- p/J*dt; A(4,4)=1.0; } }; UIREGISTER ( IMpmsmStatMz ); //! Observation model for PMSM drive and its derivative with respect to \f$x\f$ class OMpmsm: public diffbifn { public: OMpmsm() :diffbifn () {dimy=2;dimx=4;dimu=0;}; vec eval ( const vec &x0, const vec &u0 ) { vec y ( 2 ); y ( 0 ) = x0 ( 0 ); y ( 1 ) = x0 ( 1 ); return y; } void dfdx_cond ( const vec &x0, const vec &u0, mat &A, bool full=true ) { A.clear(); A ( 0,0 ) = 1.0; A ( 1,1 ) = 1.0; } }; UIREGISTER ( OMpmsm ); //! Observation model for PMSM drive with roundoff-errors class OMpmsmRO: public diffbifn { public: OMpmsmRO() :diffbifn () {dimy=2;dimx=4;dimu=0;}; vec eval ( const vec &x0, const vec &u0 ) { vec y ( 2 ); /* y ( 0 ) = x0 ( 0 ); y ( 1 ) = x0 ( 1 );*/ double istep=0.085; y[ 0 ] = istep*itpp::round( x0[ 0 ]/ istep) ; y[ 1 ] = istep*itpp::round( x0[ 1 ]/ istep); return y; } void dfdx_cond ( const vec &x0, const vec &u0, mat &A, bool full=true ) { A.clear(); A ( 0,0 ) = 1.0; A ( 1,1 ) = 1.0; } }; UIREGISTER ( OMpmsmRO ); class OMpmsmROMz: public OMpmsmRO{ public: OMpmsmROMz() :OMpmsmRO() {dimy=2;dimx=5;dimu=0;}; }; UIREGISTER ( OMpmsmROMz ); //! Observation model for PMSM drive and its derivative with respect to \f$x\f$ for full vector of observations class OMpmsm4: public diffbifn { public: OMpmsm4() :diffbifn () {dimy=4;dimx=4;dimu=2;}; vec eval ( const vec &x0, const vec &u0 ) { vec y ( 4 ); y = x0 ; return y; } void dfdx_cond ( const vec &x0, const vec &u0, mat &A, bool full=true ) { A.clear(); A(0,0)=1.0; A(1,1)=1.0; } }; UIREGISTER ( OMpmsm4 ); //! Observation model for PMSM drive id d-q coordinates class OMpmsmDQ: public diffbifn { public: OMpmsmDQ() :diffbifn () {dimy=2;dimx=4;dimu=2;}; vec eval ( const vec &x0, const vec &u0 ) { vec y ( 2 ); double ct = cos(x0(3)); double st = sin(x0(3)); y(0) = ct*x0(0)-st*x0(1); y(1) = st*x0(0)+ct*x0(1); return y; } void dfdx_cond ( const vec &x0, const vec &u0, mat &A, bool full=true ) { double ct = cos(x0(3)); double st = sin(x0(3)); A(0,0) = ct; A(1,0) = -st; A(0,1) = st; A(1,1) = ct; A(0,2) = 0.0; A(1,2) = 0.0; A(0,3) = -st*x0(0)-ct*x0(1); A(1,3) = ct*x0(0)-st*x0(1); } }; UIREGISTER ( OMpmsmDQ ); //! Observation model for PMSM drive in reduced form coordinates class OMpmsmOT: public diffbifn { public: double Rs, Ls, dt, Ypm, kp, p, J, Mz; virtual void set_parameters ( double Rs0, double Ls0, double dt0, double Ypm0, double kp0, double p0, double J0, double Mz0 ) {Rs=Rs0; Ls=Ls0; dt=dt0; Ypm=Ypm0; kp=kp0; p=p0; J=J0; Mz=Mz0;} OMpmsmOT() :diffbifn () {dimy=2;dimx=2;dimu=4;}; vec eval ( const vec &x0, const vec &u0 ) { vec y ( 2 ); const double &omm = x0(0); const double &thm = x0(1); const double &uam = u0 ( 0 ); const double &ubm = u0 ( 1 ); const double &iam = u0 ( 2 ); const double &ibm = u0 ( 3 ); y ( 0 ) = ( 1.0- Rs/Ls*dt ) * iam + Ypm/Ls*dt*omm * sin ( thm ) + uam*dt/Ls; //ib y ( 1 ) = ( 1.0- Rs/Ls*dt ) * ibm - Ypm/Ls*dt*omm * cos ( thm ) + ubm*dt/Ls; return y; } void dfdx_cond ( const vec &x0, const vec &u0, mat &A, bool full=true ) { const double &omm = x0(0); const double &thm = x0(1); A ( 0,0 ) = Ypm/Ls*dt* sin ( thm ); A ( 0,1 ) = Ypm/Ls*dt*omm * ( cos ( thm ) ); // d ib A ( 1,0 ) = -Ypm/Ls*dt* cos ( thm ); A ( 1,1 ) = Ypm/Ls*dt*omm * ( sin ( thm ) ); } void from_setting( const Setting &root ) { const SettingResolver& params_b=root["params"]; const Setting& params=params_b.result; set_parameters ( params["Rs"], params["Ls"], 125e-6, params["Fmag"], \ params["kp"], params["p"], params["J"], 0.0); }; }; UIREGISTER ( OMpmsmOT ); //! Observation model for PMSM drive in reduced form coordinates class OMpmsmOTM: public diffbifn { public: double Rs, Ls, dt, Ypm, kp, p, J, Mz; virtual void set_parameters ( double Rs0, double Ls0, double dt0, double Ypm0, double kp0, double p0, double J0, double Mz0 ) {Rs=Rs0; Ls=Ls0; dt=dt0; Ypm=Ypm0; kp=kp0; p=p0; J=J0; Mz=Mz0;} OMpmsmOTM() :diffbifn () {dimy=2;dimx=2;dimu=4;}; vec eval ( const vec &x0, const vec &u0 ) { vec y ( 2 ); const double &omm = x0(0); const double &thm = x0(1); const double &uam = u0 ( 0 ); const double &ubm = u0 ( 1 ); const double &iam = u0 ( 2 ); const double &ibm = u0 ( 3 ); y ( 0 ) = ( 1.0- Rs/Ls*dt ) * iam + Ypm/Ls*dt*omm * sin ( thm ) + uam*dt/Ls; //ib y ( 1 ) = ( 1.0- Rs/Ls*dt ) * ibm - Ypm/Ls*dt*omm * cos ( thm ) + ubm*dt/Ls; return y; } void dfdx_cond ( const vec &x0, const vec &u0, mat &A, bool full=true ) { const double &omm = x0(0); const double &thm = x0(1); A ( 0,0 ) = Ypm/Ls*dt* sin ( thm ); A ( 0,1 ) = Ypm/Ls*dt*omm * ( cos ( thm ) ); A( 0,2) = 0.0; // d ib A ( 1,0 ) = -Ypm/Ls*dt* cos ( thm ); A ( 1,1 ) = Ypm/Ls*dt*omm * ( sin ( thm ) ); A(1,2) = 0.0; } void from_setting( const Setting &root ) { const SettingResolver& params_b=root["params"]; const Setting& params=params_b.result; set_parameters ( params["Rs"], params["Ls"], 125e-6, params["Fmag"], \ params["kp"], params["p"], params["J"], 0.0); }; }; UIREGISTER ( OMpmsmOTM ); //! Observation model for PMSM drive in reduced form coordinates -- scaled to [-1,1] class OMpmsmOTsc: public diffbifn { public: double Rs, Ls, dt, Ypm, kp, p, J, Mz; virtual void set_parameters ( double Rs0, double Ls0, double dt0, double Ypm0, double kp0, double p0, double J0, double Mz0 ) {Rs=Rs0; Ls=Ls0; dt=dt0; Ypm=Ypm0; kp=kp0; p=p0; J=J0; Mz=Mz0;} OMpmsmOTsc() :diffbifn () {dimy=2;dimx=2;dimu=4;}; vec eval ( const vec &x0, const vec &u0 ) { vec y ( 2 ); const double &omm = x0(0); const double &thm = x0(1); const double &uam = u0 ( 0 ); const double &ubm = u0 ( 1 ); const double &iam = u0 ( 2 ); const double &ibm = u0 ( 3 ); y ( 0 ) = ( 1.0- Rs/Ls*dt ) * iam + Ypm/Ls*dt*omm *Wref/Iref* sin ( thm*Thetaref/(1<<15) ) + (1<<15)*uam*dt/Ls /Iref; //ib y ( 1 ) = ( 1.0- Rs/Ls*dt ) * ibm - Ypm/Ls*dt*omm *Wref/Iref* cos ( thm*Thetaref/(1<<15) ) + (1<<15)*ubm*dt/Ls /Iref; return y; } void dfdx_cond ( const vec &x0, const vec &u0, mat &A, bool full=true ) { const double &omm = x0(0); const double &thm = x0(1); A ( 0,0 ) = Ypm/Ls*dt* Wref/Iref*sin ( thm*Thetaref/(1<<15) ); A ( 0,1 ) = Ypm/Ls*dt*omm *Wref/Iref*Thetaref/(1<<15)* ( cos ( thm*Thetaref/(1<<15) ) ); // d ib A ( 1,0 ) = -Ypm/Ls*dt* Wref/Iref*cos ( thm*Thetaref/(1<<15) ); A ( 1,1 ) = Ypm/Ls*dt*omm *Wref/Iref*Thetaref/(1<<15)* ( sin ( thm*Thetaref/(1<<15) ) ); } void from_setting( const Setting &root ) { const SettingResolver& params_b=root["params"]; const Setting& params=params_b.result; set_parameters ( params["Rs"], params["Ls"], 125e-6, params["Fmag"], \ params["kp"], params["p"], params["J"], 0.0); }; }; UIREGISTER ( OMpmsmOTsc ); /*!@}*/ #endif //PMSM_H