Orekit生成AngularRaDec观测数据

1、简要

  • 本文基于Orekit生成初轨确定用的观测数据类对象AngularRaDec,实测表明AngularRaDec并不局限于地面站观测的赤经赤纬数据,对于地面移动站(车、船、飞机等)、天基(卫星)都是支持的。
  • 以下根据一个卫星观测另外一个卫星的场景生成观测数据,适用最简单的二体模型进行预报。

2、示例代码(编译运行通过)

java 复制代码
import org.hipparchus.geometry.euclidean.threed.Vector3D;
import org.hipparchus.util.FastMath;

import org.orekit.bodies.GeodeticPoint;
import org.orekit.bodies.OneAxisEllipsoid;
import org.orekit.data.DataProvidersManager;
import org.orekit.data.DirectoryCrawler;
import org.orekit.data.DataContext;
import org.orekit.estimation.measurements.AngularRaDec;
import org.orekit.estimation.measurements.GroundStation;
import org.orekit.estimation.measurements.ObservableSatellite;
import org.orekit.frames.Frame;
import org.orekit.frames.FramesFactory;
import org.orekit.frames.Transform;
import org.orekit.frames.TopocentricFrame;
import org.orekit.orbits.CartesianOrbit;
import org.orekit.orbits.KeplerianOrbit;
import org.orekit.orbits.Orbit;
import org.orekit.orbits.OrbitType;
import org.orekit.orbits.PositionAngleType;
import org.orekit.propagation.Propagator;
import org.orekit.propagation.analytical.KeplerianPropagator;
import org.orekit.time.AbsoluteDate;
import org.orekit.time.DateComponents;
import org.orekit.time.TimeScale;
import org.orekit.time.TimeScalesFactory;
import org.orekit.utils.IERSConventions;
import org.orekit.utils.TimeStampedPVCoordinates;
import org.orekit.utils.PVCoordinates;
import org.orekit.utils.Constants;



import java.io.File;
import java.util.List;
import java.util.ArrayList;


public class AngularRaDecTest {
    
	// 静态初始化块,在类加载时初始化Orekit    
    static {    
        initOrekit();    
    }

    // 常量定义
    private static final double TIME_STEP = 60.0; // 1分钟
    private static final double TOLERANCE = 1.0e-3;
	private static final double MU = Constants.IERS2010_EARTH_MU;
	private static final Frame INERTIAL_FRAME = FramesFactory.getEME2000();
	private static final Frame ecefFrame = FramesFactory.getITRF(IERSConventions.IERS_2010, true); //地固系
	private static final TimeScale UTC = TimeScalesFactory.getUTC();
	
