root/applications/pmsm/simulator_zdenek/ekf_example/Zdrojove kody_final/PC/MATRIX.CPP

Revision 1263, 13.9 kB (checked in by peroutka, 14 years ago)
Line 
1/************************************
2        Extended Kalman Filter
3        Matrix operations
4
5        V. Smidl, Z. Peroutka
6
7Rev. 28.10.2010   (ZP)
8
926.10.2010      Prvni verze (VS)
10
1126.10.2010      Upravena chyba v Thorton_fast - spatne shiftovani o vypoctu SIGMA.
1227.10.2010      Pokus o odstraneni problemu v Thorton_fast - potize dela omezovani (orezavani) varianci.
1328.10.2010      Drobne upravy v kodu.
14
15*************************************/
16
17#include "matrix.h"
18#include <math.h>
19
20#define HIGH_PRECISION  0
21
22/* Matrix multiply Full matrix by upper diagonal matrix; */
23void mmultAU(int *m1, int *up, int *result, unsigned int rows, unsigned int columns)
24{
25    unsigned int i, j, k;
26    long tmp_sum=0L; //in 15+qAU
27    int *m2pom;
28    int *m1pom=m1;
29    int *respom=result;
30
31    for (i=0; i<rows; i++) //rows of result
32    {
33        for (j=0; j<columns; j++) //columns of result
34        {
35            m2pom=up+j;
36
37            for (k=0; k<j; k++) //inner loop up to "j" - U(j,j)==1;
38            {
39                tmp_sum += ((long)(*(m1pom++))**m2pom)>>(15-qAU);
40                m2pom+=columns;
41            }
42            // add the missing A(i,j)
43            tmp_sum += (long)(*m1pom)<<qAU; // no need to shift
44            m1pom-=j; // shift back to first element
45
46            *respom++=tmp_sum>>15;
47
48            tmp_sum=0;
49        }
50        m1pom+=columns;
51    }
52};
53
54
55void bierman_fast(int *difz, int *xp, int *U, int *D, int *R, unsigned int dimy, unsigned int dimx )
56{
57    int alpha;
58    int beta,lambda;
59    int b[5]; // ok even for 4-dim state
60    int *a; // in [0,1] -> q15
61    unsigned int iy,j,i;
62
63    int *b_j,*b_i;
64    int *a_j;
65    int *D_j;
66    int *U_ij;
67    int *x_i;
68
69    a = U; // iyth row of U
70    for (iy=0; iy<dimy; iy++)
71    {
72        // a is a row
73        a_j=a;
74        b_j=b;
75        D_j=D;
76
77        for (j=0; j<dimx; j++)
78        {
79            *b_j=((long)(*D_j)*(*a_j))>>15;
80            b_j++;
81            D_j++;
82            a_j++;
83        }
84
85        alpha = R[iy]; //\alpha = R+vDv = R+a*b
86        // R in q15, a in q15, b=q15
87
88        a_j=a;
89        b_j=b;
90        D_j=D;
91
92        for (j=0; j<dimx; j++)
93        {
94            lambda=alpha;
95            if (HIGH_PRECISION == 0)
96              alpha = alpha + (((long)(*a_j)*(*b_j))>>15);
97            else
98              alpha = (((long)alpha<<15) + (long)(*a_j)*(*b_j))>>15;    // xxxx lepsi presnost
99
100            *D_j = ((long)lambda**D_j)/alpha;
101
102            if (*D_j==0) *D_j=1;
103
104            b_i=b;
105            U_ij=U+j;
106
107            for (i=0; i<j; i++)
108            {
109                beta   = *U_ij;
110                    if (HIGH_PRECISION == 0)
111                                {
112                  *U_ij = *U_ij - ((long)(*a_j)*(*b_i))/lambda;
113                  *b_i  = *b_i + (((long)beta*(*b_j))>>15);
114                                }
115                                else
116                                {
117                  *U_ij = ((long)lambda**U_ij - (long)(*a_j)*(*b_i))/lambda;
118                  *b_i  = (((long)*b_i<<15) + (long)beta**b_j)>>15;                                     
119                                }
120                b_i++;
121                U_ij+=dimx;
122            }
123
124            a_j++;
125            b_j++;
126            D_j++;
127        }
128
129        x_i=xp;
130        b_i=b;
131
132        for (i=0; i<dimx; i++)
133        {
134          if (HIGH_PRECISION == 0)
135            *x_i += ((long)difz[iy]**b_i)/alpha; // multiply by unscaled Kalman gain
136          else 
137            *x_i = ((long)alpha**x_i + (long)difz[iy]**b_i)/alpha;
138
139            x_i++;
140            b_i++;
141        }
142
143        a+=dimx;
144    }
145}
146
147/**/
148
149// Thorton procedure - Kalman predictive variance in UD
150void thorton_fast(int *U, int *D, int *PSIU, int *Q, int *G, int *Dold, unsigned int rows) {
151    unsigned int i,j,k;
152    // copy D to Dold
153    int *Dold_i,*Dold_k;
154    int *D_i;
155    int *PSIU_ij,*PSIU_ik,*PSIU_jk;
156    int *Q_jj,*Q_ii,*Q_kk;
157    int *U_ji;
158    int *G_ik,*G_jk;
159    int irows,jrows;
160    long sigma; // in qAU+15!!
161    long z;
162    long z_tmp;
163
164    Dold_i=Dold;
165    D_i=D;
166
167    for (i=0;i<rows;i++)
168    {
169        *Dold_i=*D_i;
170        Dold_i++;
171        D_i++;
172    }
173
174    // initialize G = eye()
175    G_ik= G;
176    *G_ik++=32767;
177    for (i=0;i<rows-1;i++)
178    {
179        // clean elem before diag
180        for (k=0; k<rows; k++)
181        {
182            *G_ik++=0;
183        }
184        *G_ik++=32767;
185    }
186    // eye created
187
188    Dold_i=Dold+rows-1;
189    D_i=D+rows-1;
190
191    for (i=rows-1; 1; i--)
192    { // stop if i==0 at the END!
193        irows=i*rows;
194        sigma = 0;
195
196        PSIU_ik=PSIU+irows;
197        Dold_k=Dold;
198
199        for (k=0;k<rows; k++)
200        {
201            sigma += (((long)(*PSIU_ik)**PSIU_ik)>>(qAU))*(*Dold_k);
202            PSIU_ik++;
203            Dold_k++;
204        }
205
206        sigma += (long)*(Q+i+irows)<<(qAU+qD-15);
207
208        G_ik=G+irows+i+1;
209
210        for (j=i+1; j<rows; j++)
211        {
212            sigma += ((((long)(*G_ik)**G_ik)>>15)**(Q+j+j*rows))>>(30-qAU-qD);
213            G_ik++;
214        }
215
216        if (sigma>((long)1<<(15+qAU)))
217        {
218                   *D_i = 32767;
219                } else
220        {
221           *D_i=sigma>>qAU;
222                }
223
224        if (*D_i==0) *D_i=1;
225
226        for (j=0;j<i;j++)
227        {
228            jrows = j*rows;
229
230            sigma =0;
231            PSIU_ik=PSIU+irows;
232            PSIU_jk=PSIU+jrows;
233            Dold_k=Dold;
234
235            for (k=0;k<rows; k++)
236            {
237
238                sigma += (((long)(*PSIU_ik)**PSIU_jk)>>qAU)**Dold_k;
239                PSIU_ik++;
240                PSIU_jk++;
241                Dold_k++;
242            }
243
244            G_ik=G+irows+i;
245            G_jk=G+jrows+i;
246            Q_kk=Q+i*rows+i;
247
248            for (k=i;k<rows;k++)
249            {
250                sigma += ((((long)(*G_ik)**G_jk)>>15)**Q_kk)>>(30-qAU-qD);
251                G_ik++;
252                G_jk++;
253                Q_kk+=rows+1;
254            }
255
256            z=(sigma/(*D_i))<<(15-qAU); // shift to q15
257            if (z>32767) z=32767;
258            if (z<-32768) z=-32768;
259
260            U_ji=U+jrows+i;
261            *U_ji = z;
262
263
264            PSIU_ik=PSIU+irows;
265            PSIU_jk=PSIU+jrows;
266
267            for (k=0; k<rows;k++)
268            {
269              if (HIGH_PRECISION == 0)
270                *PSIU_jk -= ((long)*U_ji**PSIU_ik)>>15;
271                          else
272                *PSIU_jk = (((long)(*PSIU_jk)<<15) - (long)*U_ji**PSIU_ik)>>15;
273
274                PSIU_ik++;
275                PSIU_jk++;
276            }
277
278            G_jk=G+jrows;
279            G_ik=G+irows;
280
281            for (k=0;k<rows;k++)
282            {
283              if (HIGH_PRECISION == 0)
284                *G_jk -= ((long)*U_ji**G_ik)>>15;
285                          else
286                *G_jk = (((long)(*G_jk)<<15) - (long)*U_ji**G_ik)>>15;
287                 G_jk++;
288                 G_ik++;
289            }
290        }
291
292        Dold_i--;
293        D_i--;
294        if (i==0) return;
295    }
296}
297
298/* square root of 0<a<1 using taylor at 0.5 in q15*/
299int16 int_sqrt(int16 x) {
300        double xd(double(x)/32768.);
301        return (int)((sqrt(xd)+0.5)*32768);
302
303    //sqrt(x) == 1/2*2^(1/2)+1/2*2^(1/2)*(x-1/2)-1/4*2^(1/2)*(x-1/2)^2
304    //         = k1 + k1*(x-0.5) - k2*(x-0.5)(x-0.5);
305#define k1 23170 //0.5*sqrt(2)*32768
306#define k2 11585 //0.25*sqrt(2)*32768
307
308    int16 tmp;
309    if (x>6554) {
310        int16 xm05=x-16384;
311        tmp = ((long)k1*xm05)>>15;
312        tmp-=(((long(k2)*xm05)>>15)*xm05)>>15;
313        tmp +=k1;
314    } else {
315        tmp = 4*x;
316        tmp-=long(8*x)*x>>15;
317    }
318    return tmp;
319}
320
321void householder(int16 *Ch, int16 *Q, unsigned int16 dimx)
322{
323    int16 k,j,i;
324    int16 alpha,beta;
325    int32  sigma; // 2*qCh
326    int32  tmp_long;
327    int16 B[25];//Q in qCh
328    int16 w[5];
329    int16 v[5];
330
331    int16 *B_ij, *Q_i, *B_kj, *Ch_kj, *Ch_ij, *w_j, *v_j;
332
333    B_ij=B;
334    Q_i=Q;
335    // copy Q to B
336    for (i=0;i<dimx*dimx;i++)
337    {
338       *B_ij++=(*Q_i++)>>(15-qCh);
339    }
340
341    for (k=dimx-1; k>=0; k--)
342    {
343        sigma=0;
344        B_kj=B+k*dimx+k;
345        Ch_kj=Ch+k*dimx;
346
347        for (j=k;j<dimx ;j++)
348        {
349            sigma+=((long)*B_kj**B_kj);
350            B_kj++;
351        }
352
353        for (j=0;j<=k;j++)
354        {
355            sigma+=((long)*Ch_kj**Ch_kj);
356            Ch_kj++;
357        }
358
359        //alpha in qCh
360        alpha = (int)(sqrt((double)sigma)+0.5);   // verze pro PC
361//        alpha = qsqrt(sigma);                     // verze pro DSP
362
363        sigma=0;
364
365        w_j=w;
366        B_kj=B+k*dimx;
367
368        for (j=0;j<dimx;j++)
369        {
370            *w_j=*B_kj;
371            sigma+=(long)*w_j**w_j;
372            w_j++;
373            B_kj++;
374        }
375
376        v_j=v;
377        Ch_kj=Ch+k*dimx;
378
379        for (j=0; j<=k;j++)
380        {
381            if (j==k) {
382                *v_j=*Ch_kj-alpha;
383            } else {
384                *v_j=*Ch_kj;
385            }
386            sigma+=(long)*v_j**v_j;
387
388            v_j++;
389            Ch_kj++;
390        }
391
392        alpha=sigma>>(qCh+1); // alpha = sigma /2;
393        if (alpha==0) alpha =1;
394
395        for (i=0;i<=k;i++)
396        {
397            sigma=0;
398
399            B_ij=B+i*dimx+i;
400            w_j=w+i;
401
402            for (j=i;j<dimx;j++)
403            {
404                sigma+=((long)*B_ij**w_j);
405
406                B_ij++;
407                w_j++;
408            }
409
410            Ch_ij = Ch + i*dimx;
411            v_j=v;
412
413            for (j=0;j<=k;j++)
414            {
415                sigma+=(long)*Ch_ij**v_j;
416
417                Ch_ij++;
418                v_j++;
419            }
420
421            sigma = sigma >> 15;               // navrat do Q15
422            if (sigma>32767) sigma=32767;
423
424
425            B_ij=B+i*dimx+i;
426            w_j=w+i;
427
428            for (j=i;j<dimx;j++)
429            {
430                tmp_long=((long)*B_ij*alpha-sigma**w_j)/alpha;
431                if (tmp_long>32767)
432                   tmp_long=32767;
433                if (tmp_long<-32768)
434                   tmp_long=-32768;
435                *B_ij++=tmp_long;
436                w_j++;
437            };
438
439            Ch_ij=Ch+i*dimx;
440            v_j=v;
441
442            for (j=0;j<=k;j++)
443            {
444                tmp_long=((long)*Ch_ij*alpha-sigma**v_j)/alpha;
445                if (tmp_long>32767)
446                   tmp_long=32767;
447                if (tmp_long<-32768)
448                   tmp_long=-32768;
449                *Ch_ij++=tmp_long;
450                v_j++;
451            }
452        }
453    }
454}
455
456
457//  Nize uvedene fce jsou dle implementace v DSP
458void carlson(int16 *difz, int16 *xp, int16 *Ch, int16 *R, unsigned int16 dimy, unsigned int16 dimx ) {
459    int16 alpha,beta,gamma;
460    int16 delta, eta,epsilon,zeta,sigma,tau;
461    int16 i,j,iy;
462    int16 w[5];
463        int32 tmp_long;
464
465        int16 *Ch_ij, *w_i, *x_i;
466
467
468    for (iy=0; iy<dimy; iy++)
469    {
470        alpha=R[iy];
471        delta = difz[iy];
472
473        for (j=0;j<dimx;j++)
474        {
475            sigma=Ch[iy*dimx+j];
476            beta=alpha;
477//            alpha+=((long)sigma*sigma)>>15;
478            alpha=(((long)alpha<<15)+(long)sigma*sigma)>>15;                            // vyssi presnost
479//            gamma= qsqrt(((long)alpha*beta));                          // verze pro DSP
480            gamma= (int)(sqrt((double)((long)alpha*beta)));              // verze pro PC
481
482            w[j]=0;
483
484                        Ch_ij=Ch+j;
485                        w_i=w;
486
487            for (i=0;i<=j;i++)
488            {
489//                tau=Ch[i*dimx+j];
490                                tau=*Ch_ij;
491//                              tmp_long=((long)beta*Ch[i*dimx+j] -(long)sigma*w[i])/gamma;
492                                tmp_long=((long)beta**Ch_ij -(long)sigma**w_i)/gamma;
493
494                                if (tmp_long>32767)
495                                        tmp_long=32767;
496                                if (tmp_long<-32768)
497                                        tmp_long=-32768;
498                                *Ch_ij=tmp_long;
499                       
500//                w_i+=((long)tau*sigma)>>15;
501                *w_i=(((long)*w_i<<15)+(long)tau*sigma)>>15;
502
503                                w_i++;
504                                Ch_ij+=dimx;
505            }
506        }
507
508                x_i=xp;
509                w_i=w;
510        for (i=0;i<dimx;i++) {
511//            xp[i]+=((long)w[i]*delta)/alpha;
512//            *x_i+=((long)*w_i*delta)/alpha;
513            *x_i=((long)*x_i*alpha+(long)*w_i*delta)/alpha;             // vyssi presnost
514                        x_i++;
515                        w_i++;
516        }
517    }
518}
519
520/* Matrix multiply Full matrix by upper diagonal matrix; */
521void mmultACh(int16 *m1, int16 *up, int16 *result, unsigned int16 rows, unsigned int16 columns) {
522        unsigned int16 i, j, k;
523        int32 tmp_sum=0L;
524        int16 *m2pom;
525        int16 *m1pom=m1;
526        int16 *respom=result;
527
528        for (i=0; i<rows; i++) //rows of result
529    {
530                for (j=0; j<columns; j++) //columns of result
531        {
532                        m2pom=up+j;//??
533                       
534                        for (k=0; k<=j; k++) //inner loop up to "j" - U(j,j)==1;
535            {
536                                tmp_sum+=(int32)(*(m1pom++))**m2pom;
537                                m2pom+=columns;
538                        }
539                        m1pom-=(j+1); // shift back to first element
540
541                        *respom++=tmp_sum>>15;
542                       
543                        tmp_sum=0;
544                }
545                m1pom+=(columns);
546        }
547}
548
549void givens(int16 *Ch, int16 *Q, unsigned int16 dimx)
550{
551        int16 i,j,k;
552        int16 rho,s,c,tau;
553        int32  tmp_long;
554
555        int16 A[25];//beware
556
557        int16 *A_ij, *Q_i, *Ch_ki, *Ch_kj, *Ch_ii, *Ch_ij, *A_kj;
558
559        A_ij=A;
560        Q_i=Q;
561        // copy Q to A
562        for (i=0;i<dimx*dimx;i++)
563        {
564//              A[i]=Q[i]>>(15-qCh);
565          *A_ij++=(*Q_i++)>>(15-qCh);
566        }
567
568        for (i=dimx-1; i>=0; i--)
569        {
570                Ch_ii=Ch+i*dimx+i;
571                A_ij=A+i*dimx;
572
573                for (j=0; j<dimx; j++)
574                {
575//                      tmp_long=(long)Ch[i*dimx+i]*Ch[i*dimx+i]+(long)A[i*dimx+j]*A[i*dimx+j];
576
577                        tmp_long=(long)*Ch_ii**Ch_ii+(long)*A_ij**A_ij;
578
579                        if (tmp_long>0)
580                        {
581//                              rho=qsqrt(tmp_long);                   // verze pro DSP
582                                rho=(int)(sqrt((double)tmp_long));     // verze pro PC
583                                s=((long)*A_ij<<15)/rho;
584                                c=((long)*Ch_ii<<15)/rho;
585
586                                Ch_ki=Ch+i;
587                                A_kj=A+j;
588
589                                for (k=0;k<=i; k++)
590                                {
591                                        tau=((long)c**A_kj-(long)s**Ch_ki)>>15;
592                                        *Ch_ki=((long)s**A_kj+(long)c**Ch_ki)>>15;
593                                        *A_kj=tau;
594
595                                        Ch_ki+=dimx;
596                                        A_kj+=dimx;
597                                }
598                        }
599                        A_ij++;
600                }
601       
602        Ch_ij = Ch+i*dimx;
603
604        for (j=0; j<i; j++)
605        {
606                tmp_long=(long)*Ch_ii**Ch_ii+(long)*Ch_ij**Ch_ij;
607               
608                if (tmp_long>0)
609                {
610//                      rho=qsqrt(tmp_long);                     // verze pro DSP
611                        rho=(int)(sqrt((double)tmp_long));       // verze pro PC
612                        s=((long)*Ch_ij<<15)/rho;
613                        c=((long)*Ch_ii<<15)/rho;
614                       
615                        Ch_kj = Ch + j;
616                        Ch_ki = Ch + i;
617                       
618                        for (k=0; k<=i; k++)
619                        {
620                                tau=((long)c**Ch_kj-(long)s**Ch_ki)>>15;
621                                *Ch_ki =((long)s**Ch_kj+(long)c**Ch_ki)>>15;
622                                *Ch_kj=tau;
623
624                                Ch_kj += dimx;
625                                Ch_ki += dimx;
626                        }
627                }
628                Ch_ij++;
629        }
630  }
631}
Note: See TracBrowser for help on using the browser.