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

Revision 1239, 14.5 kB (checked in by peroutka, 14 years ago)
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>>15;
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    int dzs;
199
200    a = U; // iyth row of U
201    for (iy=0; iy<dimy; iy++, a+=dimx) {
202        // a is a row
203        for (j=0,a_j=a,b_j=b,D_j=D; j<dimx; j++,b_j++,D_j++,a_j++)
204            *b_j=((long)(*D_j)*(*a_j))>>15;
205
206        alpha = (long)R[iy]; //\alpha = R+vDv = R+a*b
207        // R in q15, a in q15, b=q15
208//              gamma = (1<<15)/alpha; //(in q15)
209        //min alpha = R[iy] = 164
210        //max gamma = 0.0061 => gamma_ref = q7
211        for (j=0,a_j=a,b_j=b,D_j=D; j<dimx; j++,a_j++,b_j++,D_j++) {
212            beta   = alpha;
213            lambda = -((long)(*a_j)<<15)/beta;
214            alpha  += ((long)(*a_j)*(*b_j))>>15;
215            D[j] = ((((long)beta<<15)/alpha)*(*D_j))>>15; //gamma is long
216            if (*D_j==0) *D_j=1;
217
218            for (i=0,b_i=b,U_ij=U+j; i<j; i++, b_i++,U_ij+=dimx) {
219                beta   = *U_ij;
220                *U_ij +=  ((long)lambda*(*b_i))>>15;
221                *b_i  +=  ((long)beta*(*b_j))>>15;
222            }
223        }
224        dzs = (((long)difz[iy])<<15)/alpha;  // apply scaling to innovations
225        // no shift due to gamma
226        for (i=0,x_i=xp,b_i=b; i<dimx; i++,x_i++,b_i++) {
227            *x_i  += ((long)dzs*(*b_i))>>15; // multiply by unscaled Kalman gain
228        }
229
230        //cout << "Ub: " << U << endl;
231        //cout << "Db: " << D << endl <<endl;
232
233    }
234
235}
236
237// Thorton procedure - Kalman predictive variance in UD
238void thorton_fast(int *U, int *D, int *PSIU, int *Q, int *G, int *Dold, unsigned int rows) {
239    unsigned int i,j,k;
240    // copy D to Dold
241    int *Dold_i,*Dold_k;
242    int *D_i;
243    int *PSIU_ij,*PSIU_ik,*PSIU_jk;
244    int *Q_jj,*Q_ii,*Q_kk;
245    int *U_ji;
246    int *G_ik,*G_jk;
247    int irows,jrows;
248    long sigma; // in qAU+15!!
249    long z;
250
251    for (i=0,Dold_i=Dold,D_i=D;i<rows;i++,Dold_i++,D_i++) {
252        *Dold_i=*D_i;
253    }
254
255    // initialize G = eye()
256    G_ik= G;
257    *G_ik++=32767;
258    for (i=0;i<rows-1;i++) {
259        // clean elem before diag
260        for (k=0; k<rows; k++) {
261            *G_ik++=0;
262        }
263        *G_ik++=32767;
264    }
265    // eye created
266
267    for (i=rows-1, Dold_i=Dold+i, D_i=D+i;
268            1; i--, Dold_i--,D_i--) { // stop if i==0 at the END!
269        irows=i*rows;
270        sigma = 0;
271        for (k=0, PSIU_ik=PSIU+irows,Dold_k=Dold;
272                k<rows; k++, PSIU_ik++,Dold_k++) {
273                        sigma += (((long)(*PSIU_ik)**PSIU_ik)>>(qAU))*(*Dold_k);
274        }
275        sigma += *(Q+i+irows)<<qAU;
276        for (j=i+1, G_ik=G+irows+i+1; j<rows; j++,G_ik++) {
277            sigma += (((long)(*G_ik)**G_ik)>>16)**(Q+j+j*rows);
278
279        }
280
281                if (sigma>((long)1<<(qAU+15))) {
282                        *D_i = 32767;
283//                      *(Dold+i)-=*(Q+i+irows);
284                } else {
285                        *D_i=sigma>>qAU;
286                }
287        if (*D_i==0) *D_i=1;
288
289        for (j=0;j<i;j++) {
290            jrows = j*rows;
291
292            sigma =0;
293            for (k=0, PSIU_ik=PSIU+irows, PSIU_jk=PSIU+jrows, Dold_k=Dold;
294                    k<rows; k++, PSIU_ik++, PSIU_jk++, Dold_k++) {
295
296                                sigma += ((((long)(*PSIU_ik)**PSIU_jk)>>qAU)**Dold_k);
297            }
298
299            for (k=i,G_ik=G+irows+i,G_jk=G+jrows+i,Q_kk=Q+k*rows+k;
300                    k<rows;k++,G_ik++,G_jk++,Q_kk+=rows+1) {
301                sigma += ((((long)*G_ik)**G_jk)>>16)**Q_kk;
302            }
303
304            z=(sigma/(*D_i))<<(15-qAU); // shift to q15
305            if (z>32767) z=32767;
306            if (z<-32768) z=-32768;
307
308            U_ji=U+jrows+i;
309            *U_ji = (int)z;
310
311
312            for (k=0,PSIU_ik=PSIU+irows,PSIU_jk=PSIU+jrows;
313                    k<rows;k++,PSIU_ik++,PSIU_jk++) {
314                *PSIU_jk -= ((long)*U_ji**PSIU_ik)>>15;
315            }
316
317            for (k=0,G_jk=G+jrows,G_ik=G+irows;
318                    k<rows;k++, G_jk++, G_ik++) {
319                *G_jk -=  ((long)*U_ji**G_ik)>>15;
320            }
321
322        }
323                if (i==0) return;
324    }
325}
326
327void bierman(int *difz, int *xp, int *U, int *D, int *R, unsigned int dimy, unsigned int dimx ) {
328    long alpha;
329    long gamma,beta,lambda;
330    int b[5]; // ok even for 4-dim state
331    int *a; // in [0,1] -> q15
332    unsigned int iy,j,i;
333
334    for (iy=0; iy<dimy; iy++) {
335        // a is a row
336        a = U+iy*dimx; // iyth row of U
337        for (j=0;j<dimx;j++) {
338            (j<iy)? b[j]=0: (j==iy)? b[j]=D[j] : b[j]=((long)D[j]*a[j])>>15;
339        }
340
341        alpha = (long)R[iy]; //\alpha = R+vDv = R+a*b
342        // R in q15, a in q15, b=q15
343//              gamma = (1<<15)/alpha; //(in q15)
344        //min alpha = R[iy] = 164
345        //max gamma = 0.0061 => gamma_ref = q7
346        for (j=0;j<dimx;j++) {
347            beta   = alpha;
348            lambda = -(long(a[j])<<15)/beta;
349            alpha  += ((long(a[j])*b[j])>>15);
350            D[j] = (((long(beta)<<15)/alpha)*D[j])>>15; //gamma is long
351            if (D[j]==0) D[j]=1;
352
353            //                  cout << "a: " << alpha << "g: " << gamma << endl;
354            for (i=0;i<j;i++) {
355                beta   = U[i*dimx+j];
356                U[i*dimx+j] +=  (lambda*b[i])>>15;
357                b[i]   +=  (beta*b[j])>>15;
358            }
359        }
360        int dzs = (long(difz[iy])<<15)/alpha;  // apply scaling to innovations
361        // no shift due to gamma
362        for (i=0; i<dimx; i++) {
363            xp[i]  += (long(dzs*b[i]))>>15; // multiply by unscaled Kalman gain
364        }
365
366        //cout << "Ub: " << U << endl;
367        //cout << "Db: " << D << endl <<endl;
368
369    }
370
371}
372
373/* square root of 0<a<1 using taylor at 0.5 in q15*/
374int int_sqrt(int x) {
375        double xd(double(x)/32768.);
376        return round(sqrt(xd)*32768);
377
378    //sqrt(x) == 1/2*2^(1/2)+1/2*2^(1/2)*(x-1/2)-1/4*2^(1/2)*(x-1/2)^2
379    //         = k1 + k1*(x-0.5) - k2*(x-0.5)(x-0.5);
380#define k1 23170 //0.5*sqrt(2)*32768
381#define k2 11585 //0.25*sqrt(2)*32768
382
383    int tmp;
384    if (x>6554) {
385        int xm05=x-16384;
386        tmp = ((long)k1*xm05)>>15;
387        tmp-=(((long(k2)*xm05)>>15)*xm05)>>15;
388        tmp +=k1;
389    } else {
390        tmp = 4*x;
391        tmp-=long(8*x)*x>>15;
392    }
393    return tmp;
394}
395
396void householder(int *Ch /*= int *PSICh*/, int *Q, unsigned int dimx) {
397    int k,j,i;
398    int alpha,beta;
399    long sigma;
400    int B[25];//beware
401    int w[5];
402    int v[5];
403
404    // copy Q to B
405    for (i=0;i<dimx*dimx;i++)
406    {
407        B[i]=Q[i];
408    }
409
410    for (k=dimx-1; k>=0; k--)
411    {
412        sigma=0;
413        for (j=0;j<dimx;j++)
414        {
415            sigma+=(long)B[k*dimx+j]*B[k*dimx+j];
416        }
417        for (j=0;j<=k;j++)
418        {
419            sigma+=(long)Ch[k*dimx+j]*Ch[k*dimx+j];
420        }
421        /*               double sigf=double(sigma)/(1<<15);
422                         double alpf = sqrt(sigf);*/
423//              if (sigma>16384) sigma=16384;
424//        alpha=int_sqrt(sigma);
425          alpha = (int)(sqrt((double)sigma)+0.5);   // predelat pro DSP
426        // alpha = alpf*(1<<15);
427        //
428        sigma=0;
429        for (j=0;j<dimx;j++) {
430            w[j]=B[k*dimx+j];
431            sigma+=(long)w[j])*w[j];
432        }
433        for (j=0; j<=k;j++) {
434            if (j==k) {
435                v[j]=Ch[k*dimx+j]-alpha;
436            } else {
437                v[j]=Ch[k*dimx+j];
438            }
439            sigma+=(long)v[j]*v[j];
440        }
441       
442        alpha=sigma>>16;
443        if (alpha==0) alpha =1;
444
445        for (i=0;i<=k;i++) {
446            sigma=0;
447            for (j=0;j<dimx;j++) {
448                sigma+=(long)B[i*dimx+j]*w[j];
449            }
450            for (j=0;j<=k;j++) {
451                sigma+=(long)Ch[i*dimx+j]*v[j];
452            }
453
454            sigma = sigma >> 15;               // navrat do Q15
455
456            for (j=0;j<dimx;j++) 
457            {
458                B[i*dimx+j]-=(sigma*w[j])/alpha;
459            };
460           
461            for (j=0;j<=k;j++)
462            {
463                Ch[i*dimx+j]-=(sigma*v[j])/alpha;
464            }
465        }
466    }
467
468}
469
470void carlson(int *difz, int *xp, int *Ch, int *R, unsigned int dimy, unsigned int dimx ) {
471    int alpha,beta,gamma;
472    int delta, eta,epsilon,zeta,sigma,tau;
473    int i,j,iy;
474    int w[5];
475
476    for (iy=0; iy<dimy; iy++)
477    {
478        alpha=R[iy];
479        delta = difz[iy];
480
481        for (j=0;j<dimx;j++)
482        {
483            sigma=Ch[iy*dimx+j];
484            beta=alpha;
485            alpha+=((long)sigma*sigma)>>15;
486//                      double ab=(double)alpha*beta/32768./32768.;
487//                      double s_ab=sqrt(ab);
488            gamma=(int)(sqrt((double)((long)alpha*beta))+0.5);            // predelat v DSP
489            //gamma = round(s_ab*(1<<15));
490//            eta=((long)beta<<15) / gamma;
491            //zeta=(long(sigma)<<15)/ gamma;
492            w[j]=0;
493            for (i=0;i<=j;i++) {
494                tau=Ch[i*dimx+j];
495                Ch[i*dimx+j]=((long)beta*Ch[i*dimx+j] -(long)sigma*w[i])/gamma;
496                w[i]+=((long)tau*sigma)>>15;
497            }
498        }
499
500        //epsilon=(long(difz)<<15) / (alpha); // q15*q13/q13 = q15
501        for (i=0;i<dimx;i++) {
502            xp[i]+=((long)w[i]*delta)/alpha;
503        }
504    }
505}
506
507/* perform Householder update of Ch matrix using PSI*Ch , Q, */
508extern void givens(int *Ch /*= int *PSICh*/, int *Q, unsigned int dimx){
509        int i,j,k;
510        int rho,s,c,tau;
511
512        int A[25];//beware
513        // copy Q to A
514        for (i=0;i<dimx*dimx;i++) {
515                A[i]=Q[i];
516        }
517
518
519        for (i=dimx-1; i>=0; i--){
520                for (j=0; j<dimx; j++) {
521                        rho=int_sqrt(((long)Ch[i*dimx+i]*Ch[i*dimx+i]+long(A[i*dimx+j])*A[i*dimx+j])>>15);
522                        if (rho==0) break;
523                        s=(long(A[i*dimx+j])<<15)/rho;
524                        c=(long(Ch[i*dimx+i])<<15)/rho;
525                        for (k=0;k<=i; k++){
526                                tau=(long(c)*A[k*dimx+j]-long(s)*Ch[k*dimx+i])>>15;
527                                Ch[k*dimx +i]=(long(s)*A[k*dimx+j]+long(c)*Ch[k*dimx+i])>>15;
528                                A[k*dimx +j]=tau;
529                        }
530                }
531        }
532        for (j=0; j<i; j++){
533                rho=int_sqrt((long(Ch[i*dimx+i])*Ch[i*dimx+i]+long(Ch[i*dimx+j])*Ch[i*dimx+j])>>15);
534                if (rho==0) break; 
535                s=(long(Ch[i*dimx+j])<<15)/rho;
536                c=(long(Ch[i*dimx+i])<<15)/rho;
537                for (k=0; k<=i; k++){
538                        tau=(long(c)*Ch[k*dimx+j]-long(s)*Ch[k*dimx+i])>>15;
539                        Ch[k*dimx+i]=(long(s)*Ch[k*dimx+j]+long(c)*Ch[k*dimx+i])>>15;
540                        Ch[k*dimx+j]=tau;
541                }
542        }
543}
Note: See TracBrowser for help on using the browser.