关于Orekit的IodGooding类

IodGooding为Orekit中的其中一个初轨确定类,使用三点输入,IodGooding对于"初始距离估计"(rho1init和rho3init)非常敏感,除非能提供精确的初始范围估计值,否则估计结果可能与实际情况相去甚远!

(1)其轨道确定函数接口如下

复制代码
public Orbit estimate​(Frame outputFrame, AngularAzEl azEl1, AngularAzEl azEl2, AngularAzEl azEl3, double rho1init, double rho3init)

Estimate orbit from three angular observations.

This signature assumes there was less than an half revolution between start and final date

Parameters:

outputFrame - inertial frame for observer coordinates and orbit estimate

azEl1 - first angular observation

azEl2 - second angular observation

azEl3 - third angular observation

rho1init - initial guess of the range problem. range 1, in meters

rho3init - initial guess of the range problem. range 3, in meters

Returns:

an estimate of the Keplerian orbit at the central date (i.e., date of the second angular observation)

(2) 实测发现IodGooding对于不同程度误差的"初始距离估计"(rho1init和rho3init)有如下结果:

  • 设置1%的距离误差,结果半长轴相差19.9%
  • 设置2%的距离误差,结果半长轴相差30.2%

测试代码如下(从官方测测试代码src/test/java/org/orekit/estimation/iod/IodGoodingTest.java改造而来):

java 复制代码
import org.orekit.estimation.iod.*;
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.hipparchus.util.FastMath;
import org.orekit.data.DataProvidersManager;
import org.orekit.data.DirectoryCrawler;
import org.orekit.data.DataContext;
import org.orekit.frames.Frame;
import org.orekit.frames.FramesFactory;
import org.orekit.orbits.KeplerianOrbit;
import org.orekit.orbits.PositionAngleType;
import org.orekit.propagation.analytical.KeplerianPropagator;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.TimeScalesFactory;
import org.orekit.utils.Constants;
import org.orekit.utils.PVCoordinates;

import java.io.File;

/**
 * Gooding IOD算法简化测试类
 */
public class SimplifiedIodGoodingTest {
    
    // 常量定义
    private static final double MU = Constants.IERS2010_EARTH_MU;
    private static final double TIME_STEP = 60.0; // 1分钟
    private static final double TOLERANCE = 1.0e-3;
    
    // 测试轨道参数
    private static final double A = 24464564.0;     // 半长轴 (m)
    private static final double E = 0.725;          // 偏心率
    private static final double I = FastMath.toRadians(56.0);  // 倾角
    private static final double OMEGA = FastMath.toRadians(30.0); // 升交点赤经
    private static final double ARG_PERI = FastMath.toRadians(20.0); // 近地点幅角
    private static final double MEAN_ANOMALY = FastMath.toRadians(350.0); // 平近点角


	// 静态初始化块,在类加载时初始化Orekit    
    static {    
        initOrekit();    
    }    
    
    /**    
     * 初始化Orekit环境    
     */    
    private static void initOrekit() {    
        try {    
            // 设置Orekit数据路径    
			String userHome = System.getProperty("user.home");
            String orekitDataPath = userHome + File.separator + "orekit-data";
			System.out.println("orekit-data:" + orekitDataPath);
			
            File orekitData = new File(orekitDataPath);    
            if (!orekitData.exists()) {    
                System.err.println("警告: orekit-data目录不存在");    
                System.err.println("请从https://gitlab.orekit.org/orekit/orekit-data下载数据");    
                // 创建目录供用户放置数据    
                orekitData.mkdirs();    
            }    
    
            // 初始化数据提供者    
            DataProvidersManager manager = DataContext.getDefault().getDataProvidersManager();    
            manager.addProvider(new DirectoryCrawler(orekitData));    
    
            System.out.println("Orekit初始化完成");    
        } catch (Exception e) {    
            System.err.println("Orekit初始化警告: " + e.getMessage());    
        }    
    } 
    
