在上两文中给出了Java编程实现对RINEX格式的观测值文件和广播星历文件的读取(读取观测值文件链接https://blog.csdn.net/qq_40449816/article/details/100695746读取广播星历文件链接https://blog.csdn.net/qq_40449816/article/details/100767851),本文给出根据广播星历对卫星某一时刻的空间位置计算的代码,包括对卫星钟差改正和相对论效应改正。代码详情如下:
package PosCalcluate;
import ReadFile.DataClass.Ephemeris;
import ReadFile.ReadNavData;
import TimeSysTrans.GPST;
import Util.CorrectionCalculate.SatelliteClockCorrection;
import java.util.ArrayList;
import java.util.List;
/**
* 该类实现对某一时刻卫星位置的计算
* @author lhn
* */
public class SatellitePosCal {
//地球自转角速度
private static final double EARTH_ROTATION_RATE_RAD_PER_SEC = 7.2921151467e-5;
/**
* 实现对某一时刻,某一卫星的空间坐标位置计算(默认采用的坐标系时WGS-84空间大地坐标系)
* @param obs_t 观测时刻
* @param ephemeris 卫星星历数据
* @return satPos
*/
public static SatellitePosition CalSatPos(GPST obs_t, Ephemeris ephemeris){
double X_Pos=0.0;
double Y_Pos=0.0;
double Z_Pos=0.0;
SatellitePosition satellitePosition=new SatellitePosition();
/* *//**筛选出与观测时刻最近的历元星历数据*//*
Ephemeris ephemeris=null;
GPST temp=new GPST();
for(Ephemeris e:ephemerisList){
if(e.getPrn().equals(prn)){
temp=e.getGpst();
ephemeris=e;
break;
}
}
for(Ephemeris e:ephemerisList){
if(e.getPrn().equals(prn)){
GPST gpst=obs_t.sub(e.getGpst());
if(gpst.isLess(temp)){
temp=gpst;
ephemeris=e;
}
}
}*/
/**根据开普勒轨道6参数和摄动九参数确定卫星的空间坐标*/
if(ephemeris!=null){
try {
SatelliteClockCorrection satelliteClockCorrection=new SatelliteClockCorrection(ephemeris,obs_t);
//归化时间(s)
double tkSec=satelliteClockCorrection.getTimeFromRefEpochSec();
//偏近点角(弧)
double eccentricAnomalyRadians=satelliteClockCorrection.getEccentricAnomalyRadians();
//真近点角(弧)
double trueAnomalyRadians=Math.atan2(Math.sqrt(1-ephemeris.getE()*ephemeris.getE())*Math.sin(eccentricAnomalyRadians),
Math.cos(eccentricAnomalyRadians)-ephemeris.getE());
//升交距角(弧)
double argumentOfLatitudeRadians=ephemeris.getOmega()+trueAnomalyRadians;
//受摄卫星矢距(m)
double radiusOfSatelliteOrbit=ephemeris.getSqurt_A()*ephemeris.getSqurt_A()*(1-ephemeris.getE()*Math.cos(eccentricAnomalyRadians));
//计算摄动改正项
/*升交距角改正项*/
double argumentOfLatitudeCorrection=ephemeris.getCuc()*Math.cos(2*argumentOfLatitudeRadians)+ephemeris.getCus()*Math.sin(2*argumentOfLatitudeRadians);
/*受摄卫星失距改正项*/
double radiusCorrection=ephemeris.getCrc()*Math.cos(2*argumentOfLatitudeRadians)+ephemeris.getCrs()*Math.sin(2*argumentOfLatitudeRadians);
/*受摄卫星轨道倾角改正*/
double inclinationCorrectionRadians=ephemeris.getCic()*Math.cos(2*argumentOfLatitudeRadians)+ephemeris.getCIS()*Math.sin(2*argumentOfLatitudeRadians);
/*改正后的值*/
argumentOfLatitudeRadians+=argumentOfLatitudeCorrection;
radiusOfSatelliteOrbit+=radiusCorrection;
double inclinationRadians=ephemeris.getI0()+inclinationCorrectionRadians+ephemeris.getIDOT()*tkSec;
//计算卫星再轨道平面坐标系的位置
double xPosition=radiusOfSatelliteOrbit*Math.cos(argumentOfLatitudeRadians);
double yPosition=radiusOfSatelliteOrbit*Math.sin(argumentOfLatitudeRadians);
//计算观测瞬间升交点经度L
double omegaKRadians=ephemeris.getOMEGA()+(ephemeris.getOMEGA_DOT()-EARTH_ROTATION_RATE_RAD_PER_SEC)*tkSec
-EARTH_ROTATION_RATE_RAD_PER_SEC*ephemeris.getToe();
//计算卫星瞬时地球坐标中的位置
X_Pos=xPosition*Math.cos(omegaKRadians)-yPosition*Math.cos(inclinationRadians)* Math.sin(omegaKRadians);
Y_Pos=xPosition*Math.sin(omegaKRadians)+yPosition*Math.cos(inclinationRadians)*Math.cos(omegaKRadians);
Z_Pos=yPosition*Math.sin(inclinationRadians);
} catch (Exception e) {
e.printStackTrace();
}
}
satellitePosition.setSatellitePosition_X(X_Pos);
satellitePosition.setSatellitePosition_Y(Y_Pos);
satellitePosition.setSatellitePosition_Z(Z_Pos);
return satellitePosition;
}
}
package Util.CorrectionCalculate;
import ReadFile.DataClass.Ephemeris;
import TimeSysTrans.GPST;
/**
* 该类实现为卫星钟差改正
*/
public class SatelliteClockCorrection {
//光速(m)
private static final double SPEED_OF_LIGHT_MPS = 299792458.0;
//GM(万有引力常数与地球质量的乘积)
private static final double EARTH_UNIVERSAL_GRAVITATIONAL_CONSTANT_M3_SM2 = 3.986005e14;
//相对论改正常数
private static final double RELATIVISTIC_CONSTANT_F = -4.442807633e-10;
//地球自转角速度
private static final double EARTH_ROTATION_RATE_RAD_PER_SEC = 7.2921151467e-5;
//一周的秒数
private static final int SECONDS_IN_WEEK = 604800;
//精度限差
private static final double ACCURACY_TOLERANCE = 1.0e-11;
//迭代最大次数
private static final int MAX_ITERATIONS = 100;
//卫星钟差改正(m)
private double satelliteClockCorrectionMeter;
//偏近点角(弧)
private double eccentricAnomalyRadians;
//归化时间tk(s)
private double timeFromRefEpochSec;
/**
* @param e 星历数据
* @param transmissionTime 信号传播的时间
*/
public SatelliteClockCorrection(Ephemeris e, GPST transmissionTime) throws Exception {
if(e!=null && transmissionTime!=null){
calculateSatelliteClockCorrectionAndEccentricAnomalyRadians(e,transmissionTime);
}
}
private void calculateSatelliteClockCorrectionAndEccentricAnomalyRadians(Ephemeris ephemeris,GPST transmissionTime) throws Exception {
//平近点角(弧)
double meanAnomallyRad;
//偏近点角
double eccentricAnomallay;
//长半轴(m)
double a=ephemeris.getSqurt_A()*ephemeris.getSqurt_A();
//卫星平均角速度(弧/秒)
double n0=Math.sqrt(EARTH_UNIVERSAL_GRAVITATIONAL_CONSTANT_M3_SM2/(a*a*a));
double n=n0+ephemeris.getDelta_n();
//GPST时转为秒
double transmissionSec=transmissionTime.getWeeks()*SECONDS_IN_WEEK+transmissionTime.getSeconds();
//初始时间间隔
double tcSec=transmissionSec-ephemeris.getGpst().getWeeks()*SECONDS_IN_WEEK-ephemeris.getGpst().getSeconds();
tcSec=fixWeekRollerover(tcSec);
//设置偏近点角等初始值用于迭代计算
double oldEccentricAnomalyRad = 0.0;
double newSatClockCorrectionSeconds = 0.0;
double relativisticCorrection = 0.0;
double changeInSatClockCorrection = 0.0;
final double initSatClockCorrectionSeconds=ephemeris.getA0()+ephemeris.getA1()*tcSec+ephemeris.getA2()*tcSec*tcSec-ephemeris.getTGD();
//卫星钟差改正数(s)
double satClockCorrrection=initSatClockCorrectionSeconds;
double tkSec;
int satClockCorrectionsCounter = 0;
do {
int eccentricAnomalyCounter = 0;
//归化时间
tkSec=transmissionSec-(
ephemeris.getGpst().getWeeks()*SECONDS_IN_WEEK+ephemeris.getGpst().getSeconds()+satClockCorrrection
);
tkSec=fixWeekRollerover(tkSec);
double meanAnomally=ephemeris.getM0()+n*tkSec;
//初始偏近点角等于平近点角
eccentricAnomallay=meanAnomally;
//迭代运算求出偏近点角
do {
oldEccentricAnomalyRad=eccentricAnomallay;
eccentricAnomallay=meanAnomally+ephemeris.getE()*Math.sin(eccentricAnomallay);
eccentricAnomalyCounter++;
if(eccentricAnomalyCounter>MAX_ITERATIONS){
throw new Exception("Kepler Eccentric Anomaly calculation did not converge in "
+ MAX_ITERATIONS + " iterations");
}
}while (Math.abs(oldEccentricAnomalyRad-eccentricAnomallay)>ACCURACY_TOLERANCE);
relativisticCorrection=RELATIVISTIC_CONSTANT_F*ephemeris.getE()*ephemeris.getSqurt_A()*Math.sin(eccentricAnomallay);
newSatClockCorrectionSeconds=initSatClockCorrectionSeconds+relativisticCorrection;
changeInSatClockCorrection=Math.abs(satClockCorrrection-newSatClockCorrectionSeconds);
satClockCorrrection=newSatClockCorrectionSeconds;
satClockCorrectionsCounter++;
if(satClockCorrectionsCounter>MAX_ITERATIONS){
throw new Exception("Satellite Clock Correction calculation did not converge in "
+ MAX_ITERATIONS + " iterations");
}
}while (changeInSatClockCorrection>ACCURACY_TOLERANCE);
tkSec=transmissionSec-(ephemeris.getGpst().getWeeks()*SECONDS_IN_WEEK+ephemeris.getGpst().getSeconds()+satClockCorrrection);
this.satelliteClockCorrectionMeter=satClockCorrrection*SPEED_OF_LIGHT_MPS;
this.timeFromRefEpochSec=tkSec;
this.eccentricAnomalyRadians=eccentricAnomallay;
}
/**
* 将time的范围调整为-302400-302400之间
* @param time
* @return
*/
private double fixWeekRollerover(double time){
double newTime=time;
if(time > SECONDS_IN_WEEK / 2.0){
newTime=time-SECONDS_IN_WEEK;
}if(time <- SECONDS_IN_WEEK / 2.0){
newTime=time+SECONDS_IN_WEEK;
}
return newTime;
}
public double getSatelliteClockCorrectionMeter() {
return satelliteClockCorrectionMeter;
}
public double getEccentricAnomalyRadians() {
return eccentricAnomalyRadians;
}
public double getTimeFromRefEpochSec() {
return timeFromRefEpochSec;
}
}
package PosCalcluate;
/**
* 该类为卫星的位置信息类
*/
public class SatellitePosition {
//X坐标(m)
private double satellitePosition_X;
//Y坐标(m)
private double satellitePosition_Y;
//Z坐标(m)
private double satellitePosition_Z;
public double getSatellitePosition_X() {
return satellitePosition_X;
}
public void setSatellitePosition_X(double satellitePosition_X) {
this.satellitePosition_X = satellitePosition_X;
}
public double getSatellitePosition_Y() {
return satellitePosition_Y;
}
public void setSatellitePosition_Y(double satellitePosition_Y) {
this.satellitePosition_Y = satellitePosition_Y;
}
public double getSatellitePosition_Z() {
return satellitePosition_Z;
}
public void setSatellitePosition_Z(double satellitePosition_Z) {
this.satellitePosition_Z = satellitePosition_Z;
}
}
卫星某一时刻的空间位置计算完后,接下来,就是根据观测历元伪距等相位观测值数据迭代计算求出测站坐标,代码实现将在下文中给出。