⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 svcalc.c

📁 GPS导航定位程序
💻 C
📖 第 1 页 / 共 2 页
字号:
#include "includes.h"

/****************************************************************************    
* Function: void SVPredicts(int sv, int wk, double sec, double t[3][3],
*                           double obsx,double obsy, double obsz,
*                           float *elv, float *azi, float *dopp,
*                           float *erc, float *iono, float *tropo)
*
* Predicts a satellite's elevation, azimuth, Doppler and earth rotation,
* ionospheric and tropospheric correction to the pseudo-range.
*
* Input: sv - the satellite PRN number.
*        wk - the GPS week number.
*        sec - the GPS second in the week.
*        obsx - the observer x co-ordinate.
*        obsy - the observer y co-ordinate.
*        obsz - the observer z co-ordinate.
*
* Output: elv - the satellite elevation, radians.
*         azi - the satellite azimuth, radians.
*         dopp - the Doppler frequency, Hz.
*         erc - earth rotation pseudo-range correction, m.
*         iono - ionospheric pseudo-range correction, m.
*         tropo - tropospheric pseudo-range correction, m.
*
* Return Value: None.
****************************************************************************/
void SVPredicts(int sv, int wk, double sec, double t[3][3],
		double obsx,double obsy, double obsz,
		float *elv, float *azi, float *dopp,
		float *erc, float *iono, float *tropo)
{
    double n,e,u,rho,dx,dy,dz,sx,sy,sz,svx,svy,svz,svirel,rhox,rhoy,
	   es,a,phu,lmu,temp,f,psi,phi,lmi,phm,phm2,phm3,suma,sumb,xtemp,
	   x2,x4,tlocal,elvrad,azirad,dp,EarthRotCorr,ic,tr;

    /* Use either the ephemeris or almanac for the prediction. */

    if(ephs[sv-1].vflg==1)
	EphemerisPrediction(sv,sec,&svirel,&sx,&sy,&sz,&svx,&svy,&svz);
    else
	AlmanacPrediction(sv,wk,sec,&sx,&sy,&sz,&svx,&svy,&svz);

    /* Convert SV XYZ to NEU in observer's local astronomic system. */

    dx = sx - obsx;
    dy = sy - obsy;
    dz = sz - obsz;

    n = t[0][0]*dx + t[0][1]*dy + t[0][2]*dz;
    e = t[1][0]*dx + t[1][1]*dy + t[1][2]*dz;
    u = t[2][0]*dx + t[2][1]*dy + t[2][2]*dz;

    /* Compute SV elevation and azimuth. */

    rho = sqrt(n*n+e*e);
    elvrad = atan2(u,rho);
    azirad = atan2(e,n);

    /* Compute SV Doppler. */

    dp = - (dx*svx+dy*svy+dz*svz)/sqrt(dx*dx+dy*dy+dz*dz)*L1/SPEED_OF_LIGHT;

    /* Compute the SV's earth rotation correction. */

    rhox = sx - obsx;
    rhoy = sy - obsy;
    EarthRotCorr = WGS84oe / SPEED_OF_LIGHT * (sy*rhox-sx*rhoy);

    /* Compute the SV's ionospheric correction. */

    es = elvrad / PI;                      /* SV elevation in semicircles. */
    a = azirad;                                  /* SV azimuth in radians. */
    PROTECT++;
    phu = CurNavState.lat / PI;       /* Receiver latitude in semicircles. */
    lmu = CurNavState.lon / PI;      /* Receiver longitude in semicircles. */
    PROTECT--;

    /* Don't compute ionospheric correction for SV's below the horizon. */

    if(es < 0.0)
    {
	ic=0;
	goto TROPCALC;
    }

    /* Use nocturnal value when ionospheric correction is unavailablEphem. */

    if(ionoutc.vflg==0)
    {
	temp = 0.53 - es;
	f = 1.0 + 16.0*temp*temp*temp;
	ic = f * 5.0e-9 * SPEED_OF_LIGHT + 0.5;
	goto TROPCALC;
    }

    /* Compute receiver's local time of day in seconds
       = GMT + 43200 seconds per semicircle of longitude. */

    tlocal = sec + SECONDS_IN_DAY/2.0*lmu + SECONDS_IN_DAY;
    while(tlocal > SECONDS_IN_DAY)
	tlocal -= SECONDS_IN_DAY;

    /* Compute slant factor f. */

    temp = 0.53 - es;
    f = 1.0 + 16.0*temp*temp*temp;

    /* Compute Earth angle psi (semicircles). */

    psi = 0.0137/(es+0.11) - 0.022;

    /* Compute subionospheric latitude phi (semicircles). */
    
    phi = phu + psi*cos(a);

    /* Limit phi to between +75 degrees and - 75 degrees. */

    if(phi>0.416)
	phi = 0.416;
    else if(phi<(-0.416))
	phi = -0.416;

    /* Compute subionospheric longitude lmi (semicircles). */

    lmi = lmu + psi*sin(a)/cos(phi*PI);

    /* Compute local time in seconds
       = GMT + 43200 seconds per semicircle of longitude */

    tlocal = sec + SECONDS_IN_DAY/2.0*lmi;
    while(tlocal >= SECONDS_IN_DAY)
	tlocal -= SECONDS_IN_DAY;
    while(tlocal < 0.0)
	tlocal += SECONDS_IN_DAY;
 
    /* Compute subionospheric geomagnetic latitude phm (semicircles). */

    phm = phi + 0.064*cos((lmi-1.617)*PI);
    phm2 = phm*phm;
    phm3 = phm2*phm;

    /* Diurnal maximum time delay: suma. Diurnal period: sumb. */

    PROTECT++;
    suma = ionoutc.a0 + ionoutc.a1*phm + ionoutc.a2*phm2 + ionoutc.a3*phm3;
    sumb = ionoutc.b0 + ionoutc.b1*phm + ionoutc.b2*phm2 + ionoutc.b3*phm3;
    PROTECT--;

    if(sumb!=0.0)
	xtemp = 2.0*PI*(tlocal-50400.0)/sumb;
    else
	xtemp = 0.0;

    if(fabs(xtemp)<1.57)
    {
	x2 = xtemp*xtemp;
	x4 = x2*x2;
	temp = 1.0 - x2/2.0 + x4/24.0;
	ic = f*(5.0e-9 + suma*temp)*SPEED_OF_LIGHT + 0.5;
    }
    else
	ic = f * 5.0e-9 * SPEED_OF_LIGHT;

TROPCALC:

    /* Calculate tropospheric correction for SV's above the horizon. */

    if(elvrad<0.0)
	tr = 0;
    else
    {
	PROTECT++;
	tr = 2.4224*exp(-0.13346e-3*CurNavState.hgt)/(0.026+sin(elvrad));
	PROTECT--;
	if(tr < 0)
	    tr = 0;
	else if (tr > 200)
	    tr = 200;
    }

    *elv = elvrad;
    *azi = azirad;
    if(*azi < 0)
	*azi += 2.0*PI;
    *dopp = dp;
    *erc = EarthRotCorr;
    *iono = ic;
    *tropo = tr;
}

