1843 | | /*************************************/ |
1844 | | /* LQ_EKF_Inj */ |
1845 | | /*************************************/ |
1846 | | |
1847 | | /********************************************************************************/ |
1848 | | /* !!! potrebuje nutne rizeni z cidla, protoze si EKF dela sam */ |
1849 | | /********************************************************************************/ |
1850 | | |
1851 | | class PMSM_LQCtrl_EKF_Inj: public PMSMCtrl{ |
1852 | | public: |
1853 | | /* |
1854 | | PMSMCtrl: |
1855 | | double isa; |
1856 | | double isb; |
1857 | | double ome; |
1858 | | double the; |
1859 | | double Ww; |
1860 | | */ |
1861 | | |
1862 | | //PMSM parameters |
1863 | | const double a; |
1864 | | const double b; |
1865 | | const double c; |
1866 | | const double d; |
1867 | | const double e; |
1868 | | |
1869 | | const double Rs; |
1870 | | const double Lq; |
1871 | | const double Ld; |
1872 | | |
1873 | | //input penalty |
1874 | | double r; |
1875 | | double rpd; //penalize differences u - u_old |
1876 | | |
1877 | | //time step |
1878 | | const double Dt; |
1879 | | |
1880 | | //receding horizon |
1881 | | int rec_hor; |
1882 | | |
1883 | | //system matrices |
1884 | | mat A; //5x5 |
1885 | | mat B; //5x2 |
1886 | | //mat C; //2x5 |
1887 | | mat Q; //5x5 |
1888 | | mat R; //2x2 |
1889 | | mat Rpd; //2x4 |
1890 | | |
1891 | | //control matrix |
1892 | | mat L; |
1893 | | vec uab,udq; |
1894 | | vec icondpd; |
1895 | | vec u_old; |
1896 | | |
1897 | | //control maximum |
1898 | | double MAXu; |
1899 | | int MAXuflag; |
1900 | | |
1901 | | //lqg controler class |
1902 | | LQG_universal lq; |
1903 | | |
1904 | | //EKF input |
1905 | | vec y; |
1906 | | double isaold, isbold, omeold; |
1907 | | mat Akf; |
1908 | | mat Ckf; |
1909 | | mat Qkf; |
1910 | | mat Rkf; |
1911 | | vec uoldab; |
1912 | | mat Pkf; |
1913 | | const double R0,R10; |
1914 | | |
1915 | | //Inj |
1916 | | double iqold, iqnew; |
1917 | | double theold; |
1918 | | double obs, obsf, obsfold; |
1919 | | unsigned int timesync; |
1920 | | double koef; |
1921 | | double RC, alp; |
1922 | | |
1923 | | const double Vamp; //V |
1924 | | const double freq; //Hz |
1925 | | |
1926 | | // |
1927 | | // vec p_isd, p_isq, p_ome, p_the; |
1928 | | double p_isd, p_isq; |
1929 | | |
1930 | | PMSM_LQCtrl_EKF_Inj():PMSMCtrl(), a(0.9898), b(0.0072), c(0.0361), d(1.0), e(0.0149), Rs(0.28), Lq(0.003465), Ld(1.5*0.003465), |
1931 | | r(0.005), rpd(0.1), Dt(0.000125), rec_hor(10), //for r is a default value rewrited by pcp.txt file value |
1932 | | A(5, 5), B(5, 2), Q(5, 5), R(2, 2), Rpd(2, 4), |
1933 | | uab(2), udq(2), u_old(2), icondpd(8), MAXu(100.0), MAXuflag(0), Vamp(10), |
1934 | | Akf(4,4), Ckf(/*3*/2,4), Rkf(/*3,3*/2,2), Qkf(4,4), uoldab(2), Pkf(4,4), freq(500), |
1935 | | R0(0.003), R10(3), y(3) { |
1936 | | |
1937 | | timesync = 0; |
1938 | | iqnew = 0.0; |
1939 | | theold = 0.0; |
1940 | | isaold = 0.0; |
1941 | | isbold = 0.0; |
1942 | | omeold = 0.0; |
1943 | | |
1944 | | //set fix matrices elements & dimensions |
1945 | | A.zeros(); |
1946 | | A(0, 0) = A(1, 1) = a; |
1947 | | A(2, 1) = e; |
1948 | | A(2, 2) = d; |
1949 | | A(2, 4) = d - 1; |
1950 | | A(3, 2) = A(3, 4) = Dt; |
1951 | | A(3, 3) = A(4, 4) = 1.0; |
1952 | | B.zeros(); |
1953 | | B(0, 0) = B(1, 1) = c; |
1954 | | Q.zeros(); |
1955 | | Q(2, 2) = 1.0; |
1956 | | R.zeros(); |
1957 | | Rpd.zeros(); |
1958 | | u_old.zeros(); |
1959 | | uoldab.zeros(); |
1960 | | |
1961 | | koef = Vamp*(Ld-Lq)/(2*pi*freq*2*Ld*Lq); |
1962 | | RC = 1/(2*pi*5); //48LP |
1963 | | alp = Dt/(RC + Dt); |
1964 | | |
1965 | | Akf.zeros(); |
1966 | | Akf(0,0) = a; |
1967 | | Akf(1,1) = a; |
1968 | | Akf(2,2) = d; |
1969 | | Akf(3,3) = 1.0; |
1970 | | Akf(3,2) = Dt; |
1971 | | Ckf.zeros(); |
1972 | | Ckf(0,0) = 1.0; |
1973 | | Ckf(1,1) = 1.0; |
1974 | | //Ckf(2,2) = 0.0; |
1975 | | Qkf.zeros(); |
1976 | | Qkf(0,0) = 0.1;//0.0013; |
1977 | | Qkf(1,1) = 0.1;//0.0013; |
1978 | | Qkf(2,2) = 0.1;//5e-6; |
1979 | | Qkf(3,3) = 0.01;//1e-10; |
1980 | | Rkf.zeros(); |
1981 | | Rkf(0,0) = 0.05;//0.0006; |
1982 | | Rkf(1,1) = 0.05;//0.0006; |
1983 | | //Rkf(2,2) = 0.05;//0006; |
1984 | | //Pkf.zeros(); |
1985 | | Pkf = Qkf; |
1986 | | } |
1987 | | |
1988 | | double hfsignal(int time){ |
1989 | | return Vamp*cos(freq*2*pi*time*Dt); |
1990 | | } |
1991 | | |
1992 | | |
1993 | | virtual vec ctrlaction(const itpp::vec& cond) { |
1994 | | PMSMCtrl::ctrlaction(cond); // fills isa,isb,ome,the,Ww |
1995 | | |
1996 | | //increase synchronisation timer |
1997 | | timesync++; |
1998 | | |
1999 | | //get data from PMSM |
2000 | | //y(0) = isa;// + noise |
2001 | | //y(1) = isb;// + noise |
2002 | | //ome = 0; |
2003 | | //the = 0; |
2004 | | |
2005 | | //evaluate injection |
2006 | | /*iqold = iqnew; |
2007 | | iqnew = y(1)*cos(theold) - y(0)*sin(theold); |
2008 | | |
2009 | | obs = -(iqnew-(1 - Dt*Rs/Lq)*iqold)*hfsignal(timesync)/koef;//multiplication by HF signal |
2010 | | obsf = alp*obs + (1-alp)*obsfold; //lowpass filter |
2011 | | obsfold = obsf; |
2012 | | |
2013 | | double y2 = 2*(obsf);*/ |
2014 | | double isah, isbh, omeh, theh; |
2015 | | //EKF => isa=isaold,isb=isbold,ome=omeold,the=theold |
2016 | | isah = a*isaold + b*omeold*sin(theold) + c*uoldab(0); |
2017 | | isbh = a*isbold - b*omeold*cos(theold) + c*uoldab(1); |
2018 | | omeh = d*omeold + e*(isbold*cos(theold) - isaold*sin(theold)); |
2019 | | theh = theold + Dt*omeold; |
2020 | | |
2021 | | Akf(0, 2) = b*sin(theold); |
2022 | | Akf(0, 3) = b*omeold*cos(theold); |
2023 | | Akf(1, 2) = -b*cos(theold); |
2024 | | Akf(1, 3) = b*omeold*sin(theold); |
2025 | | Akf(2, 0) = -e*sin(theold); |
2026 | | Akf(2, 1) = e*cos(theold); |
2027 | | Akf(2, 3) = -e*(isaold*cos(theold)+isbold*sin(theold)); |
2028 | | |
2029 | | vec yiab(/*3*/2); |
2030 | | yiab(0) = /*y(0)*/isa - isah; |
2031 | | yiab(1) = /*y(1)*/isb - isbh; //ybe = sqrt(3.0)/3.0 * (2.0*ybe + yal); |
2032 | | //yiab(2) = y2 - theh; |
2033 | | |
2034 | | // Rkf(2,2) = R0 + (R10 - R0)*omeold/10; |
2035 | | Pkf = Akf*Pkf*Akf.T() + Qkf; |
2036 | | mat EKK = Pkf*Ckf.T()*inv(Ckf*Pkf*Ckf.T() + Rkf); |
2037 | | Pkf = Pkf - EKK*Ckf*Pkf; |
2038 | | //mat EKK = Pkf*Ckf.transpose()*inv(Ckf*Pkf*Ckf.transpose()+Rkf); |
2039 | | //Pkf = Akf*(Pkf - Pkf*Ckf.transpose()*inv(Ckf*Pkf*Ckf.transpose()+Rkf)*Ckf*Pkf)*Akf.transpose() + Qkf; |
2040 | | |
2041 | | // EKK = -P*C'*inv(C*P*C' + R)*yiab'; |
2042 | | // P = A*(P - P*C'*inv(C*P*C' + R)*C*P)*A' + Q; |
2043 | | |
2044 | | mat EKKy = EKK*yiab; |
2045 | | isah = isah + EKKy(0,0); |
2046 | | isbh = isbh + EKKy(1,0); |
2047 | | omeh = omeh + EKKy(2,0); |
2048 | | theh = theh + EKKy(3,0); |
2049 | | |
2050 | | //cout << omeh << endl; |
2051 | | |
2052 | | /*cout << "K" << isah << " " << isbh << " " << omeh << " " << theh << endl; |
2053 | | |
2054 | | isah = isa; |
2055 | | isbh = isb; |
2056 | | omeh = ome; |
2057 | | theh = the; |
2058 | | |
2059 | | cout << "M" << isah << " " << isbh << " " << omeh << " " << theh << endl;*/ |
2060 | | |
2061 | | isaold = isah; |
2062 | | isbold = isbh; |
2063 | | omeold = omeh; |
2064 | | theold = theh; |
2065 | | |
2066 | | int i; |
2067 | | vec tmp; |
2068 | | |
2069 | | lq.resetTime(); |
2070 | | |
2071 | | p_isd = isah*cos(theh) + isbh*sin(theh);//isa; |
2072 | | p_isq = isbh*cos(theh) - isah*sin(theh);//isb; |
2073 | | |
2074 | | A(0, 1) = Dt*omeh; |
2075 | | //A(0, 2) = Dt*p_isq; |
2076 | | //A(0, 4) = Dt*p_isq; |
2077 | | A(1, 0) = -Dt*omeh; |
2078 | | A(1, 2) = /*-Dt*p_isd*/-b; |
2079 | | A(1, 4) = /*-Dt*p_isd*/-b; |
2080 | | |
2081 | | lq.Models(0).A = A; |
2082 | | |
2083 | | //create control matrix |
2084 | | for(i = rec_hor; i > 0; i--){ |
2085 | | lq.redesign(); |
2086 | | } |
2087 | | lq.redesign(); |
2088 | | |
2089 | | L = lq.getL(); |
2090 | | |
2091 | | icondpd(0) = isah*cos(theh) + isbh*sin(theh); |
2092 | | icondpd(1) = isbh*cos(theh) - isah*sin(theh); |
2093 | | icondpd(2) = omeh - /*2.65*/Ww; |
2094 | | icondpd(3) = theh; |
2095 | | icondpd(4) = /*2.65*/Ww; |
2096 | | icondpd(5) = u_old(0); |
2097 | | icondpd(6) = u_old(1); |
2098 | | icondpd(7) = 0; |
2099 | | |
2100 | | tmp = L*icondpd; |
2101 | | |
2102 | | udq = tmp(0,1); |
2103 | | |
2104 | | //uab = udq; //set size |
2105 | | uab(0) = udq(0)*cos(theh) - udq(1)*sin(theh);// + hfsignal(timesync-1)*cos(theh); |
2106 | | uab(1) = udq(1)*cos(theh) + udq(0)*sin(theh);// + hfsignal(timesync-1)*sin(theh); |
2107 | | |
2108 | | |
2109 | | if(MAXuflag == 1){ //square cut off |
2110 | | if(uab(0) > MAXu) uab(0) = MAXu; |
2111 | | else if(uab(0) < -MAXu) uab(0) = -MAXu; |
2112 | | if(uab(1) > MAXu) uab(1) = MAXu; |
2113 | | else if(uab(1) < -MAXu) uab(1) = -MAXu; |
2114 | | } |
2115 | | else if(MAXuflag == 2){ //circular cut off |
2116 | | double uampl = sqrt(uab(0)*uab(0)+uab(1)*uab(1)); |
2117 | | double uangl = atan2(uab(1), uab(0)); |
2118 | | if (uampl > MAXu) uampl = MAXu; |
2119 | | uab(0) = uampl*cos(uangl); |
2120 | | uab(1) = uampl*sin(uangl); |
2121 | | } |
2122 | | |
2123 | | u_old = udq; |
2124 | | uoldab = uab; |
2125 | | |
2126 | | return uab; |
2127 | | } |
2128 | | |
2129 | | void from_setting(const Setting &set){ |
2130 | | PMSMCtrl::from_setting(set); |
2131 | | UI::get(r,set, "r", UI::optional); |
2132 | | UI::get(rec_hor,set, "h", UI::optional); |
2133 | | UI::get(MAXu,set, "MAXu", UI::optional); |
2134 | | UI::get(MAXuflag,set, "MAXuflag", UI::optional); |
2135 | | UI::get(rpd,set, "rpd", UI::optional); |
2136 | | } |
2137 | | |
2138 | | void validate(){ |
2139 | | R(0, 0) = R(1, 1) = r; |
2140 | | Rpd(0, 0) = Rpd(1, 1) = rpd; |
2141 | | Rpd(0, 2) = Rpd(1, 3) = -rpd; |
2142 | | |
2143 | | Array<quadraticfn> qloss(3); |
2144 | | qloss(0).Q.setCh(Q); |
2145 | | qloss(0).rv = RV("x", 5, 1); |
2146 | | qloss(1).Q.setCh(R); |
2147 | | qloss(1).rv = RV("u", 2, 0); |
2148 | | qloss(2).Q.setCh(Rpd); |
2149 | | qloss(2).rv = RV("u", 2, 0); |
2150 | | qloss(2).rv.add(RV("u", 2, -1)); |
2151 | | lq.Losses = qloss; |
2152 | | |
2153 | | //set lq |
2154 | | lq.rv = RV("u", 2, 0); |
2155 | | RV tmp = RV("x", 5, 0); |
2156 | | tmp.add(RV("u", 2, -1)); |
2157 | | lq.set_rvc(tmp); |
2158 | | |
2159 | | lq.horizon = rec_hor; |
2160 | | |
2161 | | Array<linfnEx> model(2); |
2162 | | model(0).A = A; |
2163 | | model(0).B = vec("0 0 0 0 0"); |
2164 | | model(0).rv = RV("x", 5, 0); |
2165 | | model(0).rv_ret = RV("x", 5, 1); |
2166 | | model(1).A = B; |
2167 | | model(1).B = vec("0 0"); |
2168 | | model(1).rv = RV("u", 2, 0); |
2169 | | model(1).rv_ret = RV("x", 5, 1); |
2170 | | lq.Models = model; |
2171 | | |
2172 | | lq.finalLoss.Q.setCh(Q); |
2173 | | lq.finalLoss.rv = RV("x", 5, 1); |
2174 | | |
2175 | | lq.validate(); |
2176 | | |
2177 | | uab.zeros(); |
2178 | | udq.zeros(); |
2179 | | } |
2180 | | }; |
2181 | | UIREGISTER(PMSM_LQCtrl_EKF_Inj); |