Cesium航天卫星开发教程之一:基础卫星轨道
Cesium航天卫星开发教程之一:基础卫星轨道
Cesium是一个用于创建3D地球和地图的开源JavaScript库,广泛应用于地理信息系统(GIS)、虚拟现实(VR)和增强现实(AR)等领域。在航天领域,Cesium可以用于模拟和可视化卫星轨道,帮助研究人员和工程师更好地理解和分析卫星的运行状态。本文将介绍如何使用Cesium实现不同类型的卫星轨道可视化。
一、卫星轨道类型及特点
在航天领域,卫星轨道主要分为以下几种类型:
低地球轨道(LEO):轨道高度一般在 500-2000km,常用于对地观测、测地、通信、导航等任务。在 Cesium 中模拟 LEO 卫星轨道时,由于轨道高度相对较低,卫星运行速度较快,绕地球一圈的时间较短,在可视化中能明显看到卫星快速移动。
中地球轨道(MEO):高度在 2000-35786km,主要用于导航等。MEO 卫星轨道的周期比 LEO 长,在 Cesium 场景中,其运动速度相对较慢,轨道看起来比 LEO 更高更远。
地球静止轨道(GEO):位于 35786km 高度,主要用于通信、导航、气象观测等。在 Cesium 中,GEO 卫星看起来几乎静止在地球赤道上方某一位置,因为其运行周期与地球自转周期相同。
太阳同步轨道(SSO):高度一般小于 6000km,主要用于观测等。卫星在 SSO 上运行时,能保证每天在相同地方时经过同一地点上空,在 Cesium 中可用于模拟对特定区域进行定时观测的卫星任务。
倾斜地球同步轨道(IGSO):高度为 35786km,常用于导航。IGSO 卫星的轨道平面与地球赤道平面有一定夹角,在 Cesium 中可看到其沿着倾斜的轨道围绕地球运行,且在特定区域内有较好的覆盖效果。
二、轨道绘制与计算
在Cesium中,可以使用以下两种方法绘制卫星轨道:
基于轨道六根数:通过轨道半长轴、轨道离心率、轨道倾角、右上升角、近地点角距、平近点角这六个参数来计算卫星位置。先根据公式计算半通径、径向距离、轨道平面上的位置,再计算组合旋转矩阵,最后应用旋转矩阵到轨道平面上的位置向量,得到卫星在空间中的坐标,通过循环修改真近点角可绘制出轨道。
基于 TLE 数据:利用 TLE 数据中的轨道参数,通过特定算法和公式,如利用卫星运动周期公式等,计算卫星在不同时间点的位置,再将这些位置点连接起来,形成卫星轨道。
三、可视化相关功能
Cesium提供了丰富的可视化功能,可以实现卫星轨道的动态仿真和交互:
轨道动态仿真:利用 Cesium 原生的动画控件和时间线控件完成卫星轨道的动态仿真,用户可通过动画控件控制场景中动画的播放和暂停,并调节动画速率,时间线控件则指示当前时间,允许用户跳到特定时间,方便观察卫星在不同时刻的位置和轨道情况。
卫星与场景交互:可实现卫星扫描范围展示,通过 EllipseGraphics 等图形对象来定义卫星的扫描范围椭圆。还能实现摄像头跟随卫星的动态视角调整,使用户能以卫星视角或跟随卫星的方式观察其运动和轨道。
四、代码实现
1. 模拟轨道数据
function gerateSatelliteLines(lon, lat) {
const arr = []
for (let i = 0; i <= 360; i += 10) {
arr.push(
lon + i,
lat,
700000
)
}
return arr
}
export default gerateSatelliteLines
2. 卫星轨道
import Cesium from '@/cesiumUtils/cesium'
export default class Roaming {
/**
*Creates an instance of satellite roaming.
* @param {*} viewer 需要传入
* @param {*} options.modeluri 模型的uri 需要传入
* @param {*} options.start 开始节点 不需要传入
* @param {*} options.stop 结束节点 不需要传入
* @param {*} options.Lines 点集合 需要传入
* @param {*} options.isPathShow 路径是否显示 默认显示
* @memberof Roaming
*/
constructor(viewer, options) {
this.viewer = viewer
this.entity = undefined
this.entity2 = undefined
this.url = options.uri
this.start = undefined
this.stop = undefined
this.Lines = options.Lines
const newLen = options.Lines.length / 3
this.LinesArr = Array(newLen).fill('').map((any, i) => {
return options.Lines.slice(i * 3, (i + 1) * 3)
})
this.isPathShow = options.isPathShow || true
this.InitSatellite(this.computeFlight(this.LinesArr), this.start, this.stop)
this.InitRadarArea(this.computeFlight(this.LinesArr, true), this.start, this.stop, true)
}
/**
*
*
* @param {*} Lines 点集合
* @param {*} isCone 是否是圆锥区域
* @returns
* @memberof Roaming
*/
computeFlight(Lines, isCone) {
const property = new Cesium.SampledPositionProperty()
const start = Cesium.JulianDate.now()
this.start = start
const stop = Cesium.JulianDate.addSeconds(start, 360, new Cesium.JulianDate())
this.stop = stop
this.viewer.clock.startTime = start.clone()
this.viewer.clock.stopTime = stop.clone()
this.viewer.clock.currentTime = start.clone()
// 循环执行
this.viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP // Loop at the end
// 时间速率,数字越大时间过的越快
// this.viewer.clock.multiplier = 10
this.viewer.timeline.zoomTo(start, stop)
Lines.forEach((line, i) => {
const time = Cesium.JulianDate.addSeconds(start, line[0], new Cesium.JulianDate())
const position = Cesium.Cartesian3.fromDegrees(line[0], line[1], isCone ? line[2] / 2 : line[2])
property.addSample(time, position)
})
return property
}
/**
*
* 画卫星和卫星的路径
* @param {*} position computeFlight计算的属性
* @param {*} start 开始时间节点
* @param {*} stop 结束时间节点
* @memberof Roaming
*/
InitSatellite(position, start, stop) {
this.entity = this.viewer.entities.add({
id: 'satt',
name: '卫星',
label: {
text: '卫星',
backgroundPadding: new Cesium.Cartesian2(7, 7),
showBackground: true,
pixelOffset: new Cesium.Cartesian2(0, -100),
verticalOrigin: Cesium.VerticalOrigin.TOP,
font: '30px sans-serif',
horizontalOrigin: Cesium.HorizontalOrigin.CENTER,
scale: 0.5,
fillColor: Cesium.Color.WHITE,
scaleByDistance: new Cesium.NearFarScalar(10000000, 1, 10000001, 0.0)
},
availability: new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({
start,
stop
})]),
// 位置
position,
// 计算朝向
orientation: new Cesium.VelocityOrientationProperty(position),
// 加载模型
model: {
// 模型路径
uri: this.url,
// 模型最小刻度
minimumPixelSize: 20000,
maximumSize: 20000,
// 设置模型最大放大大小
maximumScale: 200000,
// scale: 20000,
runAnimations: true // 是否运行模型中的动画效果
},
path: {
resolution: 1,
material: new Cesium.PolylineGlowMaterialProperty({
glowPower: 0.1,
color: Cesium.Color.WHITE
}),
width: 2
}
})
// 设置连线的曲度
this.entity.position.setInterpolationOptions({
// 曲度
interpolationDegree: 3,
// 点插值 (接近圆)
interpolationAlgorithm: Cesium.LagrangePolynomialApproximation
// 点插值 (直连)
// interpolationAlgorithm: Cesium.LinearApproximation
// // // 点插值 (接近半圆)
// interpolationAlgorithm: Cesium.HermitePolynomialApproximation
})
// 设置相机视角默认在飞机上
// this.viewer.zoomTo(this.entity)
// this.viewer.trackedEntity = this.entity
}
/**
*
* 卫星下面的锥形
* @param {*} position computeFlight计算的属性
* @param {*} start 开始时间节点
* @param {*} stop 结束时间节点
* @memberof Roaming
*/
InitRadarArea(position, start, stop) {
this.entity2 = this.viewer.entities.add({
availability: new Cesium.TimeIntervalCollection([new Cesium.TimeInterval({
start,
stop
})]),
name: '卫星探测区域',
// 位置
position,
// 计算朝向
orientation: new Cesium.VelocityOrientationProperty(position),
cylinder: {
HeightReference: Cesium.HeightReference.CLAMP_TO_GROUND,
length: 700000,
topRadius: 0,
bottomRadius: 700000,
material: Cesium.Color.BLUE.withAlpha(0.2),
outline: 1,
numberOfVerticalLines: 0,
outlineColor: Cesium.Color.BLUE.withAlpha(0.1)
}
})
// 设置连线的曲度
this.entity2.position.setInterpolationOptions({
// 曲度
interpolationDegree: 5,
// 点插值 (接近圆)
interpolationAlgorithm: Cesium.LagrangePolynomialApproximation
})
}
/**
*漫游的暂停和继续
*
* @param {*} state bool类型 false为暂停,ture为继续
* @memberof Roaming
*/
PauseOrContinue(state) {
this.viewer.clock.shouldAnimate = state
}
/**
*改变飞行的速度
*
* @param {*} value 整数类型
* @memberof Roaming
*/
ChangeRoamingSpeed(value) {
this.viewer.clock.multiplier = value
}
/**
*
*取消漫游
* @memberof Roaming
*/
EndRoaming() {
if (this.entity) {
this.viewer.entities.remove(this.entity)
}
if (this.entity2) {
this.viewer.entities.remove(this.entity2)
}
}
}