/****************************************************************************    
* Function: void AlmanacPrediction(int sv, int wk, double sec,
*                                  double *x, double *y, double *z,
*                                  double *vx, double *vy, double *vz)
*
* Predictions a satellite position and velocity vector from the almanac.
*
* Input: sv - the satellite PRN number.
*        wk - the GPS week number.
*        sec - second in the GPS week.
*
* Output: x - the satellite x co-ordinate, m.
*         y - the satellite y co-ordinate, m.
*         z - the satellite z co-ordinate, m.
*         vx - the satellite x co-ordinate velocity, m/s.
*         vy- the satellite y co-ordinate velocity, m/s.
*         vz - the satellite z co-ordinate velocity, m/s.
*
* Return Value: None.
****************************************************************************/
void AlmanacPrediction(int sv, int wk, double sec,
		       double *x, double *y, double *z,
		       double *vx, double *vy, double *vz)
{
    float a,n0,tk,mk,ek,cek,sek,denom,cvk,svk,vk,pk,uk,
	  rk,ik,cuk,suk,xpk,ypk,ok,sik,cik,sok,cok,ekold;
    float  ecc,slr,tmp,xdot,ydot;

    almstruc A;

    PROTECT++;
    A = alms[sv-1];               /* Get the almanac for the SV concerned. */
    PROTECT--;

    /* Semimajor axis (m). */

    a = A.sqrta;
    a = a * a;

    /* Mean motion (rad/sec). */

    n0 = sqrt((double)(GravConstant/(a*a*a)));

    /* Compute the difference, in seconds, between the epoch and wk & sec. */

    tk = (wk-A.refweek)*SECONDS_IN_WEEK + sec - A.toa;

    /* Mean anomaly (rads). */

    mk = A.manom + n0*tk;

    /* Obtain eccentric anomaly by solving Kepler's equation. */

    ecc = A.ecc;
    ek = mk;
    ekold = ek + 1.0E0;
    while(fabs((double)(ek-ekold)) > 1.0E-13)
    {
	ekold = ek;
	ek = ekold + (mk-ekold+ecc*sin((double)ekold))
		     / (1.0E0-ecc*cos((double)ekold));
    }

    cek = cos((double)ek);
    sek = sin((double)ek);

    /* Compute the true anomaly (rads). */

    denom = 1.0E0 - ecc*cek;
    cvk = (cek-ecc)/denom;
    svk = sqrt((double)(1.0-ecc*ecc)) * sek / denom;
    vk = atan2((double)svk,(double)cvk);
    if (vk < 0.0E0)
	vk = vk + 2.0*PI;

    /* Argument of latitude (rads). */

    pk = vk + A.argpg;

    /* Corrected argument of latitude (rads). */

    uk = pk;

    /* Corrected radius (rads). */

    rk = denom * a;

    /* Corrected inclination (rads). */

    ik = A.inclin;

    cuk = cos((double)uk);
    suk = sin((double)uk);

    /* Position in the orbital plane. */

    xpk = rk*cuk;
    ypk = rk*suk;

    slr = a*(1.0 - ecc*ecc);
    tmp = sqrt((double)(GravConstant/slr));

    xdot = -tmp*suk;
    ydot = tmp*(ecc + cuk);

    /* Corrected longitude of the ascending node (rads). */

    ok = A.ratoa + tk*(A.rora-WGS84oe) - WGS84oe*A.toa;

    sik = sin((double)ik);
    cik = cos((double)ik);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -