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

📄 nav.c

📁 GPS导航定位程序
💻 C
📖 第 1 页 / 共 4 页
字号:
* Function: int ObservedMinusPredicted(int SV, unsigned long obsTIC,
*                                      navstatestruc NavState,
*                                      pseudostruc *pseudo,
*                                      double *OMPrange, double *OMPrrate,
*                                      double *OMPicp, double lmnr[4])
*
* Calculates the following quantities for the navigation solution: observed
* minus predicted values for range, range rate and the integrated carrier
* phase as a range, plus the direction cosines to the satellites and the
* differerential corrections to the range and range rate (if available).
*
* Input:  SV - The satellite being processed.
*         obsTIC - Time of the observation (TIC).
*         NavState - current observer position.
*
* Output: pseudo - pointer to the struct of pseudo-range data and corrections.
*         OMPrange - pointer to the Observed minus predicted range.
*         OMPrrate - pointer to the Observed minus predicted range rate.
*         OMPicp - pointer to the Observed minus predicted ICP as range.
*         lmnr - Observer-satellite direction cosines.
*
* Return Value: TRUE - All data was good.
*               FALSE - The differential correction data was bad.
****************************************************************************/
int ObservedMinusPredicted(int SV, unsigned long obsTIC,
			   navstatestruc NavState, pseudostruc *pseudo,
			   double *OMPrange, double *OMPrrate,
			   double *OMPicp, double lmnr[4])
{
    int observation_week;                      /* GPS week of observation. */
    int iod;                         /* IOD of the current ephemeris data. */

    double sx,sy,sz;                     /* Satellite ECEF psoiton vector. */
    double svx,svy,svz;                 /* Satellite ECEF velocity vector. */
    double dx,dy,dz;                      /* Observer to satellite vector. */
    double range;                                      /* Satellite range. */
    double relativistic;                   /* SV Relavtivistic correction. */
    double clock_correction;                       /* SV clock correction. */
    double relative_velocity;            /* SV-Observer relative velocity. */
    double propagation_delay;           /* Total signal propagation delay. */

    double observation_second;                     /* Time of observation. */
    double transmission_second;                   /* Time of transmission. */
    double delta_time;          /* Time between observation and ephemeris. */
    double SV_delta_frequency;               /* SV clock frequency offset. */
    double SV_delta_time;                        /* SV clock time offsets. */

    ephstruc E;                      /* Satellite ephemeris data structure */
	
    /* Make a local copy of the ephemeris data for the SV in question. */

    PROTECT++;      
    E = ephs[SV-1];
    PROTECT--;

    /* GPS time of the observation. */

    TICToGpsTime(obsTIC,&observation_week,&observation_second);

    /* SV position at time of the pseudorange observation. */

    EphemerisPrediction(SV,observation_second,
			&relativistic,&sx,&sy,&sz,&svx,&svy,&svz);
 
    /* Observer to satellite vector and the satellite range. */

    dx = sx - NavState.x;
    dy = sy - NavState.y;
    dz = sz - NavState.z;
    range = sqrt(dx*dx + dy*dy + dz*dz);

    /* SV position at time signal was transmitted. */

    transmission_second = observation_second - range/SPEED_OF_LIGHT;
    if(transmission_second < 0.0)
	transmission_second += SECONDS_IN_WEEK;

    EphemerisPrediction(SV,transmission_second,
			&relativistic,&sx,&sy,&sz,&svx,&svy,&svz);

    /* New observer to satellite vector and satellite range. */

    dx = sx - NavState.x;
    dy = sy - NavState.y;
    dz = sz - NavState.z;
    range = sqrt(dx*dx + dy*dy + dz*dz);

    lmnr[0] = dx/range;                              /* Direction cosines. */
    lmnr[1] = dy/range;
    lmnr[2] = dz/range;
    lmnr[3] = range;

    iod = E.iode;                             /* Issue of data being used. */

    /* Time between transmission and ephemeris validty. */

    delta_time = transmission_second - E.toc;

    if(delta_time > SECONDS_IN_WEEK/2.0)
	delta_time -= SECONDS_IN_WEEK;
    else if (delta_time < -SECONDS_IN_WEEK/2.0)
	delta_time += SECONDS_IN_WEEK;

    /* Satellite clock frequency and time correction at transmission. */

    SV_delta_frequency = E.af1 + 2.0*delta_time*E.af2;  
    SV_delta_time = E.af0 + delta_time*(E.af1 + delta_time*E.af2)
		    + relativistic;  

    /* Total clock correction term (m). */

    clock_correction = SPEED_OF_LIGHT*(SV_delta_time - E.tgd);

    /* Total propagation delay. */

    propagation_delay = range + sverc[SV-1] - clock_correction;

    /* Observed minus predicted range. */

    *OMPrange = pseudo->range - propagation_delay; 

    /* Compute the predicted relative velocity of SV and receiver */

    relative_velocity = (svx-NavState.velx)*lmnr[0]
	     + (svy-NavState.vely)*lmnr[1]
	     + (svz-NavState.velz)*lmnr[2];

    /* Observed minus predicted range rate. */

    *OMPrrate = pseudo->range_rate - relative_velocity
	      + SV_delta_frequency*SPEED_OF_LIGHT + NavState.clockdrift;

    /* Observed minus predicted integrated carrier phase range. */

    *OMPicp = pseudo->icp_range - propagation_delay;

    /* See if there are valid differential corrections available for this
       measurement block. */

    {
	double dt, dt2;   /* Delta time & double delta time btwn obs & MZ. */

	beacstruc B;

	/* Make a local copy of the DGPS beacon data structure. */

	PROTECT++;      
	B = BEAC;
	PROTECT--;

	pseudo->differential_range_correction = NO_DGPS;
	pseudo->differential_range_rate_correction = NO_DGPS;
    
	if(B.sig && B.data && B.hlth!=7 && B.DC[SV-1].vflg==TRUE)
	{
	    if(B.DC[SV-1].dontuse==FALSE)         /* Check don't use flag. */
	    {
		dt = MZDifference(observation_second,B.DC[SV-1].mzcount);

		/* Don't use if DGPS data older than 60 seconds. */

		if(fabs(dt)<=60.0)
		{
		    if(B.DC[SV-1].iod==iod)
		    {
			pseudo->differential_range_rate_correction = 
							      B.DC[SV-1].rrc;
			pseudo->differential_range_correction = 
			       B.DC[SV-1].prc + 
			       dt*pseudo->differential_range_rate_correction;
		    }
		    else if(B.DDC[SV-1].iod==iod && B.DDC[SV-1].vflg==TRUE)
		    {
			dt2 = MZDifference(observation_second,
							B.DDC[SV-1].mzcount);

			if(fabs(dt)<=120.0)
			{
			    pseudo->differential_range_rate_correction = 
					   B.DC[SV-1].rrc + B.DDC[SV-1].drrc;
			    pseudo->differential_range_correction = 
				      B.DC[SV-1].prc + B.DDC[SV-1].dprc +
				      dt*B.DC[SV-1].rrc + dt2*B.DDC[SV-1].drrc;
			}
		    }                                   /* IODs don't match. */
		}                              /* dt larger than 60 seconds. */
	    }                                             /* Don't use data. */
	}                                              /* No data available. */
  
	/* Don't use corrections greater in magnitude than 1000 meters
	   (range) or 100 meters/sec (range rate). */

	if(fabs(pseudo->differential_range_correction)>1000.0)
	    pseudo->differential_range_correction = NO_DGPS;
	if(fabs(pseudo->differential_range_rate_correction)>100.0)
	    pseudo->differential_range_rate_correction = NO_DGPS;

	/* If we are receiving RTCM-104 differential corrections inputs,
	   omit any satellites which do not have a correction. */

	if(B.sig && B.data && (B.hlth<7))
	{
	    if(pseudo->differential_range_correction>1000.0)
	    {
		WarningMessage("Differential Correction invalid in "
			       "ObservedMinusPredicted");
		return(FALSE);
	    }
	}
    }
    return(TRUE);
}

