1 概述
在用GPS信号进行导航定位以与制订观测计划时,都必须已知GPS卫星在空间的瞬间位置。卫星位置的计算是根据卫星电文所提供的轨道参数按一定的公式计算的。本节专门讲解观测瞬间GPS卫星在地固坐标系中坐标的计算方法。
2 卫星位置的计算
1. 计算卫星运行的平均角速度n
根据开普勒第三定律,卫星运行的平均角速度n0可以用下式计算:
式中μ为WGS-84坐标系中的地球引力常数,且μ=3.986005×1014m3/s2。平均角速度n0加上卫星电文给出的摄动改正数Δn,便得到卫星运行的平均角速度n
n=n0+Δn (4-12)
2. 计算归化时间tk
首先对观测时刻t′作卫星钟差改正
t=t′-Δt
然后对观测时刻t归化到GPS时系
tk=t-toc (4-13)
式中tk称作相对于参考时刻toe的归化时间(读者注意:toc≠toe)。
3. 观测时刻卫星平近点角Mk的计算
Mk=M0+ntk (4-14)
式中M0是卫星电文给出的参考时刻toe的平近点角。
4. 计算偏近点角Ek
Ek=Mk+esinEk(Ek,Mk以弧度计) (4-15)
上述方程可用迭代法进行解算,即先令Ek=Mk,代入上式,求出Ek再代入上式计算,因为GPS卫星轨道的偏心率e很小,因此收敛快,只需迭代计算两次便可求得偏近点角Ek。
5. 真近点角Vk的计算
由于:
因此:
6.升交距角Φk的计算
ω为卫星电文给出的近地点角距。
7. 摄动改正项δu,δr,δi的计算
δu,δr,δi分别为升交距角u的摄动量,卫星矢径r的摄动量和轨道倾角i的摄动量。
8. 计算经过摄动改正的升交距角uk、卫星矢径rk和轨道倾角ik
9. 计算卫星在轨道平面坐标系的坐标
卫星在轨道平面直角坐标系(X轴指向升交点)中的坐标为
10. 观测时刻升交点经度Ωk的计算
升交点经度Ωk等于观测时刻升交点赤经Ω(春分点和升交点之间的角距)与格林泥治视恒星时GAST(春分点和格林尼治起始子午线之间的角距)之差,
Ωk=Ω-GAST (4-23)
又因为:
(4-24)
其中Ωoe为参与时刻toe的升交点的赤经;
是升交点赤经的变化率,卫星电文每小时更新一次Ω和toe。
此外,卫星电文中提供了一周的开始时刻tw的格林尼治视恒星时GASTw。由于地球自转作用,GAST不断增加,所以:
GAST=GASTw+ωet (4-25)
式中ωe=7.29211567×10-5rad/s为地球自转的速率;t为观测时刻。
由式(4-24)和(4-25),得:
由(4-13)式,得:
其中
,、、的值可从卫星电文中获取。
11. 计算卫星在地心固定坐标系中的直角坐标
把卫星在轨道平面直角坐标系中的坐标进行旋转变换,可得出卫星在地心固定坐标系中的三维坐标:
12. 卫星在协议地球坐标系中的坐标计算
考虑极移的影响,卫星在协议地球坐标系中的坐标为
利用C语言程序实现
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <math.h>
#define u 3.986004418e+14
#define WE 7.292115e-6
struct canshu
{
int prn, nian, yue, ri, shi, fen;//卫星PRN号,年,月,日,时,分
double miao;//秒
long double adoe, a0, a1, a2, mo, dn, e, ga, pio, io, w, pid, ii, cuc, cus, cue, crs, crc, cis, cic, toe, aodc, wn;
/*参数说明:ADOE值,a0 卫星钟偏差, a1 卫星钟漂移, a2 卫星钟频率漂移, M0 平近点角, Δn平运动差, e偏心率, a1/2半长轴的平方根, Ω0 轨道平面升交点经度,
i0 倾角, ω近地点角距, *Ω升交点速率, IDot 倾角速率, Cuc Cus 升交角距的摄动改正项, Crc Crs 地心距的摄动改正项, Cic Cis 倾角的摄动改正项,
toe 参考历元*/
};
void wxzbjx(struct canshu *pt)
{
long double a, n0, n, t, tk, toc, mk, ek, vk, fik, uk, rk, ik;
long double xk, yk ,zk, lk;
long double XK, YK, ZK;
int temp;
pt->nian = pt->nian + 2000;
t = (long double)(((pt ->nian)- 1980) * 365 * 24 * 3600 + (pt ->yue - 1) * 30 * 24 * 3600 + pt ->ri
* 24 * 3600 + pt->shi * 3600 + pt ->miao);
a = pt ->ga * pt ->ga;
n0 = sqrt(WE/(a*a*a));//平均角速度n0
n = n0 + pt ->dn;
tk = t - pt ->toe;
toc = pt ->a0 + pt ->a1 * (t - pt ->toe) + pt ->a2 * (t - pt->toe) * (t - pt ->toe);
tk = tk - pt ->toe;
mk = pt ->mo + n * tk;
ek = mk;
for(temp=0;temp<10;temp++)
{
ek=mk+ pt ->e * sin(ek);//利用迭代法求偏近点角ek
}
vk = 2 * atan(sqrt((1+ pt ->e) / (1 - pt ->e))* (tan(ek)) / 2 );
fik = vk + pt ->w;
uk = fik + pt ->cuc * cos(2* fik) + pt ->cus * sin(2*fik);
rk = pt ->ga * pt ->ga * (1 - pt ->e * ek) + pt ->crc * cos(2* fik) + pt ->crs * sin(2*fik);
ik = pt ->io + pt ->cic * cos(2 * fik) + pt ->cis * sin(2* fik) + pt ->ii * tk;
xk = rk * cos(uk);
yk = rk * sin(uk);
zk = 0;
lk = pt ->pio + (pt ->pid - WE) * tk - WE * pt->toe;
XK = xk * cos(lk) - yk * cos(ik) * sin(lk);
YK = xk * sin(lk) + yk * cos(ik) * cos(lk);
ZK = yk * sin(ik);
printf("\n%d年%d月%d号%d时%.2f秒 %d号卫星的坐标:", pt->nian, pt->yue ,pt->ri , pt->shi ,pt->miao, pt->prn);
printf("\nXk = %.9f\nYk= %.9f\nZK = %.9f\n\n", XK, YK, ZK);
}
int main(void)
{
FILE *fp, *fp1, *fp2;
struct canshu a;
int i=0, hanhao = 1;
long double temp1, temp2, temp3, temp5, temp4, temp6, temp7;
char ch, ch1;
if((fp1 = fopen("E:\\星历文件\\guangboxingli2.txt", "r")) == NULL)//请自定义星历文件位置与名称
{
printf("文件无法打开!");
exit(0);
}
else
{
if((fp2 = fopen("E:\\星历文件\\guangboxingli2fu.txt", "w")) == NULL)
{
printf("文件无法打开!");
exit(0);
}
else
{
while((ch1 = fgetc(fp1)) != EOF)
{
if(ch1 == '\n')
{
i ++;
}
putchar(ch1);
if(i == 15)
{
break;
}
}
while(!feof(fp1))
{
ch1=fgetc(fp1);
if(ch1 == 'D')
{
ch1 = 'e';
}
fputc(ch1,fp2);
}
fclose(fp1);
}
fclose(fp2);
}
printf("以上是星历文件的头文件!\n");
system("pause");
printf("读取文件参数数据\n!");
if((fp = fopen("E:\\星历文件\\guangboxingli2fu.txt", "r")) == NULL)//创建计算结果文档
{
printf("文件无法打开!");
exit(0);
}
while(!feof(fp))
{
switch(hanhao)
{
case 1:
{
fscanf(fp,"\n%d%d%d%d%d%d%lf %le %le %le", &a.prn, &a.nian, &a.yue, &a.ri, &a.shi,
&a.fen, &a.miao, &a.a0, &a.a1, &a.a2);
printf("%d %d %d %d %d %d %lf %le %le %le", a.prn, a.nian, a.yue, a.ri, a.shi,
a.fen, a.miao, a.a0, a.a1, a.a2);
hanhao++;
}
case 2:
{
fscanf(fp,"%le %le %le %le", &a.adoe, &a.crs, &a.dn, &a.mo);
printf("\n%le %le %le %le", a.adoe, a.crs, a.dn, a.mo);
hanhao++;
}
case 3:
{
fscanf(fp,"%le %le %le %le", &a.cue, &a.e, &a.cus, &a.ga);
printf("\n%le %le %le %le", a.cue, a.e, a.cus, a.ga);
hanhao++;
}
case 4:
{
fscanf(fp,"%le %le %le %le", &a.toe, &a.cic, &a.pio, &a.cis);
printf("\n%le %le %le %le", a.toe, a.cic, a.pio, a.cis);
hanhao++;
}
case 5:
{
fscanf(fp,"%le %le %le %le", &a.io, &a.crc, &a.w, &a.pid);
printf("\n%le %le %le %le", a.io, a.crc, a.w, a.pid);
hanhao++;
}
case 6:
{
fscanf(fp,"%le %le %le %le", &a.ii, &temp1, &a.wn, &temp2);
printf("\n%le %le %le %le", a.ii, temp1, a.wn, temp2);
hanhao++;
}
case 7:
{
fscanf(fp,"%le %le %le %le", &temp3, &temp4, &temp5, &a.aodc);
printf("\n%le %le %le %le", temp3, temp1, temp5, a.aodc);
hanhao++;
}
case 8:
{
fscanf(fp,"%le", &temp6);
printf("\n%le", temp6);
if((ch=fgetc(fp)) != '\n')
{
fscanf(fp,"%le", &temp7);
printf(" %le\n", temp7);
}
}
}
wxzbjx(&a);
system("pause");
hanhao = 1;
}
fclose(fp);
return 0;
}