起因:看了cesium官网卫星通信示例发现只有cmzl版本的,决定自己动手写一个。欢迎大家一起探讨,评论留言。

效果

全部代码在最后

起步

寻找卫星轨迹数据,在网站space-track上找的,自己注册账号QQ邮箱即可。

  1. 卫星轨道类型 轨道高度 卫星用途
  2. LEO (低地球轨道) 500-2000km 对地观测、测地、通信、导航等
  3. MEO (中地球轨道) 2000-35786km 导航
  4. GEO(地球静止轨道) 35786km 通信 导航、气象观测等
  5. SSO (太阳同步轨道) <6000km 观测等
  6. IGSO(倾斜地球同步轨道) 35786km 导航

    点击TLE就可以得到卫星的两个轨道数据

    当然这个数据需要相对应的插件satellite.js转换成我们熟悉的经纬高;
    拔下来的数据存入json文件中:

    最后构造卫星轨迹对象
import {twoline2satrec, gstime, eciToGeodetic,PositionAndVelocity, propagate, EciVec3,degreesLong
} from 'satellite.js';fetch("data/points.json").then(res => res.json()).then(data => {for (const key in data) {if (Object.prototype.hasOwnProperty.call(data, key)) {const element = data[key];const satrec = twoline2satrec(element.data[0], element.data[1]);const positionAndVelocity: PositionAndVelocity = propagate(satrec, time);const positionEci = positionAndVelocity.position as EciVec3<number>;obj[key] = {country: element.country,times: [],positions: []};let lon, lat, alt;//一年365天 一天为间隔for (let index = min; index <= nowTime; index = index + 86400000) {const gmst = gstime(new Date(index));const positionGd = eciToGeodetic(positionEci, gmst)lon = positionGd.longitude,lat = positionGd.latitude,alt = positionGd.height;obj[key].times.push(index)obj[key].positions.push([degreesLong(lon), degreesLong(lat), alt])}}}})

加载卫星和轨迹线

//用数据集方便管理
const satellites = new Cesium.CustomDataSource("satellite");
const polylines = new Cesium.CustomDataSource("statelliteLine");
function computeCirclularFlight(arr: Obj, hasLine: boolean = true) {for (const key in arr) {if (Object.prototype.hasOwnProperty.call(arr, key)) {const element = arr[key];const property = new Cesium.SampledPositionProperty();const length = element.positions.lengthconst positions: number[] = []let p, tfor (let index = 0; index < length; index++) {p = element.positions[index]t = element.times[index]property.addSample(Cesium.JulianDate.addHours(Cesium.JulianDate.fromDate(new Date(t)), 8, new Cesium.JulianDate()), Cesium.Cartesian3.fromDegrees(p[0], p[1], p[2]));positions.push(...element.positions[index])}satellites.entities.add({id: key,model: {uri: element.country === 'US' ? 'models/satellite/satellite1/Satellite.gltf': element.country === 'PRC' ? 'models/satellite/satellite2/10477_Satellite_v1_L3.gltf' : 'models/satellite/satellite3/satellite.gltf',minimumPixelSize: 32},position: property,});if (hasLine)polylines.entities.add({id: key,polyline: {width: 1,material: Cesium.Color.BLUE.withAlpha(.5),positions: Cesium.Cartesian3.fromDegreesArrayHeights(positions)}})}}viewer.dataSources.add(satellites);viewer.dataSources.add(polylines);
}

加载卫星和轨迹的效果

加载地面雷达

const radars = new Cesium.CustomDataSource("radar");
const radarpoints: {id: string;lon: number;lat: number;radius: number
}[] = [{ id: 'radar1', lon: 104, lat: 34, radius: 300000 },{ id: 'radar2', lon: -100, lat: 55, radius: 300000 },{ id: 'radar3', lon: 109.70841, lat: 19.365791, radius: 300000 },]//添加雷达radarpoints.forEach(i => {createRadar(i.id, i.lon, i.lat, i.radius)})function createRadar(id: string, lon: number, lat: number, radius: number) {radars.entities.add({id: id,model: {uri: 'models/antenna_07.glb',minimumPixelSize: 32,},position: Cesium.Cartesian3.fromDegrees(lon, lat),})viewer.dataSources.add(radars)new LCesiumApi.RadarPrimitive({radius: radius,stackPartitions: 10,slicePartitions: 10,stackDegrees: {x: 0,y: 90,},sliceDegrees: {x: 0,y: 360,},color: Cesium.Color.GREEN.withAlpha(0.2),lineColor: Cesium.Color.RED,scanColor: Cesium.Color.YELLOW.withAlpha(0.2),scanLineColor: Cesium.Color.RED,scene: viewer.scene,center: Cesium.Cartesian3.fromDegrees(lon, lat),scanSpeed: 5000,show: true,scan: true,});
}

关于雷达效果在我之前文章里面有

卫星与地面雷达通信

  • 暂时只做了m(雷达)-n(卫星),m*n;没有做卫星之间的通信判断,不过原理都是一样的.
  • 网上搜索了一下通信距离一般是3,580km
  • 计算此时卫星距雷达的距离,其实就是计算带高度的经纬度之间的距离
Cartesian3.distance(point1: Cartesian3, point2: Cartesian3)

当卫星和地面卫星通信时,创建连线,离开设置为隐藏。

function computeRange() {satellites.entities.values.forEach(i => {radars.entities.values.forEach(j => {const po1 = i.position?.getValue(viewer.clock.currentTime)const po2 = j.position?.getValue(viewer.clock.currentTime)if (po1 && po2) {const len = LCesiumApi.Tool.getDistanceFromCartesian3(po1, po2)if (len <= communicationRange) {if (showFlyObject[`${i.id}-${j.id}`]) {showFlyObject[`${i.id}-${j.id}`].show = trueshowFlyObject[`${i.id}-${j.id}`].po1 = LCesiumApi.Tramsform.degreesFromCartesian(po1)showFlyObject[`${i.id}-${j.id}`].po2 = LCesiumApi.Tramsform.degreesFromCartesian(po2)}else {showFlyObject[`${i.id}-${j.id}`] = {entity: null,show: true,po1: LCesiumApi.Tramsform.degreesFromCartesian(po1),po2: LCesiumApi.Tramsform.degreesFromCartesian(po2)}}} else {if (showFlyObject[`${i.id}-${j.id}`]) showFlyObject[`${i.id}-${j.id}`].show = false}}})})setLine()
}
function setLine() {for (const key in showFlyObject) {if (Object.prototype.hasOwnProperty.call(showFlyObject, key)) {const element = showFlyObject[key];if (element.entity === null) element.entity = createFlyLine(key)element.entity.show = element.show}}
}
function createFlyLine(id: string) {var material = new PolylineTrailLinkMaterialProperty({color: Cesium.Color.fromCssColorString('#7ffeff'),duration: 3000,});const line = Connection.entities.add({id: id,polyline: {positions: new Cesium.CallbackProperty(() => {return Cesium.Cartesian3.fromDegreesArrayHeights([showFlyObject[id].po1.longitude,showFlyObject[id].po1.latitude,showFlyObject[id].po1.height,showFlyObject[id].po2.longitude,showFlyObject[id].po2.latitude,showFlyObject[id].po2.height,])}, false),width: 8,material}})return line
}

完整代码

<template><Map @onViewerLoaded="onViewerLoaded" :options="options" />
</template>
<script lang="ts" setup>
import Map from "@/components/Cesium/lib/Map.vue";
import * as Cesium from "cesium";
import { message } from 'ant-design-vue'
import {twoline2satrec, gstime, eciToGeodetic,PositionAndVelocity, propagate, EciVec3,degreesLong
} from 'satellite.js';
import LCesiumApi from "@lib/main";
//@ts-ignore
import { PolylineTrailLinkMaterialProperty } from './PolylineTrailMaterialProperty.js'
const options = {imageryProvider: new Cesium.ArcGisMapServerImageryProvider({url: 'https://services.arcgisonline.com/ArcGIS/rest/services/World_Imagery/MapServer'}),
}
let viewer: Cesium.Viewer
let start: Cesium.JulianDate
let stop: Cesium.JulianDate
let handler: Cesium.ScreenSpaceEventHandler;
const communicationRange = 3580000;
const time = new Date()
let max = time.getTime()
let year = 31622400000;
let min = max - year;
type Obj = {[index: string]: {country: string;times: number[];positions: [[number, number, number]] | number[][]}
}
const showFlyObject: {[index: string]: any
} = {}
let obj: Obj = {}
const radarpoints: {id: string;lon: number;lat: number;radius: number
}[] = [{ id: 'radar1', lon: 104, lat: 34, radius: 300000 },{ id: 'radar2', lon: -100, lat: 55, radius: 300000 },{ id: 'radar3', lon: 109.70841, lat: 19.365791, radius: 300000 },]
const onViewerLoaded = (Viewer: Cesium.Viewer) => {viewer = Viewerhandler = new Cesium.ScreenSpaceEventHandler(viewer.canvas);//设置时间轴setTimeline()//读取卫星分布两行数据const nowTime = time.getTime()fetch("data/points.json").then(res => res.json()).then(data => {for (const key in data) {if (Object.prototype.hasOwnProperty.call(data, key)) {const element = data[key];const satrec = twoline2satrec(element.data[0], element.data[1]);const positionAndVelocity: PositionAndVelocity = propagate(satrec, time);const positionEci = positionAndVelocity.position as EciVec3<number>;obj[key] = {country: element.country,times: [],positions: []};let lon, lat, alt;//一年365天 一天为间隔for (let index = min; index <= nowTime; index = index + 86400000) {const gmst = gstime(new Date(index));const positionGd = eciToGeodetic(positionEci, gmst)lon = positionGd.longitude,lat = positionGd.latitude,alt = positionGd.height;obj[key].times.push(index)obj[key].positions.push([degreesLong(lon), degreesLong(lat), alt])}}}computeCirclularFlight(obj)})//添加点击事件addPick()//添加雷达radarpoints.forEach(i => {createRadar(i.id, i.lon, i.lat, i.radius)})//添加过境扫描; (viewer as any).frameUpdate.addEventListener((delta: any) => {computeRange()});
}
function setTimeline() {start = Cesium.JulianDate.fromDate(new Date(min));  // 获取当前时间 这不是国内的时间start = Cesium.JulianDate.addHours(start, 8, new Cesium.JulianDate());  // 添加八小时,得到我们东八区的北京时间stop = Cesium.JulianDate.fromDate(new Date(max));  // 设置一个结束时间,意思是360秒之后时间结束viewer.clock.startTime = start.clone();   // 给cesium时间轴设置开始的时间,也就是上边的东八区时间viewer.clock.stopTime = stop.clone();     // 设置cesium时间轴设置结束的时间viewer.clock.currentTime = start.clone(); // 设置cesium时间轴设置当前的时间viewer.clock.clockRange = Cesium.ClockRange.LOOP_STOP;  // 时间结束了,再继续重复来一遍//时间变化来控制速度 // 时间速率,数字越大时间过的越快viewer.clock.multiplier = 1;//给时间线设置边界viewer.timeline.zoomTo(start, stop);
}
const satellites = new Cesium.CustomDataSource("satellite");
const polylines = new Cesium.CustomDataSource("statelliteLine");
const radars = new Cesium.CustomDataSource("radar");
const Connection = new Cesium.CustomDataSource("connection");
function computeCirclularFlight(arr: Obj, hasLine: boolean = true) {for (const key in arr) {if (Object.prototype.hasOwnProperty.call(arr, key)) {const element = arr[key];const property = new Cesium.SampledPositionProperty();const length = element.positions.lengthconst positions: number[] = []let p, tfor (let index = 0; index < length; index++) {p = element.positions[index]t = element.times[index]property.addSample(Cesium.JulianDate.addHours(Cesium.JulianDate.fromDate(new Date(t)), 8, new Cesium.JulianDate()), Cesium.Cartesian3.fromDegrees(p[0], p[1], p[2]));positions.push(...element.positions[index])}satellites.entities.add({id: key,model: {uri: element.country === 'US' ? 'models/satellite/satellite1/Satellite.gltf': element.country === 'PRC' ? 'models/satellite/satellite2/10477_Satellite_v1_L3.gltf' : 'models/satellite/satellite3/satellite.gltf',minimumPixelSize: 32},position: property,});if (hasLine)polylines.entities.add({id: key,polyline: {width: 1,material: Cesium.Color.BLUE.withAlpha(.5),positions: Cesium.Cartesian3.fromDegreesArrayHeights(positions)}})}}viewer.dataSources.add(satellites);viewer.dataSources.add(polylines);viewer.dataSources.add(Connection)
}
const addPick = () => {handler.setInputAction((movement: any) => {const pickedObject = viewer.scene.pick(movement.position);if (Cesium.defined(pickedObject)) {message.info(pickedObject.id.id)}}, Cesium.ScreenSpaceEventType.LEFT_CLICK)
}
function createRadar(id: string, lon: number, lat: number, radius: number) {radars.entities.add({id: id,model: {uri: 'models/antenna_07.glb',minimumPixelSize: 32,},position: Cesium.Cartesian3.fromDegrees(lon, lat),})viewer.dataSources.add(radars)new LCesiumApi.RadarPrimitive({radius: radius,stackPartitions: 10,slicePartitions: 10,stackDegrees: {x: 0,y: 90,},sliceDegrees: {x: 0,y: 360,},color: Cesium.Color.GREEN.withAlpha(0.2),lineColor: Cesium.Color.RED,scanColor: Cesium.Color.YELLOW.withAlpha(0.2),scanLineColor: Cesium.Color.RED,scene: viewer.scene,center: Cesium.Cartesian3.fromDegrees(lon, lat),scanSpeed: 5000,show: true,scan: true,});
}
function computeRange() {satellites.entities.values.forEach(i => {radars.entities.values.forEach(j => {const po1 = i.position?.getValue(viewer.clock.currentTime)const po2 = j.position?.getValue(viewer.clock.currentTime)if (po1 && po2) {const len = LCesiumApi.Tool.getDistanceFromCartesian3(po1, po2)if (len <= communicationRange) {if (showFlyObject[`${i.id}-${j.id}`]) {showFlyObject[`${i.id}-${j.id}`].show = trueshowFlyObject[`${i.id}-${j.id}`].po1 = LCesiumApi.Tramsform.degreesFromCartesian(po1)showFlyObject[`${i.id}-${j.id}`].po2 = LCesiumApi.Tramsform.degreesFromCartesian(po2)}else {showFlyObject[`${i.id}-${j.id}`] = {entity: null,show: true,po1: LCesiumApi.Tramsform.degreesFromCartesian(po1),po2: LCesiumApi.Tramsform.degreesFromCartesian(po2)}}} else {if (showFlyObject[`${i.id}-${j.id}`]) showFlyObject[`${i.id}-${j.id}`].show = false}}})})setLine()
}
function setLine() {for (const key in showFlyObject) {if (Object.prototype.hasOwnProperty.call(showFlyObject, key)) {const element = showFlyObject[key];if (element.entity === null) element.entity = createFlyLine(key)element.entity.show = element.show}}
}
function createFlyLine(id: string) {var material = new PolylineTrailLinkMaterialProperty({color: Cesium.Color.fromCssColorString('#7ffeff'),duration: 3000,});const line = Connection.entities.add({id: id,polyline: {positions: new Cesium.CallbackProperty(() => {return Cesium.Cartesian3.fromDegreesArrayHeights([showFlyObject[id].po1.longitude,showFlyObject[id].po1.latitude,showFlyObject[id].po1.height,showFlyObject[id].po2.longitude,showFlyObject[id].po2.latitude,showFlyObject[id].po2.height,])}, false),width: 8,material}})return line
}
</script>

Cesium 卫星轨迹、卫星通信、卫星过境,模拟数据传输。相关推荐

  1. Cesium专栏-卫星轨迹

    Cesium Cesium 是一款面向三维地球和地图的,世界级的JavaScript开源产品.它提供了基于JavaScript语言的开发包,方便用户快速搭建一款零插件的虚拟地球Web应用,并在性能,精 ...

  2. 利用计算机测地震是计算机的什么,计算机在气象预报、地震探测、导弹卫星轨迹等方面的应用都属于( )...

    参考答案如下 计算机在气象预报.计算机地震探测.导弹卫星轨迹等方面的应用都属于( ) 气象[单选题]关于第四代计算机的特点描述错误的是( ) [单选题]徽派民居建筑风格有"三绝"- ...

  3. matlab 画卫星轨道,Matlab仿真实例-卫星轨迹

    卫星轨迹 一.问题提出 设卫星在空中运行的运动方程为: d2rkd 2 r() 22 dtrdt 2 d 2drd rdtdt dt2 其中是k重力系数(k=401408km3/s).卫星轨道采用极坐 ...

  4. 怎样做ppt如何用PPT绘制卫星轨迹图形表达?

    本文来自BX教程网www.benxitj.com:整理编辑 - 原文出处 www.benxitj.com/Article/?406/59.html 转载注明 怎样做ppt PPT制造本领:若何用PPT ...

  5. matlab给定坐标画卫星轨道,Matlab仿真实例-卫星轨迹

    卫星轨迹 一.问题提出 设卫星在空中运行的运动方程为: 其中是k 重力系数(k=401408km3/s).卫星轨道采用极坐标表示,通过仿真,研究发射速度对卫星轨道的影响.实验将作出卫星在地球表面(r= ...

  6. 遥感图像卫星概述--海洋卫星,资源卫星,商用卫星

    遥感图像卫星–资料搜集 文章目录 遥感图像卫星--资料搜集 海洋卫星 1.数据处理的特点 2.难点与挑战 3.具体方法 资源卫星 1.数据处理的特点 2.难点与挑战 3.具体方法 商用卫星 1.数据处 ...

  7. 有趣的Hack-A-Sat黑掉卫星挑战赛——跟踪卫星

    国家太空安全是国家安全在空间领域的表现.随着太空技术在政治.经济.军事.文化等各个领域的应用不断增加,太空已经成为国家赖以生存与发展的命脉之一,凝聚着巨大的国家利益,太空安全的重要性日益凸显[1].而 ...

  8. “用手机就能访问卫星” 软件定义升级卫星智能

    ▲"天智一号"是全球首颗实际开展工程研制并发射的软件定义卫星.软件所供图 来源: 中国科学报 ▲专家学者探讨开源.开放的航天生态环境.沈春蕾摄 "假设未来30年将发射10 ...

  9. 【实战】物联网安防监控项目【5】———把模拟数据传输到web网页、web显示mjpeg-streamer视频图像

    1.模拟数据传输到web 为了把硬件传感器上的数据上传到web网页,我们需要在跑linux服务器的开发板上写一个应用程序,并创建出几个线程来收集传感器检测到的数据,通过进程/线程间通信.boa与cgi ...

最新文章

  1. 1.5w字,30图带你彻底掌握 AQS!
  2. 第十八课.动态图模型
  3. Android 启动模式简介
  4. python中fn的用法_Pytorch技巧:DataLoader的collate_fn参数使用详解
  5. 微信小程序适配iPhone X
  6. gh0st源码分析与远控的编写(二)
  7. [杂题训练]CF1228E Another Filling the Grid(容斥),CF936C Lock Puzzle(构造)
  8. spring集成mq_使用Spring Integration Java DSL与Rabbit MQ集成
  9. 算法题:输入一个表示整数的字符串,把该字符串转换成整数并输出。例如输入字符串“12345”,则输出整数“12345”
  10. [转载]PHP 计算时间差
  11. 4fsk调制matlab_数字调制解调技术的MATLAB与FPGA实现
  12. java冒泡排序_冒泡排序法丨java、python冒泡排序实现代码
  13. 视频+课件| 视觉引导系列课程-绪论
  14. 计蒜客-三值排序(贪心)
  15. 测开之路三十三:Flask实现扎金花游戏
  16. 关于OpenHarmony蜂窝通信框架能力的说明
  17. 三星正在完成android更新,三星发布Android 10更新计划表!又三款机型被选中,有你的吗?...
  18. ESP-WHO code_recognition 使用指南
  19. linux显示子系统-framebuffer架构分析
  20. 学习笔记:在Ubuntu16.04系统内安装Petalinux软件(包括如何安装Ubuntu16.04和相关支持库 详解)

热门文章

  1. Ubuntu 安装时出现“failed to load ldlinux.c32” 方法总结
  2. linux运维现在怎么样,浅谈现下Linux运维人员面临的问题
  3. java实例化对象例子
  4. 2023年软考信息安全工程师备考学习笔记汇总
  5. FlyMcu给STM32一键烧录程序
  6. ApiPost——高效生成接口文档好方法
  7. android随机数1 100,android 产生0~100之间的随机数
  8. Luedecke LPH-23
  9. labview控制 西门子S7-1200 1214 dcdcdcplc 程序
  10. SSH框架搭建整合详细步骤及运行流程