/****************************************************************************    
*
* Function: double MZDifference(double gsec, int mzcount)
*
* Gets the difference in seconds between an RTCM-104 modified Z count and a
* specified GPS time. The assumption is that the Z count (which is modulo
* 3600 seconds) is within +/- 1/2 hour of the specified GPS time.                                                             
*
* Input:  gps_second - GPS time of week, seconds
*         mzcount - modified Z count from RTCM-104 message
*
* Output: None.
*
* Return Value: Difference between GPS time and mzcount.
****************************************************************************/
double MZDifference(double gps_second, int mzcount)
{
    double time_difference;

    time_difference = fmod(gps_second,SECONDS_IN_HOUR) 
		      - mzcount*SECONDS_PER_MZCOUNT;

    if(time_difference>SECONDS_IN_HALF_HOUR)
	time_difference-= SECONDS_IN_HOUR;
    else if(time_difference<-SECONDS_IN_HALF_HOUR)
	time_difference += SECONDS_IN_HOUR;

    return(time_difference);
}

/****************************************************************************    
*
* Function: int BuildNavMat(double solution_matrix[MAXCHANNELS][4],
*                           navstatestruc *NewNavState, ompstruc *omp)
*                       
* Gets the navigation matrix - the product of the covarince matrix and the
* solution matrix.
*
* Input: solution_matrix - the direction cosines to the satellites.
*        NewNavState - pointer to the navigation state structure.
*        omp - pointer to the observed minus predicted range/range-rate.
*
* Output: NewNavState - update for the navigation matrix.
*
* Return Value: FALSE - GDOP big or inverse covariance matrix singular.
*               TRUE - GDOP and inverse covariance matrix good.
****************************************************************************/
int BuildNavMat(double solution_matrix[MAXCHANNELS][4],
		navstatestruc *NewNavState, ompstruc *omp)
{
    double inverse_covariance_matrix[4][4];
    
    /* If there are only 3 satellites in the solution then use altitude
       aiding for 2D fix. */

    if(NumSatsInSoln==3 && AltitudeAided)
	AltitudeAiding(NewNavState,omp,solution_matrix);

    /* Get the inverse of the covariance matrix and check if it's singular.
       If the singularity can't be corrected by applying altitude aiding then
       return because a navigation solution can't be calculated */

    if(GetInvCovMat(NewNavState,omp,solution_matrix,
		    inverse_covariance_matrix)==SINGULAR)
	return(FALSE);

    /* Build navigation matrix from the inverted covariance matrix and the
       solution matrix. Multiply this matrix by the observed-predicted
       pseudoranges vector to get the XYZT navigation update.  The same
       navigation matrix also works to give velocity updates from the
       observed-predicted pseudorange rate errors. */

    GetNavMat(NewNavState,solution_matrix,inverse_covariance_matrix);

    CalcDOPS(NewNavState);

    /* Check for acceptable GDOP. If GDOP is too big, try augmenting the
       nav matrix before giving up. */

    if(NewNavState->gdop>GdopMask && NewNavState->altitude_aiding==NO &&
       AltitudeAided)
    {
	AltitudeAiding(NewNavState,omp,solution_matrix);
	if(GetInvCovMat(NewNavState,omp,solution_matrix,
			inverse_covariance_matrix)==SINGULAR)
	    return(FALSE);

	GetNavMat(NewNavState,solution_matrix,inverse_covariance_matrix);
	CalcDOPS(NewNavState);
    }
    return(TRUE);
}                              

