/*------------------------------------------------------------------------------ * lambda.c : integer ambiguity resolution * * Copyright (C) 2007-2008 by T.TAKASU, All rights reserved. * * 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 * * version : $Revision: 1.1 $ $Date: 2008/07/17 21:48:06 $ * history : 2007/01/13 1.0 new * 2015/05/31 1.1 add api lambda_reduction(), lambda_search() *-----------------------------------------------------------------------------*/ #include "rtklib.h" /* constants/macros ----------------------------------------------------------*/ #define LOOPMAX 10000 /* maximum count of search loop */ #define SGN(x) ((x)<=0.0?-1.0:1.0) #define ROUND(x) (floor((x)+0.5)) #define SWAP(x,y) do {double tmp_; tmp_=x; x=y; y=tmp_;} while (0) /* LD factorization (Q=L'*diag(D)*L) -----------------------------------------*/ static int LD(int n, const double *Q, double *L, double *D) { int i,j,k,info=0; double a,*A=mat(n,n); memcpy(A,Q,sizeof(double)*n*n); for (i=n-1;i>=0;i--) { if ((D[i]=A[i+i*n])<=0.0) {info=-1; break;} a=sqrt(D[i]); for (j=0;j<=i;j++) L[i+j*n]=A[i+j*n]/a; for (j=0;j<=i-1;j++) for (k=0;k<=j;k++) A[j+k*n]-=L[i+k*n]*L[i+j*n]; for (j=0;j<=i;j++) L[i+j*n]/=L[i+i*n]; } free(A); if (info) fprintf(stderr,"%s : LD factorization error\n",__FILE__); return info; } /* integer gauss transformation ----------------------------------------------*/ static void gauss(int n, double *L, double *Z, int i, int j) { int k,mu; if ((mu=(int)ROUND(L[i+j*n]))!=0) { for (k=i;k=0) { if (j<=k) for (i=j+1;is[imax]) imax=nn; for (i=0;i=LOOPMAX) { fprintf(stderr,"%s : search loop count overflow\n",__FILE__); return -2; } return 0; } /* lambda/mlambda integer least-square estimation ------------------------------ * integer least-square estimation. reduction is performed by lambda (ref.[1]), * and search by mlambda (ref.[2]). * args : int n I number of float parameters * int m I number of fixed solutions * double *a I float parameters (n x 1) (double-diff phase biases) * 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 (lower diaganol) factorization (Q=L'*diag(D)*L) */ if (!(info=LD(n,Q,L,D))) { /* lambda reduction (z=Z'*a, Qz=Z'*Q*Z=L'*diag(D)*L) */ reduction(n,L,D,Z); matmul("TN",n,1,n,1.0,Z,a,0.0,z); /* z=Z'*a */ /* mlambda search z = transformed double-diff phase biases L,D = transformed covariance matrix */ if (!(info=search(n,m,L,D,z,E,s))) { /* returns 0 if no error */ info=solve("T",Z,E,n,m,F); /* F=Z'\E */ } } free(L); free(D); free(Z); free(z); free(E); return info; } /* lambda reduction ------------------------------------------------------------ * reduction by lambda (ref [1]) for integer least square * args : int n I number of float parameters * double *Q I covariance matrix of float parameters (n x n) * double *Z O lambda reduction matrix (n x n) * return : status (0:ok,other:error) *-----------------------------------------------------------------------------*/ extern int lambda_reduction(int n, const double *Q, double *Z) { double *L,*D; int i,j,info; if (n<=0) return -1; L=zeros(n,n); D=mat(n,1); for (i=0;i