root/applications/pmsm/simulator_zdenek/ekf_example/matrix_vs.cpp @ 1233

Revision 1233, 14.3 kB (checked in by smidl, 14 years ago)

fix shifts in thorton fast

Line 
1/************************************
2        Extended Kalman Filter
3        Matrix operations
4
5        V. Smidl
6
7Rev. 30.8.2010
8
930.8.2010      Prvni verze
10
11*************************************/
12#include "fixed.h"
13#include "stdio.h"
14#include <math.h>
15
16#include "matrix_vs.h"
17
18/* Matrix multiply Full matrix by upper diagonal matrix; */
19void mmultAU(int *m1, int *up, int *result, unsigned int rows, unsigned int columns) {
20    unsigned int i, j, k;
21    long tmp_sum=0L; //in 15+qAU
22    int *m2pom;
23    int *m1pom=m1;
24    int *respom=result;
25
26    for (i=0; i<rows; i++) //rows of result
27    {
28        for (j=0; j<columns; j++) //columns of result
29        {
30            m2pom=up+j;//??
31
32            for (k=0; k<j; k++) //inner loop up to "j" - U(j,j)==1;
33            {
34                tmp_sum+=((long)(*(m1pom++))**m2pom)>>(15-qAU);
35                m2pom+=columns;
36            }
37            // add the missing A(i,j)
38            tmp_sum +=(long)(*m1pom)<<qAU; // no need to shift
39            m1pom-=(j); // shift back to first element
40
41            // saturation effect
42            tmp_sum=tmp_sum>>15;
43            if (tmp_sum>32767) {
44                                printf("Au - saturated\n");
45            }
46            if (tmp_sum<-32768) {
47                                printf("Au - saturated\n");
48            }
49//                      printf("Au - saturated\n");
50
51            *respom++=tmp_sum;
52
53            tmp_sum=0;
54        }
55        m1pom+=(columns);
56    }
57};
58
59/* Matrix multiply Full matrix by upper diagonal matrix; */
60void mmultACh(int *m1, int *up, int *result, unsigned int rows, unsigned int columns) {
61    unsigned int i, j, k;
62    long tmp_sum=0L;
63    int *m2pom;
64    int *m1pom=m1;
65    int *respom=result;
66
67    for (i=0; i<rows; i++) //rows of result
68    {
69        for (j=0; j<columns; j++) //columns of result
70        {
71            m2pom=up+j;//??
72
73            for (k=0; k<=j; k++) //inner loop up to "j" - U(j,j)==1;
74            {
75                tmp_sum+=(long)(*(m1pom++))**m2pom;
76                m2pom+=columns;
77            }
78            m1pom-=(j+1); // shift back to first element
79
80            // saturation effect
81            tmp_sum=tmp_sum>>15;
82            if (tmp_sum>32767) {
83                if (i!=3) tmp_sum=32767;
84            }
85            if (tmp_sum<-32768) {
86                tmp_sum=-32768;
87            }
88            //                  printf("Au - saturated\n");
89
90            *respom++=tmp_sum;
91
92            tmp_sum=0;
93        }
94        m1pom+=(columns);
95    }
96};
97
98bool DBG=true;
99
100void show(const char name[10], int *I, int n) {
101    if (!DBG) return;
102
103    printf("%s: ",name);
104    for (int i=0;i<n;i++) {
105        printf("%d ",*(I+i));
106    }
107    printf("\n");
108}
109
110// Thorton procedure - Kalman predictive variance in UD
111void thorton(int *U, int *D, int *PSIU, int *Q, int *G, int *Dold, unsigned int rows) {
112    unsigned int i,j,k;
113    // copy D to Dold
114    int *Dold_pom=Dold;
115    for (i=0;i<rows;i++) {
116        *Dold_pom++=*D++;
117    }
118    D-=rows; // back to first D
119
120    // initialize G = eye()
121    int *G_pom = G;
122    *G_pom++=1<<14;
123    for (i=0;i<rows-1;i++) {
124        // clean elem before diag
125        for (j=0; j<rows; j++) {
126            *G_pom++=0.0;
127        }
128        *G_pom++=1<<14;
129    }
130    // eye created
131
132    long sigma; // in q30!!!!!!
133    for (i=rows-1; true;i--) { // check i==0 at the END!
134        sigma = 0;
135
136        for (j=0;j<rows; j++) {
137            //long s1=(((long)PSIU[i+j*rows]*PSIU[i+j*rows])>>15)*(Dold[i]);
138            long s2=((((long)PSIU[i*rows+j]*Dold[j]))>>(2*qAU-15))*PSIU[i*rows+j];
139//                      printf("%d - %d\n",s1,s2);
140            sigma += s2;
141        }
142        sigma += Q[i*rows+i]<<15; // Q is in q15
143        for (j=i+1;j<rows; j++) {
144            sigma += (((long)G[i*rows+j]*G[i*rows+j])>>13)*Q[j*rows+j];
145//                      sigma += (((long)G[i+j*rows]*G[i+j*rows])>>13)*Q[j+j*rows];
146        }
147
148        if (sigma>16384<<15) sigma = 16384<<15;
149        *(D+i)=sigma>>15;
150        if (D[i]==0) D[i]=1;
151//show("D",D,5);
152
153        for (j=0;j<i;j++) {
154//                      printf("\n%d,%d\n",i,j);
155            sigma =0;
156            for (k=0;k<rows;k++) {
157                                int tmp= (((long(PSIU[i*rows+k])*Dold[k]))>>(2*qAU-15));
158                                if (tmp>32767) printf("!");
159                                sigma += (((long(PSIU[i*rows+k])*Dold[k]))>>(2*qAU-15))*PSIU[j*rows+k];
160            }
161            for (k=0;k<rows;k++) {
162                sigma += ((((long)G[i*rows+k])*G[j*rows+k])>>13)*Q[k*rows+k];
163            }
164            long z=sigma/D[i]; // shift by 15
165            if (z>32767) z=32767;
166            if (z<-32768) z=-32768;
167
168            U[j*rows+i] = (int)z;
169
170
171            for (k=0;k<rows;k++) {
172                PSIU[j*rows+k] -= ((long)U[j*rows+i]*PSIU[i*rows+k])>>15; //qAU*q15/q15=qAU
173            }
174
175            for (k=0;k<rows;k++) {
176                G[j*rows+k] -=  ((long)U[j*rows+i]*G[i*rows+k])>>15;
177            }
178
179        }
180        //show("U",U,25);
181        //show("G",G,25);
182        if (i==0) return;
183    }
184}
185
186void bierman_fast(int *difz, int *xp, int *U, int *D, int *R, unsigned int dimy, unsigned int dimx ) {
187    int alpha;
188    int beta,lambda;
189    int b[5]; // ok even for 4-dim state
190    int *a; // in [0,1] -> q15
191    unsigned int iy,j,i;
192
193    int *b_j,*b_i;
194    int *a_j;
195    int *D_j;
196    int *U_ij;
197    int *x_i;
198    a = U; // iyth row of U
199    for (iy=0; iy<dimy; iy++, a+=dimx) {
200        // a is a row
201        for (j=0,a_j=a,b_j=b,D_j=D; j<dimx; j++,b_j++,D_j++,a_j++)
202            *b_j=((long)(*D_j)*(*a_j))>>15;
203
204        alpha = (long)R[iy]; //\alpha = R+vDv = R+a*b
205        // R in q15, a in q15, b=q15
206//              gamma = (1<<15)/alpha; //(in q15)
207        //min alpha = R[iy] = 164
208        //max gamma = 0.0061 => gamma_ref = q7
209        for (j=0,a_j=a,b_j=b,D_j=D; j<dimx; j++,a_j++,b_j++,D_j++) {
210            beta   = alpha;
211            lambda = -((long)(*a_j)<<15)/beta;
212            alpha  += ((long)(*a_j)*(*b_j))>>15;
213            D[j] = ((((long)beta<<15)/alpha)*(*D_j))>>15; //gamma is long
214            if (*D_j==0) *D_j=1;
215
216            for (i=0,b_i=b,U_ij=U+j; i<j; i++, b_i++,U_ij+=dimx) {
217                beta   = *U_ij;
218                *U_ij +=  ((long)lambda*(*b_i))>>15;
219                *b_i  +=  ((long)beta*(*b_j))>>15;
220            }
221        }
222        int dzs = (((long)difz[iy])<<15)/alpha;  // apply scaling to innovations
223        // no shift due to gamma
224        for (i=0,x_i=xp,b_i=b; i<dimx; i++,x_i++,b_i++) {
225            *x_i  += ((long)dzs*(*b_i))>>15; // multiply by unscaled Kalman gain
226        }
227
228        //cout << "Ub: " << U << endl;
229        //cout << "Db: " << D << endl <<endl;
230
231    }
232
233}
234
235// Thorton procedure - Kalman predictive variance in UD
236void thorton_fast(int *U, int *D, int *PSIU, int *Q, int *G, int *Dold, unsigned int rows) {
237    unsigned int i,j,k;
238    // copy D to Dold
239    int *Dold_i,*Dold_k;
240    int *D_i;
241    int *PSIU_ij,*PSIU_ik,*PSIU_jk;
242    int *Q_jj,*Q_ii,*Q_kk;
243    int *U_ji;
244    int *G_ik,*G_jk;
245    int irows,jrows;
246    long sigma; // in q30!!
247
248    for (i=0,Dold_i=Dold,D_i=D;i<rows;i++,Dold_i++,D_i++) {
249        *Dold_i=*D_i;
250    }
251
252    // initialize G = eye()
253    G_ik= G;
254    *G_ik++=1<<14;
255    for (i=0;i<rows-1;i++) {
256        // clean elem before diag
257        for (k=0; k<rows; k++) {
258            *G_ik++=0;
259        }
260        *G_ik++=1<<14;
261    }
262    // eye created
263
264    for (i=rows-1, Dold_i=Dold+i, D_i=D+i;
265            true; i--, Dold_i--,D_i--) { // stop if i==0 at the END!
266        irows=i*rows;
267        sigma = 0;
268        for (k=0, PSIU_ik=PSIU+irows,Dold_k=Dold;
269                k<rows; k++, PSIU_ik++,Dold_k++) {
270                sigma += (((long)(*PSIU_ik)**Dold_k)>>(qAU))*(*PSIU_ik)<<(15-qAU);
271        }
272        sigma += *(Q+i+irows)<<15;
273        for (j=i+1, G_ik=G+irows+i+1; j<rows; j++,G_ik++) {
274            sigma += (((long)(*G_ik)**G_ik)>>13)**(Q+j+j*rows);
275
276        }
277       
278        *D_i=sigma>>15;
279        if (*D_i==0) *D_i=1;
280                if (*D_i>16384) *D_i = 16384;
281               
282
283        for (j=0;j<i;j++) {
284            jrows = j*rows;
285
286            sigma =0;
287            for (k=0, PSIU_ik=PSIU+irows, PSIU_jk=PSIU+jrows, Dold_k=Dold;
288                    k<rows; k++, PSIU_ik++, PSIU_jk++, Dold_k++) {
289
290                                sigma += (((long(*PSIU_ik)**Dold_k)>>qAU)**PSIU_jk)<<(15-qAU);
291            }
292
293            for (k=i+1,G_ik=G+irows+i,G_jk=G+jrows+i,Q_kk=Q+k*rows+k;
294                    k<rows;k++,G_ik++,G_jk++,Q_kk+=rows+1) {
295                sigma += ((((long)*G_ik)**G_jk)>>13)**Q_kk;
296            }
297
298            long z=sigma/(*D_i); // shift by 15
299            if (z>32767) z=32767;
300            if (z<-32768) z=-32768;
301
302            U_ji=U+jrows+i;
303            *U_ji = (int)z;
304
305
306            for (k=0,PSIU_ik=PSIU+irows,PSIU_jk=PSIU+jrows;
307                    k<rows;k++,PSIU_ik++,PSIU_jk++) {
308                *PSIU_jk -= ((long)*U_ji**PSIU_ik)>>15;
309            }
310
311            for (k=0,G_jk=G+jrows,G_ik=G+irows;
312                    k<rows;k++, G_jk++, G_ik++) {
313                *G_jk -=  ((long)*U_ji**G_ik)>>15;
314            }
315
316        }
317        if (i==0) return;
318    }
319}
320
321void bierman(int *difz, int *xp, int *U, int *D, int *R, unsigned int dimy, unsigned int dimx ) {
322    long alpha;
323    long gamma,beta,lambda;
324    int b[5]; // ok even for 4-dim state
325    int *a; // in [0,1] -> q15
326    unsigned int iy,j,i;
327
328    for (iy=0; iy<dimy; iy++) {
329        // a is a row
330        a = U+iy*dimx; // iyth row of U
331        for (j=0;j<dimx;j++) {
332            (j<iy)? b[j]=0: (j==iy)? b[j]=D[j] : b[j]=((long)D[j]*a[j])>>15;
333        }
334
335        alpha = (long)R[iy]; //\alpha = R+vDv = R+a*b
336        // R in q15, a in q15, b=q15
337//              gamma = (1<<15)/alpha; //(in q15)
338        //min alpha = R[iy] = 164
339        //max gamma = 0.0061 => gamma_ref = q7
340        for (j=0;j<dimx;j++) {
341            beta   = alpha;
342            lambda = -(long(a[j])<<15)/beta;
343            alpha  += ((long(a[j])*b[j])>>15);
344            D[j] = (((long(beta)<<15)/alpha)*D[j])>>15; //gamma is long
345            if (D[j]==0) D[j]=1;
346
347            //                  cout << "a: " << alpha << "g: " << gamma << endl;
348            for (i=0;i<j;i++) {
349                beta   = U[i*dimx+j];
350                U[i*dimx+j] +=  (lambda*b[i])>>15;
351                b[i]   +=  (beta*b[j])>>15;
352            }
353        }
354        int dzs = (long(difz[iy])<<15)/alpha;  // apply scaling to innovations
355        // no shift due to gamma
356        for (i=0; i<dimx; i++) {
357            xp[i]  += (long(dzs*b[i]))>>15; // multiply by unscaled Kalman gain
358        }
359
360        //cout << "Ub: " << U << endl;
361        //cout << "Db: " << D << endl <<endl;
362
363    }
364
365}
366
367/* square root of 0<a<1 using taylor at 0.5 in q15*/
368int int_sqrt(int x) {
369        double xd(double(x)/32768.);
370        return round(sqrt(xd)*32768);
371       
372    //sqrt(x) == 1/2*2^(1/2)+1/2*2^(1/2)*(x-1/2)-1/4*2^(1/2)*(x-1/2)^2
373    //         = k1 + k1*(x-0.5) - k2*(x-0.5)(x-0.5);
374#define k1 23170 //0.5*sqrt(2)*32768
375#define k2 11585 //0.25*sqrt(2)*32768
376
377    int tmp;
378    if (x>6554) {
379        int xm05=x-16384;
380        tmp = ((long)k1*xm05)>>15;
381        tmp-=(((long(k2)*xm05)>>15)*xm05)>>15;
382        tmp +=k1;
383    } else {
384        tmp = 4*x;
385        tmp-=long(8*x)*x>>15;
386    }
387    return tmp;
388}
389
390void householder(int *Ch /*= int *PSICh*/, int *Q, unsigned int dimx) {
391    int k,j,i;
392    int sigma,alpha,beta;
393    int B[25];//beware
394    int w[5];
395    int v[5];
396
397    // copy Q to B
398    for (i=0;i<dimx*dimx;i++) {
399        B[i]=Q[i];
400    }
401
402    for (k=dimx-1; k>=0; k--) {
403        sigma=0;
404        for (j=0;j<dimx;j++) {
405            sigma+=(long(B[k*dimx+j])*B[k*dimx+j])>>15;
406        }
407        for (j=0;j<=k;j++) {
408            sigma+=(long(Ch[k*dimx+j])*Ch[k*dimx+j])>>15;
409        }
410        /*               double sigf=double(sigma)/(1<<15);
411                         double alpf = sqrt(sigf);*/
412                if (sigma>16384) sigma=16384;
413        alpha=int_sqrt(sigma);
414        // alpha = alpf*(1<<15);
415        //
416        sigma=0;
417        for (j=0;j<dimx;j++) {
418            w[j]=B[k*dimx+j];
419            sigma+=(long(w[j])*w[j])>>15;
420        }
421        for (j=0; j<=k;j++) {
422            if (j==k) {
423                v[j]=Ch[k*dimx+j]-alpha;
424            } else {
425                v[j]=Ch[k*dimx+j];
426            }
427            sigma+=(long(v[j])*v[j])>>15;
428        }
429        alpha=sigma>>1;
430                if (alpha==0) alpha =1;
431        for (i=0;i<=k;i++) {
432            sigma=0;
433            for (j=0;j<dimx;j++) {
434                sigma+=(long(B[i*dimx+j])*w[j])>>15;
435            }
436            for (j=0;j<=k;j++) {
437                sigma+=(long(Ch[i*dimx+j])*v[j])>>15;
438            }
439            for (j=0;j<dimx;j++) {
440                B[i*dimx+j]-=(long(sigma)*w[j]/alpha);
441            };
442            for (j=0;j<=k;j++) {
443                Ch[i*dimx+j]-=(long(sigma)*v[j]/alpha);
444            }
445        }
446    }
447
448}
449
450void carlson(int *difz, int *xp, int *Ch, int *R, unsigned int dimy, unsigned int dimx ) {
451    int alpha,beta,gamma;
452    int delta, eta,epsilon,zeta,sigma,tau;
453    int i,j,iy;
454    int w[5];
455
456    for (iy=0; iy<dimy; iy++) {
457        alpha=R[iy];
458        delta = difz[iy];
459
460        for (j=0;j<dimx;j++) {
461            sigma=Ch[iy*dimx+j];
462            beta=alpha;
463            alpha+=(long(sigma)*sigma)>>15;
464//                      double ab=(double)alpha*beta/32768./32768.;
465//                      double s_ab=sqrt(ab);
466            gamma=int_sqrt(((long)alpha*beta)>>15);
467            //gamma = round(s_ab*(1<<15));
468            eta=(long (beta)<<15) / gamma;
469            //zeta=(long(sigma)<<15)/ gamma;
470            w[j]=0;
471            for (i=0;i<=j;i++) {
472                tau=Ch[i*dimx+j];
473                Ch[i*dimx+j]=((long(eta)*Ch[i*dimx+j])>>15) -(long(sigma)*w[i])/gamma;
474                w[i]+=(long(tau)*sigma)>>15;
475            }
476        }
477
478        //epsilon=(long(difz)<<15) / (alpha); // q15*q13/q13 = q15
479        for (i=0;i<dimx;i++) {
480            xp[i]+=(long(w[i])*delta)/alpha;
481        }
482    }
483}
484
485/* perform Householder update of Ch matrix using PSI*Ch , Q, */
486extern void givens(int *Ch /*= int *PSICh*/, int *Q, unsigned int dimx){
487        int i,j,k;
488        int rho,s,c,tau;
489       
490        int A[25];//beware
491        // copy Q to A
492        for (i=0;i<dimx*dimx;i++) {
493                A[i]=Q[i];
494        }
495       
496       
497        for (i=dimx-1; i>=0; i--){
498                for (j=0; j<dimx; j++) {
499                        rho=int_sqrt(((long)Ch[i*dimx+i]*Ch[i*dimx+i]+long(A[i*dimx+j])*A[i*dimx+j])>>15);
500                        if (rho==0) break;
501                        s=(long(A[i*dimx+j])<<15)/rho;
502                        c=(long(Ch[i*dimx+i])<<15)/rho;
503                        for (k=0;k<=i; k++){
504                                tau=(long(c)*A[k*dimx+j]-long(s)*Ch[k*dimx+i])>>15;
505                                Ch[k*dimx +i]=(long(s)*A[k*dimx+j]+long(c)*Ch[k*dimx+i])>>15;
506                                A[k*dimx +j]=tau;
507                        }
508                }
509        }
510        for (j=0; j<i; j++){
511                rho=int_sqrt((long(Ch[i*dimx+i])*Ch[i*dimx+i]+long(Ch[i*dimx+j])*Ch[i*dimx+j])>>15);
512                if (rho==0) break; 
513                s=(long(Ch[i*dimx+j])<<15)/rho;
514                c=(long(Ch[i*dimx+i])<<15)/rho;
515                for (k=0; k<=i; k++){
516                        tau=(long(c)*Ch[k*dimx+j]-long(s)*Ch[k*dimx+i])>>15;
517                        Ch[k*dimx+i]=(long(s)*Ch[k*dimx+j]+long(c)*Ch[k*dimx+i])>>15;
518                        Ch[k*dimx+j]=tau;
519                }
520        }
521}
Note: See TracBrowser for help on using the browser.