rtklib代碼詳解——lambda.c


* reference :
*      [1] P.J.G.Teunissen, The least-square ambiguity decorrelation adjustment:
*        a method for fast GPS ambiguity estimation, J.Geodesy, Vol.70, 65-82,
*          1995
*      [2] X.-W.Chang, X.Yang, T.Zhou, MLAMBDA: A modified LAMBDA method for
*      integer least-squares estimation, J.Geodesy, Vol.79, 552-565, 2005

lambda/mlambda  整數最小二乘估計函數:lambda

1   首先對浮點協方差陣進行LD分解:

 

2   lambda reduction

 

 

 

3   z變換,將雙差模糊度進行變換

 

4   mlambda search,結果存儲在E和s中(整數解)

 

5   逆Z變換,求解雙差整周模糊度解,存儲在F中

 

前言

整周模糊度的求解是GNSS高精度定位中的關鍵性問題,正確快速地固定整周模糊度能使GNSS的定位精度到達厘米甚至毫米級。在GNSS相對定位過程中,通過卡爾曼濾波可以求解得雙差整周模糊度參數的浮點解(即小數解)及其方差-協方差矩陣,而由於整周模糊度具有整數特性,那么不管是單差整周模糊度還是雙差整周模糊度都理應是整數。如何利用整周模糊度參數的浮點解及其方差-協方差矩陣,正確求得整周模糊度參數的固定解(即整數解),就是模糊度固定要解決的問題(這實際上是一個數學問題)。
本篇整理了LAMBDA算法的理論及其在RTKLIB中的代碼部分,由於LAMBDA算法在模糊度固定領域已經非常成熟,博主以往都將其黑箱處理,最近才開始深入學習,若博客中有描述有誤的地方,煩請大佬指正,感激不盡!

參考文獻:
[1] 李征航, 黃勁松. GPS測量與數據處理.第3版[M]. 武漢大學出版社, 2016.
[2] Jonge P D , Tiberius C . The LAMBDA method for integer ambiguity estimation: implementation aspects[J]. No of Lgr Series, 1998.
[3] Chang X W , Yang X , Zhou T . MLAMBDA: a modified LAMBDA method for integer least-squares estimation[J]. Journal of Geodesy, 2005, 79(9):552-565.

一、LAMBDA算法理論

最小二乘模糊度降相關平差法(Leastsquare AMBiguity Decorrelation Adjustment-LAMBDA)理論嚴密,搜索速度快,是一種被廣泛采用的模糊度固定方法。該方法主要由兩部分組成:(1)為降低模糊度參數之間相關性而進行的多維整數變換;(2)在轉換后的空間內進行模糊度搜索,然后再將結果轉換回模糊度空間中,進而求得模糊度整數解。

1、模糊度參數降相關

由於模糊度之間具有相關性,一個模糊度參數的變化會影響其他模糊度的搜索,使得搜索算法的計算量巨大。如果能夠設法降低模糊度參數之間的相關性,使得某一模糊度的變化對其他模糊度的取值的影響盡可能小,就能大大加快模糊度的搜索過程。
LAMBDA算法通過對模糊度參數及其方差-協方差陣進行整數高斯變換(也稱z變換),將他們從原空間變換到新的空間中去,實現模糊度的降相關:

 

 

 

 

 

 

 

 

 

 

1)使L矩陣中非對角線元素絕對值小於0.5

 

二、RTKLIB中的lambda()函數

RTKLIB中使用的LAMBDA算法,與第一節中所述的LAMBDA算法有些區別,但他們的核心思想是相同的,配合源碼學習可幫助理解LAMBDA算法(對代碼關鍵部分進行了注釋)。

需要注意的是,RTKLIB中采用lambda算法降相關,mlambda算法搜索。

