C# 利用GPS广播星历文件实现任意时刻任意卫星位置计算(WGS-84坐标系)

编写C#桌面窗体,通过任意日期的GPS广播星历文件,计算任意时刻任意卫星的位置。

运行环境:Visual Studio 2022,.NET6.0,我的Visual Studio 2019无法正常运行该程序。


一、程序演示

GPS广播星历文件计算卫星位置程序演示视频

二、数据获取

1.下载GPS广播星历文件

网址:武汉大学IGS数据中心 (gnsswhu.cn)

我下载的是2024-04-23的GPS广播星历文件

2.解压文件,更改文件后缀为txt

3.广播星历文件的格式说明

下图中许多参数在之后的公式中会用到

注意文件有固定格式,记住每八行为一组数据,这很重要。

三、数学公式(编写多个函数)

需要注意:

参考时刻是卫星广播星历文件中的时刻

观测时刻可以是任意时刻,即所计算的时刻

该程序存在不足:默认t_{oc}=t_{oe}

可以根据需要自行编写t_{oc}t_{oe}的转换代码。

1.计算卫星运动的平均角速度n  

参考时刻t_{oe}的卫星平均角速度n_0=\sqrt{\frac{GM}{A^{3}} }

观测时刻t卫星的平均角速度n=n_0+\bigtriangleup n

\bigtriangleup n(rad/s)——卫星平均角速度的改正值(摄动参数)

GM=3.986005\times 10^{14}m^{3}/s^{2}为万有引力常数G与地球总质量M之积

\sqrt{A}   ——t_{oe}时的轨道长半径平方根

2.计算观测时刻卫星的平近点角M_{s}

M_{s}=M_{0}+n(t-t_{oe})

M_{0}—— t_{oe}时的平近点角

3.计算偏近点角E_{s},

用弧度表示的开普勒方程:E_{s}=M_{s}+esinE_{s}

e——t_{oe}时的轨道偏心率

迭代法求解E_{s},令E_{s}=M_{s}代入公式,求出E_{s}后再代入。由于轨道偏心率e很小,迭代收敛很快

迭代法代码:

   do
   {
       double newE = Ms + e * Math.Sin(Es);
       if (Math.Abs(newE - Es) < precision) // 检查收敛性  
       {
           break; // 如果收敛,跳出循环  
       }
       Es = newE; // 更新E的值  
   } while (true); // 无限循环,直到满足条件跳出  

4.计算真近点角f_{s}

f_{s}=arctan\frac{\sqrt{1-e_{2}}sinE_{s}}{cosE_{s}-e}

5.计算升交角距u_{0}

u_{0}=\omega +f_{s}

\omega——t_{oe}时的近地点角距

6.对升交角距u、卫星矢径r、卫星轨道倾角i进行摄动改正

7.计算观测时刻升交点的经度L

L=\Omega_0+(\dot{\Omega }-\omega_e)t-\dot{\Omega }t_{oe}

8.计算卫星在轨道平面坐标系中的位置

9.计算卫星在(瞬时地球)WGS-84坐标系中的位置

\begin{bmatrix} X\\ Y \\ Z \end{bmatrix}=\begin{bmatrix} xcosL-ycosisinL\\ xcosL+ycosisinL\\ ysini \end{bmatrix}

四、算法实现

如果根据指定日期指定时刻指定卫星的广播星历计算卫星位置,理清思路后,并不难,就是有些麻烦,而且一不留意就容易出错,需要一直很仔细的编写代码。

如果要根据任意日期的GPS广播星历文件,计算任意时刻、任意编号卫星的位置的话,难度有点大。

1.算法思路

这是我编写时的思路。

(1)搭建窗体

(2)在广播星历文件中先截取6号卫星,固定时刻16时的8行数据放入新的txt文本文件,

(16时的6号卫星只是图个吉利。可以自行选取。),计算时刻为15:10:26。

个人感觉观测时刻参考时刻越近计算位置结果越精确。

(3)研究提取出来的八行数据的结构,新建SatellitePosition.cs类文件,在里面编写函数读取文件,遍历文件储存于数组,提取数据等多个函数,并用在Form.cs,RichTextBox控件呈现文件的内容。

在读取文件编写数据时,我先实现把地址写入代码读取文件,成功后,才尝试通过窗体Button打开文件的方式读取文件。

读取文件时,应当注意参数后面D-09等科学计数法的处理。需要用到正则表达式。

(4)编写多个函数用于计算卫星位置,上面数学公式,每一步编写一个函数,共计9个函数进行计算。计算时需要调用上一步编写的函数提取广播星历文件中参数。

