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

📄 position.c

📁 此程序为GPS接收机的源码
💻 C
📖 第 1 页 / 共 3 页
字号:
// position.c Process pseudoranges and ephemeris into position// Copyright (C) 2005  Andrew Greenberg// Distributed under the GNU GENERAL PUBLIC LICENSE (GPL) Version 2 (June 1991).// See the "COPYING" file distributed with this software for more information.#include <cyg/kernel/kapi.h>#include <math.h>#include "position.h"#include "constants.h"#include "display.h"        // logging function#include "ephemeris.h"#include "gp4020.h"#include "gp4020_io.h"#include "log.h"#include "pseudorange.h"#include "switches.h"#include "time.h"/****************************************************************************** * Defines ******************************************************************************/// WGS-84 defines#define OMEGA_E     7.2921151467E-5  // Earth rotation rate [r/s]#define WGS84_A         6378137.0    // Earth semimajor axis [m]#define WGS84_B         6356752.3142 // Earth semiminor axis [m]// Other defines#define SQRTMU      19964981.8432    // [(m^3/2)/s] sqrt(G * M(Earth))#define F_RC -4.442807633E-10 // Relativistic correction: -2*sqrt(mu)/c^2                              // (BB p133)/****************************************************************************** * Globals ******************************************************************************/cyg_sem_t  position_semaphore;unsigned short pr2_data_fresh;// unsigned short positioning;position_t  receiver_pos;llh_t       receiver_llh;azel_t  sat_azel[N_CHANNELS];xyzt_t  sat_pos_by_ch[N_CHANNELS];// temporarily globals for debuggingsatpos_t sat_position[N_CHANNELS];double   m_rho[N_CHANNELS];/****************************************************************************** * Statics (Module variables) ******************************************************************************///static xyzt_t   rec_pos_xyz;/****************************************************************************** * Signal from pseudorange thread that there aren't enough satellites to be * calculating position. Clear things as necessary. ******************************************************************************/voidclear_position( void){    receiver_pos.positioning = 0;}/****************************************************************************** * Translate ECEF to LLH coordinates. * * Based on equations found in Hoffman-Wellinhoff ******************************************************************************/static llh_tecef_to_llh( xyz_t pos){    double p,n,thet,esq,epsq;    double a2,b2,slat,clat,sth,sth3,cth,cth3; // Save some float math.    llh_t result;    a2 = WGS84_A * WGS84_A;    b2 = WGS84_B * WGS84_B;    p = sqrt( pos.x * pos.x + pos.y * pos.y);    thet = atan( pos.z * WGS84_A / ( p * WGS84_B));    esq = 1.0 - b2 / a2;    epsq = a2 / b2 - 1.0;    sth = sin( thet);    cth = cos( thet);    sth3 = sth * sth * sth;    cth3 = cth * cth * cth;    result.lat = atan( (pos.z + epsq * WGS84_B * sth3)                        / (p - esq * WGS84_A * cth3));    result.lon = atan2( pos.y, pos.x);    clat = cos( result.lat);    slat = sin( result.lat);    n = a2 / sqrt( a2 * clat * clat + b2 * slat * slat);    result.hgt = p / clat - n;    return( result);}/****************************************************************************** * calculate_position * Given satellite locations and pseudorange measurements, return an estimated * receiver position based purely on the geometry and Earth's rotation rate. * * The initial estimated position comes from the (rec_pos_xyz) structure, the * pseduorange measurements from (m_rho), measured range, * * If the position cannot be determined, the position returned will be * <000>, the center of the Earth. *****************************************************************************/position_tcalculate_position( unsigned short nsats_used){    position_t result;    double x, y, z, b;  // estimated receiver position and clock bias    double alpha;       // Angle of Earth rotation during signal transit    //double sa,ca;       // Sin( alpha), Cos( alpha)    double e_rho;       // Estimated Range    unsigned short i, j, k; // indices    // matrix declarations    // (Is it smart to reserve N_CHANNELS when we need (nsats_used)?    //  Since there's only one instance maybe these should be globals?)    double delrho[N_CHANNELS]; // vector of per-sat. estimated range error    double A[N_CHANNELS][3];   // linearized relation of position to pseudorange    double inv[4][4];          // inverse of matrix (a[i,j] == Transpose[A].A)    double delx[4];            // incremental position correction    double  a00, a01, a02, a03,  // a[i,j], intermediate matrix for                 a11, a12, a13,  // generalized inverse calculation.                      a22, a23,  // Only 10 elements due to symmetry.                           a33;  // Don't loop, so no indexing.    double det; // matrix determinate#if 0    const char idx[4][4] = // For symmetric, indexed matrices such as inv[]        {   {0,1,2,3},     //  we store only their upper triangle.            {1,4,5,6},     // Normal indexed access is possible like so:            {2,5,7,8},     //   a[i][j] => a[idx[i][j]]            {3,6,8,9}        }    // This is not clearly better. It's probably faster to copy the 6 elements    // over and save the indirect look-up in the inner loop    // (about (16 * nsats_used) look-ups).#endif    double dx, dy, dz;          // vector from receiver to satellite (delx)    xyz_t  satxyz[N_CHANNELS];  // sat position in ECEF at time of reception    unsigned short nits = 0;    // Number of ITerationS    double         error = 1000;        // residual calculation error    unsigned short singular = 0;        // flag for matrix inversion    result.valid = 0;    b = 0.0;  // [m] local estimate of clock bias, initially zero             // Note, clock bias is defined so that:            //     measured_time == true_time + clock_bias//    nsats_used  = 4;    // make local copy of current position estimate (a speed optimization?)    x = HERE_X;    y = HERE_Y;    z = HERE_Z;//     x = rec_pos_xyz.x;//     y = rec_pos_xyz.y;//     z = rec_pos_xyz.z;    for( i = 0; i < nsats_used; i++)    {        // The instantaneous origin of a satellite's transmission, though fixed        // in inertial space, nevertheless varies with time in ECEF coordinates        // due to Earth's rotation. Here we find the position of each satellite        // in ECEF at the moment our receiver latched its signal.        // The time-delay used here is based directly on the measured        // time-difference. Perhaps some sort of filtering should be used.        // If a variation of this calculation were included in the iteration,        // more accuracy could be gained at some added computational expense.        // Note that we may want to correct for the clock bias here, but        // perhaps it's better if that's already folded into m_rho by        // the time we get here.        // alpha is the angular rotation of the earth since the signal left        // satellite[i]. [radians]        alpha = m_rho[i] * OMEGA_E / SPEED_OF_LIGHT;        // Compute the change in satellite position during signal propagation.        // Exact relations:        //   sa = sin( alpha);        //   ca = cos( alpha);        //   dx = (sat_position[i].x * ca - sat_position[i].y * sa) - x;        //   dy = (sat_position[i].y * ca + sat_position[i].x * sa) - y;        //   dz = sat_position[i].z - z;        // Make the small angle approximation        //   cos( alpha) ~= 1 and sin( alpha) ~= alpha.        satxyz[i].x = sat_position[i].x + sat_position[i].y * alpha;        satxyz[i].y = sat_position[i].y - sat_position[i].x * alpha;        satxyz[i].z = sat_position[i].z;        // TODO, check the error in this approximation.    }/************************************** * Explanation of the iterative method: * * We make measurements of the time of flight of satellite signals to the * receiver (delta-t). From this we calculate a distance known as a pseudo- * range. The pseudorange differs from the true distance because of atmospheric * delay, receiver clock error, and other smaller effects. The error sources * other than clock error are dealt with elsewhere. The precise clock error can * only be found during this position calculation unless an external and very * accurate time source is used, or the carrier "integer ambiguity" can be * resolved. Since neither of the latter is usually the case, we solve for the * receiver "clock bias" as part of this position calculation. To be precise, * We define our pseudorange to be: * *   rho[i] == sqrt( (sx[i]-x)^2 + (sy[i]-y)^2 + (sz[i]-z)^2) + b * * Where (rho[i]) is the pseudorange to the ith satellite, (<sx,sy,sz>[i]) are * the ECEF (Earth Centered Earth Fixed) rectangular coordinates of the ith * satellite which are known from orbital calculations based on the local time * and ephemeris data, and (<xyz>) is the current estimate of the receiver * position in ECEF coordinates, (b)[meters] is the remaining clock-error * (bias) after performing all relevant corrections, and (^2) means to square * the quantity in parenthesis. * * By differentiation of (rho), a linear relation can be found between a change * in receiver position (delx), and the change in pseudorange (delrho). * Written as a matrix, this relation can be inverted and the receiver position * correction (delx) found.  Though approximate, the linearized process can * be iterated until a sufficiently accurate position is found. * * The linear relation in matrix form can be written: * *   delrho == A . delx * * Where (delrho) is a column vector representing the change in pseudoranges * resulting from a change in receiver position vector (delx), and (A) is * the matrix expressing the linear relation. * * To calculate a receiver position correction, first calculate the * pseudoranges based on the estimated receiver position and the known satellite * positions, call this (e_rho), and subtract this from the measured * pseudoranges: * *   delrho = m_rho - e_rho * * Knowing (delrho) and (A) the correction (delx) can be solved for, and * the corrected estimate of position can then be found: * *   (corrected-x) = (previous-x) + delx * * In the iterative method, (corrected-x) is used as the new value of the * estimated receiver position, and the whole correction process repeated. * Iteration is successful when the size of the correction is sufficiently small. * **************************************/    do    {   // Iterate until an accurate solution is found        // Use some locals to avoid re-computing terms.        // The names somewhat indicate the terms contained.        double a01a33, a02a02, a12a23, a13a13a22,            a03a03_a00a33, a02a12_a01a22, a02a13_a01a23, a12a13_a11a23;        for( i = 0; i < nsats_used; i++)        {            // Working in the ECEF (Earth Centered Earth Fixed) frame, find the            // difference between the position of satellite[i] and the            // receiver's estimated position at the time the signal was            // received.            dx = x - satxyz[i].x;            dy = y - satxyz[i].y;            dz = z - satxyz[i].z;

⌨️ 快捷键说明

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