/****************************************************************************    
*
* Function: void AltitudeAiding(navstatestruc *NewNavState,ompstruc *omp,
*                               double solution_matrix[MAXCHANNELS][4])
*
* Adds a fictitious pseudo-range to the solution matrix to enable altitude
* aiding.
*
* Input: *NewNavState - Current observer position.
*        *omp - Observed minus predicted range/range-rate.
*
* Output: solution_matrix - the direction cosines to the satellites.
*
* Return Value: None.
****************************************************************************/
void AltitudeAiding(navstatestruc *NewNavState,ompstruc *omp,
		      double solution_matrix[MAXCHANNELS][4])
{
    double dx,dy,dz;                      /* Observer to satellite vector. */
    double range;                                      /* Satellite range. */

    NewNavState->altitude_aiding = YES;

    /* Do altitude aiding assuming a given WGS-84 ellipsoid height by
       creating a fictitious satellite at the center of the earth and
       determining the equivalent pseudorange. */

    dx = -NewNavState->x;
    dy = -NewNavState->y;
    dz = -NewNavState->z;
    range = sqrt(dx*dx + dy*dy + dz*dz);

    omp->range[NumSatsInSoln] = 0.0;
    omp->range_rate[NumSatsInSoln] = 0.0;
 
    /* Direction cosines of fictitious satellite. */

    solution_matrix[NumSatsInSoln][0] = dx/range;

⌨️ 快捷键说明

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