因为计算函数需要用到之前的计算结果。

在实际运算中,为方便写出代码(由简单到困难),某些ComBox读取的时间等参数先写死在代码里,在运行成功后,为方便调试,又改为写死状态。

每写完一个函数,最好运行检查一下,看是否出错。可以将运算结果通过TextBox或MessageBox呈现出来。

(5)在Form.cs中调用SatellitePosition.cs中所有的与计算有关的函数。计算出15:10:26时6号卫星在WGS-84坐标系中的位置。把所有写死的数据改活。


上面已经实现算法最基本的计算功能。

读取八行数据的文本文件后,计算指定卫星,指定时刻,任意观测时间的卫星坐标。

观测时刻参考时刻越近计算位置结果越精确。因此如果输入的观测时间与指定时刻差距过大,结果会不精确。

接下来需要实现实现筛选功能。

读取任意广播星历文件,选择任意卫星,输入任意时刻,计算卫星位置。

我是单独实现筛选功能后,再与上面的计算功能连接在一起实现程序的编写。


(6)实现根据下拉框中选择的时间,在完整的广播星历文件中检索离所选取时间最近的时刻,并且显示到RichTextBox控件中。

原理是如果ComBox所选的时间为单数A,则检索文件中A+1时刻的数据,以八行作为一个模块,把所有数据写入列表。最后返回结果为数组。

(7)实现根据下拉框里选择的卫星编号,检索上一步返回的数组中的数据,得到卫星编号与下拉框中的编号一致的特定行,并将该行所在的八行数据写入列表。结果返回数组。最终RichTextBox控件只会显示八行数据。

(8)更改之前(3)中的代码,从文本中读取改为从(7)的返回数组中读取。

(9)编写函数,根据广播星历文件的日期计算该日是所在周的第几天。

 public int GetDayOfWeekInWeek(string[] timeParts)
 {
     // 解析年份
     int year = 2000 + int.Parse(timeParts[1]);
     int month = int.Parse(timeParts[2]);
     int day = int.Parse(timeParts[3]);

     // 构造DateTime对象
     DateTime date = new DateTime(year, month, day);

     // 获取给定日期所在周的第一天
     DayOfWeek firstDayOfWeek = DayOfWeek.Sunday;

     // 获取给定日期是该周的第几天
     int dayOfWeek = (int)date.DayOfWeek - (int)firstDayOfWeek;
     if (dayOfWeek < 0)
     {
         // 将周天(默认为0)移到末尾
         dayOfWeek += 7;
     }
     // 加1是为了将周天作为一周的第一天
     dayOfWeek += 1;
     days = dayOfWeek;
    return days;
 }

2.具体代码

代码仍存在不足之处,会在整理完善后上传

3.不足之处

(1)默认toc=toe;

(2)只能根据公元2000年后的GPS广播星历文件计算卫星位置。

在计算周内秒时(周日为一周的第一天),根据计算日期所在周第几天的函数代码为2000+广播星历文件提取出的日期(int year = 2000 + int.Parse(timeParts[1]);),因此只能利用公元2000-2999年的广播星历文件计算卫星位置。

(3)由于广播星历文件的卫星时刻会是1时59等非整数时刻,在筛选最近时刻时存在误差。

可以通过在检索时间的同时,添加条件:检索到单数与文件中时刻一样时,以单数时刻为准,而不是单数加一后的双数时刻。

相关推荐

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-05-02 14:48:01       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-05-02 14:48:01       101 阅读
  3. 在Django里面运行非项目文件

    2024-05-02 14:48:01       82 阅读
  4. Python语言-面向对象

    2024-05-02 14:48:01       91 阅读

热门阅读

  1. 详解podman

    2024-05-02 14:48:01       30 阅读
  2. 004 springCloudAlibaba Gateway

    2024-05-02 14:48:01       26 阅读
  3. apache DbUtils 组件核心原理与应用

    2024-05-02 14:48:01       32 阅读
  4. Qt | QLabel 类(标签)

    2024-05-02 14:48:01       31 阅读
  5. 【Qt问题】Qt Creator 如何链接第三方库

    2024-05-02 14:48:01       35 阅读
  6. 编程一定要学好汉语,英语是次要的

    2024-05-02 14:48:01       32 阅读
  7. Linux驱动开发——(八)Linux异步通知

    2024-05-02 14:48:01       42 阅读
  8. 购物网站-批发

    2024-05-02 14:48:01       30 阅读
  9. Rust入门

    2024-05-02 14:48:01       31 阅读