/* lambda/mlambda integer least-square estimation ------------------------------
* integer least-square estimation. reduction is performed by lambda,
* and search by mlambda. 用lambda算法降相關,mlambda算法搜索
* args   : int    n      I  number of float parameters
*          int    m      I  number of fixed solutions
*          double *a     I  float parameters (n x 1)
*          double *Q     I  covariance matrix of float parameters (n x n)
*          double *F     O  fixed solutions (n x m)
*          double *s     O  sum of squared residulas of fixed solutions (1 x m)
* return : status (0:ok,other:error)
* notes  : matrix stored by column-major order (fortran convension)
*-----------------------------------------------------------------------------*/
extern int lambda(int n, int m, const double *a, const double *Q, double *F,
                  double *s)
{
    int info;
    double *L,*D,*Z,*z,*E;
    
    if (n<=0||m<=0) return -1;
    L=zeros(n,n); D=mat(n,1); Z=eye(n); z=mat(n,1); E=mat(n,m);
    
    /* LD factorization 對雙差模糊度方差-協方差陣Q進行LDLT分解 */
    if (!(info=LD(n,Q,L,D))) {
        
        /* lambda reduction lambda降相關 */
        reduction(n,L,D,Z);
        matmul("TN",n,1,n,1.0,Z,a,0.0,z); /* z=Z'*a */
        
        /* mlambda search mlambda搜索 */
        if (!(info=search(n,m,L,D,z,E,s))) {

            /* 將在新空間中固定的模糊度逆變換回雙差模糊度空間中 */
            info=solve("T",Z,E,n,m,F); /* F=Z'\E */
        }
    }
    free(L); free(D); free(Z); free(z); free(E);
    return info;
}

降相關子函數reduction()

/* lambda reduction (z=Z'*a, Qz=Z'*Q*Z=L'*diag(D)*L) (ref.[1]) ---------------*/
static void reduction(int n, double *L, double *D, double *Z)
{
    int i,j,k;
    double del;
    
    j=n-2; k=n-2;
    //這里的調序變換類似插入排序的思路?
    while (j>=0) {
        //由於第k+1,k+2,...,n-2列都進行過降相關並且沒有被上一次調序變換影響,
        //因此只需對第0,1,...,k-1,k列進行降相關
        if (j<=k) for (i=j+1;i<n;i++) gauss(n,L,Z,i,j);//從最后一列開始,各列非對角線元素從上往下依次降相關
        del=D[j]+L[j+1+j*n]*L[j+1+j*n]*D[j+1];
        if (del+1E-6<D[j+1]) { /* 檢驗條件,若不滿足檢驗條件則開始進行調序變換 compared considering numerical error */
            perm(n,L,D,j,del,Z);//調序變換
            k=j; j=n-2;//完成調序變換后重新從最后一列開始進行降相關及排序,k記錄最后一次進行過調序變換的列序號
        }
        else j--;
    }
}

搜索子函數search()

搜索的目標函數為:

 

 

r的取值決定了超橢圓搜索區域的大小,若r取小了,最優解落在搜索區域外,無法搜索到最優解;若r取大了,搜索區域過大,搜索效率變低。LAMBDA算法里通過某種方式確定r的取值,后續的所有搜索都在固定半徑的超橢圓區域中進行,這種固定半徑搜索方式的效率依賴於r取值的合理性。
X.W.Chang等提出MLAMBDA算法,此方法在搜索的過程中不斷地縮小搜索區域的半徑r,大多數情況下的搜索效率都要高於LAMBDA的搜索方式。其原理如下:

由理論部分,對於任一模糊度有:

 

 

 

 

 

其偽代碼(參考文獻3)及代碼(RTKLIB)如下:

 

 