    public static void main(String[] args) {
        try {            
            System.out.println("测试1: 基础Gooding算法");
            testBasicGooding();
            
            System.out.println("\n测试2: API一致性");
            testApiConsistency(true);
			
			System.out.println("\n测试2: API一致性");
            testApiConsistency(false);
            
            System.out.println("\n所有测试完成");
        } catch (Exception e) {
            System.err.println("程序执行失败: " + e.getMessage());
            e.printStackTrace();
        }
    }
    
    private static KeplerianOrbit createTestOrbit() {
        Frame frame = FramesFactory.getEME2000();
        AbsoluteDate date = new AbsoluteDate(2024, 6, 1, 12, 0, 0, TimeScalesFactory.getUTC());
        
        return new KeplerianOrbit(
            A, E, I, 
			ARG_PERI,    // 近地点幅角 (ω)
            OMEGA,       // 升交点赤经 (Ω)
            MEAN_ANOMALY, // 平近点角 (M)
            PositionAngleType.MEAN, // 使用平近点角
            frame,
            date,
            MU
        );
    }
    
    private static void testBasicGooding() {
        try {
            KeplerianOrbit truth = createTestOrbit();
            KeplerianPropagator propagator = new KeplerianPropagator(truth);
            Frame frame = truth.getFrame();
            
            // 生成三个测量点
            Vector3D[] positions = new Vector3D[3];
            AbsoluteDate[] dates = new AbsoluteDate[3];
            
            for (int i = 0; i < 3; i++) {
                dates[i] = truth.getDate().shiftedBy(i * TIME_STEP);
                PVCoordinates pv = propagator.getPVCoordinates(dates[i], frame);
                positions[i] = pv.getPosition();
            }
            
            // 视线方向(假设测站在原点)
            Vector3D los1 = positions[0].normalize();
            Vector3D los2 = positions[1].normalize();
            Vector3D los3 = positions[2].normalize();
            
            // 初始距离估计(使用真实值稍作扰动)
			double range1Estimate = positions[0].getNorm() * 0.98; // -2%扰动
			double range3Estimate = positions[2].getNorm() * 1.02; // +2%扰动
            
            // 执行Gooding算法
            IodGooding iod = new IodGooding(MU);
            KeplerianOrbit estimated = new KeplerianOrbit(iod.estimate(
                frame,
                Vector3D.ZERO, Vector3D.ZERO, Vector3D.ZERO,
                los1, dates[0],
                los2, dates[1],
                los3, dates[2],
                range1Estimate,
                range3Estimate
            ));
            
            // 验证结果
            System.out.printf("  半长轴: 真实=%.1fkm, 估计=%.1fkm, 误差=%.2f%%%n", 
                truth.getA()/1000, estimated.getA()/1000,
                Math.abs(truth.getA() - estimated.getA())/truth.getA()*100);
            
            System.out.printf("  偏心率: 真实=%.6f, 估计=%.6f, 误差=%.2e%n", 
                truth.getE(), estimated.getE(),
                Math.abs(truth.getE() - estimated.getE()));
            
            System.out.printf("  倾角: 真实=%.2f°, 估计=%.2f°, 误差=%.2e°%n",
                FastMath.toDegrees(truth.getI()), 
                FastMath.toDegrees(estimated.getI()),
                FastMath.toDegrees(Math.abs(truth.getI() - estimated.getI())));
                
        } catch (Exception e) {
            System.err.println("基础测试失败: " + e.getMessage());
            e.printStackTrace();
        }
    }
}

(3)此外,Orekit的测试代码的注释中有如下信息:

// the problem is very sensitive, and unless one can provide the exact
// initial range estimate, the estimate may be far off the truth...
final Orbit orbit = iod.estimate(frame,
stapos1, stapos2, stapos3,
lineOfSight1, date1,
lineOfSight2, date2,
lineOfSight3, date3,
r1 * 1.0, r3 * 1.0);

参考翻译:

这个问题非常敏感,除非能提供精确的初始范围估计值,否则估计结果可能与实际情况相去甚远......

(4) 参考

https://gitlab.orekit.org/orekit/orekit/-/blob/13.1.3/src/test/java/org/orekit/estimation/iod/IodGoodingTest.java

相关推荐
piaopiaolanghua4 天前
Orekit基于TLE的SGP4轨道预报
tle·sgp4·orekit