由广播星历计算GNSS卫星坐标
前言
本文是一个简单的由广播星历计算GNSS卫星坐标的程序,可以作为一个仅用于计算坐标的程序使用,先将初始版码在这里,之后会对该程序进行一些优化。
附:这篇文章主要是为了梳理自己的一些想法、思路,高手忽略~不过里面有一些细节问题可能可以给大家带来一些帮助。
注:但是发现了一个很麻烦的情况,就是不管怎么算,都会出现几个数超过了10m的误差,之后好好回想了一下,个人感觉可能是时间参数出了一点点问题,因为程序中没有用到时间改正模型,但是由于GNSS结课后本人就把相关文件都清空了,调试起来比较麻烦,感兴趣的朋友自己试试吧!
读取文件
计算卫星坐标的第一步是获取广播星历中的数据。本文以GPS导航电文文件为例读取文件。
如图,在文件头之后的就是我们需要的数据,数据结构是每个星历块八行,第一行十个数据,之后每行四个。数据的含义比较复杂,可以参考其他文献。网上应该很多相关资料。
读取文件后,数据储存在一个结构体指针中。
struct EPHEMERISBLOCK
//每小时一个卫星对应一个基本星历块
{
//PRN号
int PRN;
double a0, a1, a2;//时间改正数
//六个轨道参数
double IODE, Crs, Deltan, M0;// ORBIT - 1
double Cuc, e, Cus, SqrtA;// ORBIT - 2
double Toe, Cic, OMEGA, Cis;// ORBIT - 3
double i0, Crc, omega, OMEGAdot;// ORBIT - 4
double IDOT, GpsWeekNumber, L2C, L2P;// ORBIT - 5
double SatAccuracy, SatHealth, TGD, IODC;// ORBIT - 6
};
##
构造一个计算类CMyCalculation,专门用于完成读取文件和计算功能,在类中添加以下变量和方法:
private:
int EphemerisBlockNum;//记录星历块数目
EPHEMERISBLOCK *m_pGpsEphemeris;//记录星历数据
public void ReadBrodcastEphemeris(CString strEpheNam);
以下为读取文件函数的实现:
void CMyCaculation::ReadBrodcastEphemeris(CString strEpheNam)
{
int HeadLineNum = 0;
int WeekNo;
double WeekSecond;
//打开文件
CStdioFile pfEph;
BOOL IsEn = pfEph.Open(strEpheNam, CFile::modeRead);
if (!IsEn) {
AfxMessageBox(_T("文件读取失败"),MB_OK,0);
return;
}
//读入头文件
CString strLine;
while (IsEn)
{
IsEn = pfEph.ReadString(strLine);
HeadLineNum++;
int index = strLine.Find(CString("END OF HEADER"));
if (-1 != index)
break;
}
//计算星历块数
int AllNum = 0;
while (IsEn)
{
IsEn = pfEph.ReadString(strLine);
AllNum++;
}
//指针不为空时释放指针内存,之后重新赋值
if(NULL!=m_pGpsEphemeris){
delete m_pGpsEphemeris;
}
//临时读入星历块
EphemerisBlockNum = (AllNum + 1) / 8;
m_pGpsEphemeris = new EPHEMERISBLOCK[EphemerisBlockNum];
GPSTIME *pGpsTime = new GPSTIME[EphemerisBlockNum];
if (!m_pGpsEphemeris || !pGpsTime) return;
//将文件指针调整到数据位置
pfEph.SeekToBegin();
for (int i = 0; i<HeadLineNum; i++)
IsEn = pfEph.ReadString(strLine);
//定义读取的参数
int mPrn;//卫星号PRNo
int year, month, day, hour, minute;//卫星钟参考时刻
double msecond;
double a0, a1, a2;//卫星钟飘参数
double IODE, Crs, DeltN, M0;//数据星历发布时间,在轨道径向方向上周期改正正弦的振幅
double Cuc, e, Cus, sqrtA;//轨道延迹方向上周期改正余弦振幅 、扁心率、轨道延迹方向上周期改正正弦振幅 、长半轴平方根
double Toe, Cic, OMEGA, Cis;//星历参考时刻、轨道倾角周期改正余弦项振幅、参考时刻升交点赤径主项、轨道倾角周期改正正弦项振幅
double i0, Crc, omega, OMEGADOT;//参考时间轨道倾角、在轨道径向方向上周期改正余余弦的振幅、近地点角距、升交点赤径在赤道平面中的长期变化
double IDOT, L2C, GPSWeek, L2P;轨道倾角变化率、??、gps周
double AccuracyofSat, HealthofSat, TGD, IODC;//卫星精度、卫星健康、电离层群迟改正数
//将以下循环中读取数据的CString都改为char*类型strline
for (int i = 0; i<EphemerisBlockNum; i++)
{
//读取卫星PRN号,星历参考时间
IsEn = pfEph.ReadString(strLine);
strLine.Replace('D', 'e');
char* strline = CSTR2CAHR(strLine);//
sscanf_s(strline, "%d %d %d %d %d %d %lf %lf %lf %lf", &mPrn, &year, &month, &day, &hour, &minute, &msecond, &a0, &a1, &a2);
year += 2000;
WeekNo = Calendar2GpsTime(year, month, day, hour, minute, msecond, WeekSecond);
pGpsTime[i].weekno = WeekNo;
pGpsTime[i].weekSecond = WeekSecond;
IsEn = pfEph.ReadString(strLine);
strLine.Replace('D', 'e');
strline = CSTR2CAHR(strLine);
sscanf_s(strline, "%lf %lf %lf %lf", &IODE, &Crs, &DeltN, &M0);
//读 Cuc,e,Cus,sqrtA
IsEn = pfEph.ReadString(strLine);
strLine.Replace('D', 'e');
strline = CSTR2CAHR(strLine);
sscanf_s(strline, "%lf %lf %lf %lf", &Cuc, &e, &Cus, &sqrtA);
//Toe,Cic,OMEGA,Cis;
IsEn = pfEph.ReadString(strLine);
strLine.Replace('D', 'e');
strline = CSTR2CAHR(strLine);
sscanf_s(strline, "%lf %lf %lf %lf", &Toe