背景:
本次需要基于实现卫星模型扫描地球的业务。
技术栈采纳:
cesium 1.103.0
html
czml
记录:
1.卫星轨道数据获取
地址:https://www.space-track.org/#catalog
我这里抉择获取fengyun的数据,能够失去一个TLE格局的两行数据
2.卫星轨道数据通用转换
因为有了tle数据,这里也抉择去用sgp4来将数据转换成czml格式文件。
#!/usr/bin/python# -*- coding:utf8 -*-"""本脚本依据TLE文件生成每颗卫星的CMZL文件,用于前端js应用Cesium显示卫星轨道"""# sgp4算法依据二行星历计算每个工夫点卫星的地位from sgp4.earth_gravity import wgs84from sgp4.io import twoline2rvimport datetimeimport json# 按行读取北斗两行星历文件# 每三行标识一个卫星,格局如下:# FENGYUN 1A# 1 19467U 88080A 23086.12932362 -.00000103 00000-0 -36906-4 0 9992# 2 19467 99.1890 121.7932 0014370 10.7878 349.3593 14.03214030768865# 星历下载地址:http://celestrak.com/with open('fengyun.txt', 'r') as f: data_lines = f.read().split('\n')#TLE每颗卫星数据必须三行:第一行名称,后两行数据"# 应用字典的数组(json文件)保留每颗卫星的轨道六根数orbit_info = {}# 每三行一组,遍历所有卫星for j in range(len(data_lines) // 3): # 第一行名字,后两行数据 # 数据具体阐明:http://celestrak.com/columns/v04n03/ name = data_lines[j * 3].strip() line1 = data_lines[1 + j * 3] line2 = data_lines[2 + j * 3] # 写轨道六根数到json文件 # print("卫星轨道倾斜角", line2[8:16], "度") # print("升交点赤经", line2[17:25], "度") # print("偏心率", line2[26:33]) # print("近地点角距", line2[34: 42], "度") # print("平近点角", line2[43:51], "度") # print("均匀静止(每天绕地球圈数)", line2[52:63]) orbit_info.update({ name: { 'Inclination': line2[8:16], 'Right Ascension of the Ascending Node'.replace(' ', '_'): line2[17:25], 'Eccentricity': line2[26:33], 'Argument of Perigee'.replace(' ', '_'): line2[34: 42], 'Mean Anomaly'.replace(' ', '_'): line2[43:51], 'Mean Motion'.replace(' ', '_'): line2[52:63] } }) # 卫星每转1°所经验的工夫(单位:秒) gap = 1. / float(line2[52:63]) * 24 * 60 * 60 / 360 # 调用sgp4算法计算星历每个时刻的地位 satellite = twoline2rv(line1, line2, wgs84) assert satellite.error == 0 # 记录以后工夫,并在循环中计算出一个周期后的工夫 # 用于在CZML文件中指定interval now_time = datetime.datetime.now() next_time = datetime.datetime.now() # 保留每1°变动后卫星的地位(x, y, z):示意具体地心的间隔(单位:km) position_list = [] # 循环一圈 # 每次距离gap秒 nums = 361 for i in range(nums): # next_time示意每个地位对应的工夫点 next_time = now_time + datetime.timedelta(seconds=gap * (i + 1)) # 示意为字典,不便propagate函数的计算 next_time_str = next_time.strftime('%Y %m %d %H %M %S').split(' ') next_time_str = [int(v) for v in next_time_str] time_key = ['year', 'month', 'day', 'hour', 'minute', 'second'] time_map = dict(zip(time_key, next_time_str)) # 调用sgp4库的propagate函数计算对应时刻的地位 position, velocity = satellite.propagate( year=time_map['year'], month=time_map['month'], day=time_map['day'], hour=time_map['hour'], minute=time_map['minute'], second=time_map['second'] ) # The position vector measures the satellite position in kilometers from the center of the earth. # CZML文件中position的格局为:(time, x, y, z, time, x, y, z...) position_list.append(next_time.isoformat()) position_list.append(position[0] * 1000) position_list.append(position[1] * 1000) position_list.append(position[2] * 1000) # 格式化为ISO工夫规范格局 begin = str(now_time.isoformat()) end = str((next_time + datetime.timedelta(seconds=gap)).isoformat()) # Write the CZML document to a file filename = "D:/test/{}.czml".format(name) # 初始化CZML # CZML实际上是JSON文件,JSON文件就是字典数组 # 所以应用字典数据结构示意每个卫星 doc = [] # 定义头部 header = { # id和version为固定格局 'id': "document", "version": "1.0", 'name': name, "clock": { # interval为无效工夫,currentTime示意起始点,multiplier示意时钟速度 "interval": '{}/{}'.format(begin, end), "currentTime": begin, "multiplier": gap } } doc.append(header) # 定义主体 body = { "id": "satellites/{}".format(name), "availability": '{}/{}'.format(begin, end), "label": { # 应用label显示卫星名字 "font": "11pt Lucida Console", "outlineWidth": 2, "outlineColor": {"rgba": [0, 0, 0, 255]}, "horizontalOrigin": "LEFT", "pixelOffset": {"cartesian2": [12, 0]}, "fillColor": {"rgba": [213, 255, 0, 255]}, "text": name }, "path": { # path定义轨道的款式 "material": { "polyline": { "color": { "rgba": [255, 0, 255, 255] } } }, "width": 1, "resolution": 120 }, "billboard": { # 卫星的图标,应用base64编码表示图片 "image": "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsMAAA7DAcdvqGQAAADJSURBVDhPnZHRDcMgEEMZjVEYpaNklIzSEfLfD4qNnXAJSFWfhO7w2Zc0Tf9QG2rXrEzSUeZLOGm47WoH95x3Hl3jEgilvDgsOQUTqsNl68ezEwn1vae6lceSEEYvvWNT/Rxc4CXQNGadho1NXoJ+9iaqc2xi2xbt23PJCDIB6TQjOC6Bho/sDy3fBQT8PrVhibU7yBFcEPaRxOoeTwbwByCOYf9VGp1BYI1BA+EeHhmfzKbBoJEQwn1yzUZtyspIQUha85MpkNIXB7GizqDEECsAAAAASUVORK5CYII=", "scale": 1.5 }, "position": { # cartesian的格局:(time, x, y, z, time, x, y, z...) "referenceFrame": "FIXED", # 能够取FIXED和INERTIAL示意固定和惯性参考系 # 插值填补轨道 "interpolationDegree": 5, "interpolationAlgorithm": "LAGRANGE", "epoch": begin, "cartesian": position_list } } # 在body中增加position doc.append(body) # 应用JSON写CZML文件 with open(filename, 'w') as f: json.dump(doc, f)
原创作者地址:https://segmentfault.com/u/yourena_c
3.cesium加载卫星轨道数据
<!DOCTYPE html><html lang="en"><head> <title>Cesium CZML Example</title> <script src="https://cdn.bootcdn.net/ajax/libs/cesium/1.103.0/Cesium.js"></script> <link href="https://cdn.bootcdn.net/ajax/libs/cesium/1.103.0/Widgets/widgets.css" rel="stylesheet"> <style> html, body, #cesiumContainer { width: 100%; height: 100%; margin: 0; padding: 0; overflow: hidden; } </style></head><body> <div id="cesiumContainer"></div> <script> // 初始化Cesium Viewer var viewer = new Cesium.Viewer('cesiumContainer'); // 创立CzmlDataSource var dataSource = new Cesium.CzmlDataSource(); // 加载CZML数据 dataSource.load('./fengyun.czml').then(function() { // 增加数据到Viewer viewer.dataSources.add(dataSource); // 调整视角以查看数据 viewer.zoomTo(dataSource); }); </script></body></html>
后续增加gltf卫星模型和扫描成果