	// 创建地球参考椭球体(WGS84标准)
	private static final OneAxisEllipsoid earth = new OneAxisEllipsoid(
		Constants.WGS84_EARTH_EQUATORIAL_RADIUS,
		Constants.WGS84_EARTH_FLATTENING,
		FramesFactory.getITRF(IERSConventions.IERS_2010, true)  // ITRF2000框架
	);

    
    /**    
     * 初始化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) {
      
		System.out.println("\n测试3: 星对星用例1");
		AbsoluteDate startDate = new AbsoluteDate(2024, 1, 1, 0, 0, 0.0, UTC);
		int stepSizeSeconds = 60;
		
		KeplerianOrbit orbitA = new KeplerianOrbit(6678137, 0, 98, 0, 0, 0,
                org.orekit.orbits.PositionAngleType.MEAN, INERTIAL_FRAME, startDate, MU);
		
		KeplerianOrbit orbitB = new KeplerianOrbit(16378137, 0.3, 
				Math.toRadians(28), 
				Math.toRadians(20), 
				Math.toRadians(40), 
				Math.toRadians(60),
                org.orekit.orbits.PositionAngleType.MEAN, INERTIAL_FRAME, startDate, MU);	
				
		test(orbitA, orbitB, startDate, stepSizeSeconds); 
    }
	
	//卫星对卫星
	//@para orbitA 观测卫星开普勒根数
	//@para orbitB 目标卫星开普勒根数
	//@para startDate  起始观测时刻
	//@para stepSizeSeconds  单位为秒的步长
	public static void test(KeplerianOrbit orbitA, KeplerianOrbit orbitB, AbsoluteDate startDate, int stepSizeSeconds) 
	{
        KeplerianPropagator propagatorA = new KeplerianPropagator(orbitA);
		KeplerianPropagator propagatorB = new KeplerianPropagator(orbitB);		
        List<PVCoordinates> pvListA = new ArrayList<PVCoordinates>(3);
		List<PVCoordinates> pvListB = new ArrayList<PVCoordinates>(3);
		List<AbsoluteDate>  dateList = new ArrayList<AbsoluteDate>(3);

        for (int index = 0; index < 3; index++) 
		{
            AbsoluteDate currentDate = startDate.shiftedBy(index * stepSizeSeconds);
            PVCoordinates pvA = propagatorA.getPVCoordinates(currentDate, INERTIAL_FRAME);
			PVCoordinates pvB = propagatorB.getPVCoordinates(currentDate, INERTIAL_FRAME);
			dateList.add(currentDate);
            pvListA.add(pvA);
			pvListB.add(pvB);
        }
		
		
		// 计算目标相对于移动观测站的赤经赤纬
		AngularRaDec azEl1 = calculateAngularRaDec(pvListA.get(0).getPosition(), pvListB.get(0).getPosition(), dateList.get(0));
		AngularRaDec azEl2 = calculateAngularRaDec(pvListA.get(1).getPosition(), pvListB.get(1).getPosition(), dateList.get(1));
		AngularRaDec azEl3 = calculateAngularRaDec(pvListA.get(2).getPosition(), pvListB.get(2).getPosition(), dateList.get(2));	
	}
	
	
	
	/**
     * 计算从观测点A到目标B的视方向赤经赤纬(输入惯性系)
     * 
     * @param ax 观测点A的X坐标 (km)
     * @param ay 观测点A的Y坐标 (km)
     * @param az 观测点A的Z坐标 (km)
     * @param bx 目标点B的X坐标 (km)
     * @param by 目标点B的Y坐标 (km)
     * @param bz 目标点B的Z坐标 (km)
     * @return 包含赤经(度)和赤纬(度)的数组 [RA, Dec]
     */
    public static double[] calculateRaDec(Vector3D A, Vector3D B) {
		double ax = A.getX();
		double ay = A.getY();
		double az = A.getZ();
		double bx = B.getX();
		double by = B.getY();
		double bz = B.getZ();
		
        // 计算从A到B的方向向量
        double dx = bx - ax;
        double dy = by - ay;
        double dz = bz - az;
        
        // 计算方向向量的模
        double magnitude = Math.sqrt(dx*dx + dy*dy + dz*dz);
        
        // 归一化方向向量
        double ux = dx / magnitude;
        double uy = dy / magnitude;
        double uz = dz / magnitude;
        
        // 计算赤纬 (arcsin(z))
        double dec = Math.asin(uz);
        
        // 计算赤经 (arctan2(y, x))
        double ra = Math.atan2(uy, ux);
        
        // 将赤经转换到 [0, 2π) 范围
        if (ra < 0) {
            ra += 2 * Math.PI;
        }
		
		return new double[]{ra, dec};

    }
	
	
	private static AngularRaDec calculateAngularRaDec(Vector3D observerPos, Vector3D targetPos, AbsoluteDate date)
	{	
		//从惯性系转大地坐标系经纬高
		GeodeticPoint observerLLA = earth.transform(observerPos, INERTIAL_FRAME, date);

		// 创建站心坐标系
		TopocentricFrame topocentricFrame = new TopocentricFrame(earth, observerLLA, "observerStation");

		// 构造地面站对象
		GroundStation station = new GroundStation(topocentricFrame);

		// 观测角度计算
		double[] angular  = calculateRaDec(observerPos, targetPos);

		// 标准差:假设方位角测量标准差, 单位为弧度
		double[] sigma = new double[]{Math.toRadians(0.0), Math.toRadians(0.0)};

		// 基础权重:这里可以设置为1,或者根据实际情况计算,例如使用方差的倒数
		double[] baseWeight = new double[]{1.0, 1.0};

		// 被观测的卫星
		ObservableSatellite satellite = new ObservableSatellite(0); // 通常使用索引0

		// 创建AngularRaDec对象
		AngularRaDec angRaDec = new AngularRaDec(station, INERTIAL_FRAME, date, angular, sigma, baseWeight, satellite);
		return angRaDec;
	}
	
}

3、环境配置

XML 复制代码
        <!-- Orekit核心库 -->
        <dependency>
            <groupId>org.orekit</groupId>
            <artifactId>orekit</artifactId>
            <version>12.2</version>
        </dependency>
        <!-- 数学库 -->
        <dependency>
            <groupId>org.hipparchus</groupId>
            <artifactId>hipparchus-core</artifactId>
            <version>4.0</version>
        </dependency>
相关推荐
开源之眼13 小时前
《github star 加星 Taimili.com 艾米莉 》为什么Java里面,Service 层不直接返回 Result 对象?
java·后端·github
Maori31614 小时前
放弃 SDKMAN!在 Garuda Linux + Fish 环境下的优雅 Java 管理指南
java
用户9083246027314 小时前
Spring AI 1.1.2 + Neo4j:用知识图谱增强 RAG 检索(上篇:图谱构建)
java·spring boot
小王和八蛋14 小时前
DecimalFormat 与 BigDecimal
java·后端
beata14 小时前
Java基础-16:Java内置锁的四种状态及其转换机制详解-从无锁到重量级锁的进化与优化指南
java·后端
IT探险家15 小时前
你的第一个 Java 程序就翻车?HelloWorld 的 8 个隐藏陷阱
java
随风飘的云15 小时前
SpringBoot 的自动配置原理
java
SimonKing15 小时前
觅得又一款轻量级数据库管理工具:GoNavi
java·后端·程序员
Seven9716 小时前
BIO详解:解锁阻塞IO的使用方式
java
oak隔壁找我1 天前
JVM常用调优参数
java·后端