static int search(int n, int m, const double *L, const double *D,
                  const double *zs, double *zn, double *s)
{
    int i,j,k,c,nn=0,imax=0;
    double newdist,maxdist=1E99,y;//maxdist,當前超橢圓半徑
    double *S=zeros(n,n),*dist=mat(n,1),*zb=mat(n,1),*z=mat(n,1),*step=mat(n,1);
    
    k=n-1; dist[k]=0.0; //k表示當前層,從最后一層(n-1)開始計算
    zb[k]=zs[k];//即zn
    z[k]=ROUND(zb[k]); y=zb[k]-z[k]; step[k]=SGN(y);    //四舍五入取整;取整后的數與未取整的數作差;step記錄z[k]是四舍還是五入
    for (c=0;c<LOOPMAX;c++) {
        newdist=dist[k]+y*y/D[k];
        if (newdist<maxdist) {  //如果當前累積目標函數計算值小於當前超橢圓半徑
            if (k!=0) { //情況1:若還未計算至第一層,繼續計算累積目標函數值
                dist[--k]=newdist;  //記錄下當前層的累積目標函數值,dist[k]表示了第k,k+1,...,n-1層的目標函數計算和
                for (i=0;i<=k;i++)
                    S[k+i*n]=S[k+1+i*n]+(z[k+1]-zb[k+1])*L[k+1+i*n];//
                zb[k]=zs[k]+S[k+k*n];   //計算Zk,即第k個整數模糊度參數的備選組的中心
                z[k]=ROUND(zb[k]); y=zb[k]-z[k]; step[k]=SGN(y);    //四舍五入取整;取整后的數與未取整的數作差;記錄是四舍還是五入
            }
            else {  //情況2:若已經計算至第一層,意味着所有層的累積目標函數值計算完畢
                //nn為當前候選解數,m為我們需要的固定解數,這里為2,表示需要一個最優解及一個次優解
                //s記錄候選解的目標函數值,imax記錄之前候選解中的最大目標函數值的坐標
                if (nn<m) { //若候選解數還沒滿
                    if (nn==0||newdist>s[imax]) imax=nn;//若當前解的目標函數值比之前最大的目標函數值都大,那么更新imax使s[imax]指向當前解中具有的最大目標函數值
                    for (i=0;i<n;i++) zn[i+nn*n]=z[i];//zn存放所有候選解
                    s[nn++]=newdist;//s記錄當前目標函數值newdist,並加加當前候選解數nn
                }
                else {  //若候選解數已滿(即當前zn中已經存了2個候選解)
                    if (newdist<s[imax]) {  //若 當前解的目標函數值 比 s中的最大目標函數值 小
                        for (i=0;i<n;i++) zn[i+imax*n]=z[i];    //用當前解替換zn中具有較大目標函數值的解
                        s[imax]=newdist;    //用當前解的目標函數值替換s中的最大目標函數值
                        for (i=imax=0;i<m;i++) if (s[imax]<s[i]) imax=i;    //更新imax保證imax始終指向s中的最大目標函數值
                    }
                    maxdist=s[imax];    //用當前最大的目標函數值更新超橢圓半徑
                }
                z[0]+=step[0]; y=zb[0]-z[0]; step[0]=-step[0]-SGN(step[0]); //在第一層,取下一個有效的整數模糊度參數進行計算(若zb為5.3,則z取值順序為5,6,4,7,...)
            }
        }
        else {  //情況3:如果當前累積目標函數計算值大於當前超橢圓半徑
            if (k==n-1) break; //如果當前層為第n-1層,意味着后續目標函數各項的計算都會超出超橢圓半徑,因此終止搜索
            else {  //若當前層不是第n-1層
                k++;    //退后一層,即從第k層退到第k+1層
                z[k]+=step[k]; y=zb[k]-z[k]; step[k]=-step[k]-SGN(step[k]); //計算退后一層后,當前層的下一個有效備選解
            }
        }
    }

    // 對s中的目標函數值及zn中的候選解進行排序(以s中目標函數值為排序標准,進行升序排序)
    // RTKLIB中最終可以得到一個最優解一個次優解,存在zn中,兩解對應的目標函數值,存在s中
    for (i=0;i<m-1;i++) { /* sort by s */
        for (j=i+1;j<m;j++) {
            if (s[i]<s[j]) continue;
            SWAP(s[i],s[j]);
            for (k=0;k<n;k++) SWAP(zn[k+i*n],zn[k+j*n]);
        }
    }
    free(S); free(dist); free(zb); free(z); free(step);
    
    if (c>=LOOPMAX) {
        fprintf(stderr,"%s : search loop count overflow\n",__FILE__);
        return -1;
    }
    return 0;
}

 參考鏈接

  GNSS整周模糊度固定算法(LAMBDA算法)     (理論推導非常詳細)

   模糊度固定LAMBDA算法詳解

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM