写在前面
最近接触了卫星通信相关的业务,其中接触到了Java开发的飞行动力学库 Orekit, 虽然利用他的 API 完成了一些业务,但对其原理和其设计并不是特别理解,所以打算根据其教程边学习边记录笔记,第一篇就是从 Attitude 开始。其教程的源码 Orekit-tutorials
Earth Observation
轨道定义
这里我利用真实卫星轨道两行轨道根数定义轨道(TLE),后面到轨道篇之后会专门介绍 TLE 数据,获取 TLE 数据可以从 NORAD 网站下载到。
//定义初始化日期
final AbsoluteDate initDate = new AbsoluteDate(2022, 11, 3, 13, 0, 00.000, TimeScalesFactory.getUTC());
//采用 STARLINK-1016 卫星定义轨道
final String line1 = "1 44722U 19074K 22306.13064920 .00001350 00000+0 10954-3 0 9998";
final String line2 = "2 44722 53.0549 279.3841 0001884 44.5577 315.5564 15.06391807164509";
TLE tle = new TLE(line1, line2);
TLEPropagator tlePropagator = TLEPropagator.selectExtrapolator(tle);
//这里定义开普勒轨道
final Orbit initOrbit = new KeplerianOrbit(tlePropagator.getPVCoordinates(initDate),FramesFactory.getEME2000(), initDate, Constants.EIGEN5C_EARTH_MU);
//太阳坐标及坐标系
final PVCoordinatesProvider sun = CelestialBodyFactory.getSun();
//定义地球,J2000坐标系下
final OneAxisEllipsoid earth = new OneAxisEllipsoid(Constants.WGS84_EARTH_EQUATORIAL_RADIUS,Constants.WGS84_EARTH_FLATTENING, FramesFactory.getITRF(IERSConventions.IERS_2010, true));
卫星姿态定义
卫星姿态的定义实际上就是 Local Frames 定义,对于卫星物体坐标系一般采用 LVLH(Local Vertical, Local Horizontal frame) .
- Z 轴从卫星指向地心
- Y 轴垂直轨道平面,指向轨道面外侧
- X 轴是 Y 轴 Z 轴叉乘,满足右手坐标系
// Attitudes sequence definition
// 白天观察地球的姿态,Orekit Local Frame 还可以定义旋转角 Pitch(x),Yaw(y),Roll(z),
final AttitudeProvider dayObservationLaw = new LofOffset(initOrbit.getFrame(), LOFType.VVLH, RotationOrder.XYZ, FastMath.toRadians(20), FastMath.toRadians(40), 0);
// 夜晚休息的姿态
final AttitudeProvider nightRestingLaw = new LofOffset(initOrbit.getFrame(), LOFType.VVLH);
昼夜变化探测
关于事件定义和事件探测的设计,后续再深入展开,这里就姑且先看一下教程的实现逻辑,检测卫星飞行过程中的昼夜变化。
//Sun's radius=696000000m
//定义白天到夜晚的探测事件
final EventDetector dayNightEvent = new EclipseDetector(sun, 696000000., earth).withHandler(new ContinueOnEvent<EclipseDetector>());
//定义黑夜到白天的探测事件
final EventDetector nightDayEvent = new EclipseDetector(sun, 696000000., earth).withHandler(new ContinueOnEvent<EclipseDetector>());
final AttitudesSequence attitudesSequence = new AttitudesSequence();
final AttitudesSequence.SwitchHandler switchHandler =
(preceding, following, s) -> {
if (preceding == dayObservationLaw) {
output.add(s.getDate() + ": switching to night law");
} else {
output.add(s.getDate() + ": switching to day law");
}};
//添加昼夜切换的条件
attitudesSequence.addSwitchingCondition(dayObservationLaw, nightRestingLaw, dayNightEvent, false, true, 10.0, AngularDerivativesFilter.USE_R, switchHandler);
attitudesSequence.addSwitchingCondition(nightRestingLaw, dayObservationLaw, nightDayEvent, true, false, 10.0, AngularDerivativesFilter.USE_R, switchHandler);
if (dayNightEvent.g(new SpacecraftState(initOrbit)) >= 0) {
// initial position is in daytime
attitudesSequence.resetActiveProvider(dayObservationLaw);
} else {
// initial position is in nighttime
attitudesSequence.resetActiveProvider(nightRestingLaw);
}
轨道传播模型(Oribit propagation models)
轨道传播模型有 Keplerian model (effect of central force),Secular J2 model (secular effects due to J2),Eckstein-Hechler model,Lyddane model,对于这几种轨道传播模型以及什么是轨道传播模型,后续介绍 Propagation 专题中会介绍。
轨道传播模型主要用来进行卫星在轨道内进行事件探测。
// Propagator : consider the analytical Eckstein-Hechler model
final Propagator propagator = new EcksteinHechlerPropagator(initOrbit, attitudesSequence,
Constants.EIGEN5C_EARTH_EQUATORIAL_RADIUS,
Constants.EIGEN5C_EARTH_MU,
Constants.EIGEN5C_EARTH_C20,
Constants.EIGEN5C_EARTH_C30,
Constants.EIGEN5C_EARTH_C40,
Constants.EIGEN5C_EARTH_C50,
Constants.EIGEN5C_EARTH_C60);
// Register the switching events to the propagator
attitudesSequence.registerSwitchEvents(propagator);
propagator.getMultiplexer().add(180.0, currentState -> {
final DecimalFormatSymbols angleDegree = new DecimalFormatSymbols(Locale.US);
angleDegree.setDecimalSeparator('\u00b0');
final DecimalFormat ad = new DecimalFormat(" 00.000;-00.000", angleDegree);
// the Earth position in spacecraft frame should be along spacecraft Z axis
// during nigthtime and away from it during daytime due to roll and pitch offsets
final Vector3D earthDir = currentState.toTransform().transformPosition(Vector3D.ZERO);
final double pointingOffset = Vector3D.angle(earthDir, Vector3D.PLUS_K);
// the g function is the eclipse indicator, it is an angle between Sun and Earth limb,
// positive when Sun is outside of Earth limb, negative when Sun is hidden by Earth limb
final double eclipseAngle = dayNightEvent.g(currentState);
output.add(currentState.getDate() +
" " + ad.format(FastMath.toDegrees(eclipseAngle)) +
" " + ad.format(FastMath.toDegrees(pointingOffset)));
});
final AbsoluteDate targetDate = new AbsoluteDate(2022, 11, 3, 15, 0, 00.000, TimeScalesFactory.getUTC());
final SpacecraftState finalState = propagator.propagate(targetDate);
结果验证
查看北京时间11月3号21点-23点的昼夜过境事件
// we print the lines according to lexicographic order, which is chronological order here
// to make sure out of orders calls between step handler and event handlers don't mess things up
for (final String line : output) {
System.out.println(line);
}
System.out.println("Propagation ended at " + finalState.getDate());
结果发现在北京时间 21:25:33 卫星可观测地球的白天、22:27:33卫星观测地球的黑夜
2022-11-03T13:25:33.36915618048181Z: switching to day law
2022-11-03T14:27:33.2701364307041Z: switching to night law
我们利用依据 TLE 绘制该时刻的星下轨迹点,计算出卫星在上述两个时间的星下点:
- 2022-11-03T13:25:34,卫星的位置为(lng:-142.5413,lat:-11.5357)
- 2022-11-03T14:27:34,卫星的位置为(lng:68.8998,lat:47.9302)
通过 Earth View (fourmilab.ch) 进行卫星位置昼夜观察。
2022-11-03T13:25:34 如图所示卫星所在位置可以看到白天即将到来,卫星可以调整为工作拍摄姿态
2022-11-03T14:27:34 如图所示卫星位置可以看到夜晚降临,卫星可以收起拍摄姿态进入休息姿态