1. 介紹
SpaceDSL
是一個(gè)天體動(dòng)力學(xué)仿真庫。它使用C++編寫秤朗,為天體動(dòng)力學(xué)愛好者提供一個(gè)開放的框架以更自由的方式實(shí)現(xiàn)天體動(dòng)力學(xué)仿真煤蹭。本項(xiàng)目基于MIT協(xié)議開放源碼,以供自由使用取视。本項(xiàng)目通過CMake
構(gòu)建硝皂,可以用于Windows
、Linux
和Mac OS
作谭。SpaceDSL
庫可以被編譯成靜態(tài)庫稽物、動(dòng)態(tài)庫和Python依賴庫。當(dāng)然也支持直接使用。
1.1 核心特性
SpaceDSL
包含了有關(guān)天體動(dòng)力學(xué)仿真的全部基本功能,包括:
- 天文時(shí)間系統(tǒng):支持
EOP web Service
舅列,包含UTC倔丈、UT1和TT等多種時(shí)間系統(tǒng)的定義和轉(zhuǎn)換 - 參考坐標(biāo)系:包含ECI、TOD碉克、ECEF、VVLH等常用空間坐標(biāo)系的變換方程
- JPL星歷:重新打包了JPL星歷讀取模塊,提供最新的
DE436
文件羊赵,包括1950至2050年間的數(shù)據(jù) - 地球重力模型:使用
EGM2008
數(shù)據(jù)(80X80)和球諧函數(shù)構(gòu)建地球的高精度重力模型 - 其他攝動(dòng)模型:大氣阻力(
NRLMSISE2000
)、太陽輻射壓扇谣、第三天體重力(Third Body Gravity
) - 雙天體軌道預(yù)測(cè)昧捷、J2軌道預(yù)測(cè)和用于航天器的高精度軌道預(yù)測(cè)
- 多種地面目標(biāo)模型和訪問分析(
Access Analysis
) - 傳感器支持(
Simple Conic
和Rectangular
) - 常用物理常量
- 多線程并行支持:類似于
Qt
的API,包含線程和線程池 - 支持基于STL的異常處理
- 提供基于NLopt的非線性優(yōu)化庫
- 提供基于Electron和Cesium的可視化工具
1.2 后續(xù)支持的特性
- 攝動(dòng)模型:固體潮(
Earth Tide
)罐寨、相對(duì)論效應(yīng) - 航天器的相對(duì)運(yùn)動(dòng)仿真
- 軌道動(dòng)作仿真特性
- 軌道偏移量預(yù)測(cè)
2. 編譯
2.1 支持的編譯器
- Clang/LLVM 3.3 及以上版本(如果是Xcode的Clang靡挥,需要5.0.0及以上版本)
- GCC 7.2 及以上版本
- Microsoft Visual Studio 2015 Update 3 及以上版本
- Intel C++ compiler 16 及以上版本
2.2 編譯過程
克隆項(xiàng)目代碼:
git clone https://github.com/Astrodynamics/SpaceDSL.git
選擇
Build All
注意,如果平臺(tái)是Linux系統(tǒng)鸯绿,則在Build之前需要安裝以下依賴:(以Ubuntu 16.04系統(tǒng)為例,其他Linux系統(tǒng)下的安裝指令類似):
sudo apt-get install python-dev
sudo apt-get install python3-dev
編譯成功后跋破,文件中多出了Build文件夾,其中astrodata
是該庫需要的一些基礎(chǔ)數(shù)據(jù)文件瓶蝴,libNLOpt_d.dylib
和libSpaceDSL_d.0.0.dylib
等是動(dòng)態(tài)鏈接庫文件幔烛,PySpaceDSL_d.cpython-37m-darwin.so
是該項(xiàng)目使用python封裝后的依賴庫文件。
基于以上動(dòng)態(tài)鏈接庫和位于Build/Dependence
文件夾下的頭文件囊蓝,即可編寫C++代碼饿悬,進(jìn)行仿真,示例代碼如下:(TestMain.cpp)
#include <iostream>
#include "SpaceDSL/SpaceDSL.h"
using namespace std;
using namespace SpaceDSL;
int main(int argc, char *argv[])
{
cout<<"SpaceDSL Test Run!"<<endl;
try
{
/// Initial Data
UTCCalTime vehicle_epoch (2018,1,4,16,58,11.1);
string targetName1 = "Facility1";
PointTarget target1(targetName1, -75.5966*DegToRad, 40.0386*DegToRad, 0, 10*DegToRad);
string vehicle_name1 = "The First Vehicle";// h = 257km
CartState vehicle1_cart0(-5.04649e+06, -3.53951e+06, -2.44795e+06,
4954.67 , -4008.83, -4417.73 );
double vehicle1_mass = 1000.0;
string vehicle_name2 = "The Second Vehicle"; // h = 1065km
CartState vehicle2_cart0(-5.65484e+06, -3.96619e+06, -2.74305e+06,
4680.57 , -3787.06, -4173.34 );
double vehicle2_mass = 1500.0;
/// Mission Start
Mission *pMission = new Mission();
auto pVehicle1 = pMission->InsertSpaceVehicle(vehicle_name1,vehicle_epoch,vehicle1_cart0,vehicle1_mass, 2.2, 3, 1.0, 3);
auto pVehicle2 = pMission->InsertSpaceVehicle(vehicle_name2,vehicle_epoch,vehicle2_cart0,vehicle2_mass, 2.2, 6, 1.0, 6);
pMission->RemoveSpaceVehicle(pVehicle2->GetID());
pMission->InsertFacility(targetName1,-75.5966*DegToRad, 40.0386*DegToRad, 0, 10*DegToRad);
ThirdBodyGravitySign thirdGravSign;
thirdGravSign.bIsUseSunGrav = true;
thirdGravSign.bIsUseMoonGrav = true;
double kp = 3.0;
VectorXd ap;
ap.resize(7);
ap.fill(0.0);
ap(0) = GeomagneticKpToAp(kp);
pMission->SetEnvironment(E_Earth, GravityModel::GravModelType::E_EGM08Model,
20 , 20, thirdGravSign,
GeodeticCoordSystem::GeodeticCoordType::E_WGS84System,
AtmosphereModel::AtmosphereModelType::E_NRLMSISE00Atmosphere,
150,150,ap,
true, true);
pMission->SetPropagator(E_RungeKutta4, 60);
//pMission->SetPropagator(E_RungeKutta78, 60, 0.01, 1, 120, 100);
UTCCalTime initial_time (2018,1,5,16,58,11.1);
pMission->SetMissionSequence(initial_time, 86123);
pMission->Start(true);
cout<<"------First Calculation Finished ------"<<endl;
pMission->CalMissionAccessData();
auto accessListMap = pMission->GetAccessData();
for (auto iterMap = accessListMap->begin();
iterMap != accessListMap->end();
++iterMap)
{
cout<<"Access Data:"<<endl;
cout<<iterMap->first.first->GetName()<<"--------"<<iterMap->first.second->GetName()<<endl;
cout<<" Start Time (UTCG) Stop Time (UTCG) Duration (sec)"<<endl;
auto accessList = iterMap->second;
for(auto &data:accessList)
{
double mjd = CalendarTimeToMjd(data.first);
cout.precision(15);
cout<<mjd<<" "<<data.first.ToString()<<" "<<data.second.ToString()<<" "<<(data.second - data.first)<<endl;
}
}
pVehicle1->Reset();
pMission->ClearProcessData();
pMission->Start();
pMission->CalMissionAccessData();
cout<<"------Second Calculation Finished ------"<<endl;
accessListMap = pMission->GetAccessData();
for (auto iterMap = accessListMap->begin();
iterMap != accessListMap->end();
++iterMap)
{
cout<<"Access Data:"<<endl;
cout<<iterMap->first.first->GetName()<<"--------"<<iterMap->first.second->GetName()<<endl;
cout<<" Start Time (UTCG) Stop Time (UTCG) Duration (sec)"<<endl;
auto accessList = iterMap->second;
for(auto &data:accessList)
{
double mjd = CalendarTimeToMjd(data.first);
cout.precision(15);
cout<<mjd<<" "<<data.first.ToString()<<" "<<data.second.ToString()<<" "<<(data.second - data.first)<<endl;
}
}
//CalObservationAll();
cout<<"Calculation Finished!"<<endl;
/// CZML File Wirte;
CZMLScript script;
script.Initializer("TestData.czml", pMission);
script.WirteCZML();
cout<<"CZML Output Finished!"<<endl;
pMission->Destory();
}
catch (SPException &e)
{
e.what();
}
return 0;
}
通過Python封裝過的依賴庫PySpaceDSL
聚霜,可以使用Python編寫仿真代碼狡恬。
將PySpaceDSL_d.cpython-37m-darwin.so
文件重命名為PySpaceDSL.so
珠叔,同時(shí)在當(dāng)前路徑下放置astrodata
基礎(chǔ)數(shù)據(jù)文件夾,編寫Python腳本(TestPython.py):
from PySpaceDSL import *
import numpy as np
print("SpaceDSL Test Run!")
def main():
# Initial Data
initial_time = UTCCalTime(2018, 1, 4, 16, 58, 11.1)
vehicle1_cart0 = CartState(-5.04649e+06, -3.53951e+06, -2.44795e+06, 4954.67, -4008.83, -4417.73)
vehicle1_mass = 1000.0
vehicle2_cart0 = CartState(-5.65484e+06, -3.96619e+06, -2.74305e+06, 4680.57, -3787.06, -4173.34)
vehicle2_mass = 1500.0
# Mission Start
test_mission = Mission()
test_mission.InsertSpaceVehicle('The First Vehicle', initial_time, vehicle1_cart0, vehicle1_mass, 2.2, 3, 1.0, 3)
test_mission.InsertSpaceVehicle('The Second Vehicle', initial_time, vehicle2_cart0, vehicle2_mass, 2.2, 6, 1.0, 6)
test_mission.InsertFacility('Facility1', -75.5966 * DegToRad(), 40.0386 * DegToRad(), 0, 10 * DegToRad())
thirdGravSign = ThirdBodyGravitySign()
thirdGravSign.bIsUseSunGrav = True
thirdGravSign.bIsUseMoonGrav = True
kp = 3.0
ap = np.zeros(7)
ap[0] = GeomagneticKpToAp(kp)
test_mission.SetEnvironment(SolarSysStarType.E_Earth, GravityModel.GravModelType.E_EGM08Model, 20, 20,
thirdGravSign, GeodeticCoordSystem.GeodeticCoordType.E_WGS84System,
AtmosphereModel.AtmosphereModelType.E_NRLMSISE00Atmosphere,
150, 150, ap, True, True)
test_mission.SetPropagator(IntegMethodType.E_RungeKutta4, 60.0)
test_mission.SetMissionSequence(initial_time, 86400)
test_mission.Start(True)
print('------First Calculation Finished ------')
test_mission.CalMissionAccessData()
accessListMap = test_mission.GetAccessData()
print(accessListMap)
# CZML File Wirte;
script = CZMLScript()
script.Initializer("PyTestData.czml", test_mission)
script.WirteCZML()
print("CZML Output Finished!")
if __name__ == "__main__":
main()
運(yùn)行程序弟劲,會(huì)在當(dāng)前目錄生成一個(gè).CZML
后綴的文件祷安。CMZL文件是一種用來描述動(dòng)態(tài)場(chǎng)景的JSON架構(gòu)的語言,主要用于Cesium在瀏覽器中的展示兔乞。這里的CZML文件就是用于可視化展示仿真結(jié)果的描述文件汇鞭。
3.使用說明
編寫C++程序或Python腳本完成仿真過程,并自動(dòng)生成.CZML
文件后庸追,可以通過SpaceDSL
自帶的可視化程序ElectronVisualizer
展示仿真結(jié)果霍骄。
首先需要在系統(tǒng)安裝Node.js環(huán)境。
然后切換到SpaceDSL
項(xiàng)目中的ElectronVisualizer
路徑下:
cd ElectronVisualizer
安裝相關(guān)依賴庫:
npm install --save-dev electron
npm install --save-dev cesium
npm install --save glob
然后淡溯,啟動(dòng)可視化軟件:
npm start
軟件啟動(dòng)后读整,點(diǎn)擊菜單Read Script
,選擇先前生成的.CZML
文件加載咱娶。
文件加載后米间,操作界面左下角的控制按鈕,即可播放仿真結(jié)果膘侮。