Java实现对某一时刻GPS中圆轨道卫星的空间位置计算

在上两文中给出了Java编程实现对RINEX格式的观测值文件和广播星历文件的读取(读取观测值文件链接https://blog.csdn.net/qq_40449816/article/details/100695746读取广播星历文件链接https://blog.csdn.net/qq_40449816/article/details/100767851),本文给出根据广播星历对卫星某一时刻的空间位置计算的代码,包括对卫星钟差改正和相对论效应改正。代码详情如下:

  • SatellitePosCal.java

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;
    }


}
  • SatelliteClockCorrection.java

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;
    }
}
  • SatellitePosition.java

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;
    }
}

卫星某一时刻的空间位置计算完后,接下来,就是根据观测历元伪距等相位观测值数据迭代计算求出测站坐标,代码实现将在下文中给出。

你可能感兴趣的:(Java实现对某一时刻GPS中圆轨道卫星的空间位置计算)