关于如何在STK中根据TLE数据插入卫星对象,参见本人另一篇文章:
本回文探索如何利用STK提供的实例代码和接口直接通过VC++编程,由TLE数据插入卫星对象。
预分析:
根据对STK的初步学习,在加入卫星对象时,STK首先创建一个卫星对象,可以什么也不做(不进行设置),此时的对象是一个空对象(只有名称,没有相关配置参数),直观的结果就是二三维视窗不会有对应的对象显示,说明STK还没有进行(与卫星有关的轨道)计算。这点与其他对象不同,例如加入地面设施,不需要进行对象属性配置(例如地面设施的经纬度设置),场景中会在当前默认的位置增加一个地面设施对象,并同时在二三维场景中显示。
有了空的卫星对象后,应当继续借助卫星对象的属性配置窗口或卫星轨道向导工具对卫星的相关属性进一步配置,例如轨道六根数、轨道预报器类型等,在对相关操作进行确认后,STK会根据当前的设置进行轨道计算,应该是(个人判断)先把计算结果缓存了,后续进行动画仿真或显示只是一个查表的过程,所以在仿真的时候会感觉比较流畅。
当我们在动画(仿真)过程中进行对象的属性更新并确认时,二三维视窗的显示会有明显的卡顿,可能的原因就是STK在根据最新的变更进行计算,并在后台更新相应的数据。
如上所述,可以通过两种方式对卫星进行配置,一是通过对象属性窗口,包括卫星对象的‘Basic/基本’属性,还有二三维图形(显示)属性、约束(Constraints)、RF、DIS等属性配置。在基本属性配置中,会提供用户选择轨道预报器类型,然后根据轨道预报器的类型进行进一步的参数配置;另一种是通过轨道向导(Orbit Wizard)进行配置,此时提供给用户选择的是卫星轨道类型,例如圆轨道(Circle)、地球同步轨道(Geosynchronous)等。
在STK由TLE数据插入卫星的操作中,首先需要(从TLE数据文件)读入TLE数据,列表数据中包含的卫星对象,用户从列表选择相关对象后,点击确认,对象被加入到场景中。
这里有一个问题是仿真时间与卫星星历时间,TLE数据给出了每个卫星对象在某一时刻的数据,而场景的仿真时间是用户在新建场景时指定的,并且,加入多个TLE数据对象时,它们的TLE数据时刻(卫星星历)可能各不相同,STK在将对象加入到场景执行计算时,(个人猜测)应该是根据各个时间进行了调整。
所以如果是自行解析TLE数据,计算并获取相关的轨道参数,然后利用经典轨道参数方式(例如STK给出的示例项目Events)加入卫星对象,则需要解决仿真时间与卫星星历时间的转换问题,俺是非专业领域人士,还是看看STK是否提供了相关接口为妙。
TLE数据文件是与SGP4轨道预报器一起使用的,那我们就从SGP4轨道预报器开始。
// 注:文件 agstkobjects.tlh,第31327行开始定义,省略了本文分析的非必要信息 IAgVePropagatorSGP4 : IAgVePropagator { // 属性 _variant_t StartTime; _variant_t StopTime; double Step; IAgVeSGP4SegmentCollectionPtr Segments; VARIANT_BOOL UseScenarioAnalysisTime; VARIANT_BOOL AutoUpdateEnabled; // 是否根据TLE数据源自动更新 IAgVeSGP4AutoUpdatePtr AutoUpdate; // 自动更新设置 IAgVePropagatorSGP4CommonTasksPtr CommonTasks; // 从TLE源获取Segments IAgVeSGP4PropagatorSettingsPtr Settings; // SGP4预报器设置 // 方法 HRESULT Propagate(); _variant_t GetStartTime ( ); void PutStartTime (const _variant_t & pVal ); _variant_t GetStopTime ( ); void PutStopTime (const _variant_t & pVal ); double GetStep ( ); void PutStep (double pVal ); IAgVeSGP4SegmentCollectionPtr GetSegments ( ); VARIANT_BOOL GetUseScenarioAnalysisTime ( ); void PutUseScenarioAnalysisTime (VARIANT_BOOL pRetVal ); VARIANT_BOOL GetAutoUpdateEnabled ( ); void PutAutoUpdateEnabled (VARIANT_BOOL pRetVal ); IAgVeSGP4AutoUpdatePtr GetAutoUpdate ( ); IAgVePropagatorSGP4CommonTasksPtr GetCommonTasks ( ); IAgVeSGP4PropagatorSettingsPtr GetSettings ( ); }; |
除了一目了然的属性外,另外有三个属性:
- IAgVeSGP4SegmentCollectionPtr Segments;
- IAgVePropagatorSGP4CommonTasksPtr CommonTasks;
- IAgVeSGP4PropagatorSettingsPtr Settings
以及,一个方法:
- Propagatet() // 执行轨道计算
为清晰起见,利用VS2017集成编译环境提供的‘转到定义’功能,将SGP4轨道预报器相关的STK COM接口对象及属性画出来,如下图:
图中标记了小红旗的为关键属性或方法,分析如下:
SGP4预报器有两个重要属性:
- IAgVeSGP4SegmentCollectionPtr Segments
- IAgVePropagatorSGP4CommonTasksPtr CommonTasks
其中,Segments包含了当前有效的所有TLE对象(在SGP4接口类中称为‘Segment’)的集合,Segments有一个属性为IAgVeSGP4SegmentPtr Item[],那个‘Item[]’应该就是TLE对象数组,该接口类另外提供了一个接口类IAgVeSGP4LoadFile支持从TLE文件加载TLE对象(Segments)。
CommonTasks属性对象则另外提供了加载TLE对象的方法,即:AddSegsFromFile(),个人感觉通过该方法加入的Segments也保存在了SegmentCollection集合中。
开始尝试!
1、下载TLE数据
参考本人之前一篇文章‘STK9中根据TLE数据插入卫星对象’,下载中国空间站轨道参数,另存为文本文件,如下图:
2、定制界面
如下图,增加一个操作按钮,当新建场景后,允许通过TLE数据文件插入卫星对象。
3、定制按钮点击事件代码,如下:
如果对各文件(例如***Dlg.cpp, ***Helper.cpp)不熟悉,请参见本系列之前文章。
// ***Dlg.cpp // 通过TLE数据文件插入卫星对象,统一起见,均通过Helper执行实际的操作 void CEventsDlg::OnBnClickedAddtle() { try { CObjectModelHelper helper; helper.LoadTLE(m_pRoot); } catch (_com_error& err) { ReportComError(err); } UpdateDisplayState(); } |
// ObjectModelHelper.cpp // 由TLE数据(文件)添加卫星对象 void CObjectModelHelper::LoadTLE(STKObjects::IAgStkObjectRootPtr pRoot) { _bstr_t bstrName; _bstr_t bstrSSCNum; _bstr_t bstrTLEFile; IAgStkObjectPtr pNewObj; // STK Object IAgSatellitePtr pSat; // STK卫星对象 IAgVePropagatorSGP4Ptr pSGP4Prop; // SGP4轨道预报器 IAgVeSGP4SegmentCollectionPtr segments; // TLE对象集合 IAgVeSGP4LoadFilePtr pSGP4LoadFile; SAFEARRAY* pArray = NULL; // 确保首先执行了 NewScenario 操作 ASSERT(pRoot != NULL); // 参照STK的示例代码,首先获取当前场景,通过当前场景新增一个卫星对象 bstrName = "TianGong"; pNewObj = pRoot->GetCurrentScenario()->GetChildren()->New(eSatellite, bstrName); pSat = pNewObj; // 设置轨道预报器:SGP4。注:STK给的对外接口中定义了 15 种轨道预报器 pSat->SetPropagatorType(ePropagatorSGP4); pSGP4Prop = pSat->Propagator; // TLE数据 bstrSSCNum = "48274"; // 卫星编号,TLE轨道数据第1行以及第2行第03-07列(通常为5位数字) bstrTLEFile = "D:\\tledata_TianGong_220406.txt"; // 加载TLE数据,方法一:由CommonTask加入 // 此方法加入数据后,SGP4SegmentCollection会自动生效,即 Segments->Count 不为 0 if (pSGP4Prop->CommonTasks->AddSegsFromFile(bstrSSCNum, bstrTLEFile) != S_OK) { AfxMessageBox("Load TLE data failed!"); return; } // 加载TLE数据,方法二:由Segments对象加载 // 此方法加载数据后,SGP4SegmentCollection的Segments对象不会立刻生效,需要在调用轨道计算方法 // Propagate()之后才会生效 //segments = pSGP4Prop->Segments; //segments->LoadMethodType = eFileLoad; //pSGP4LoadFile = segments->LoadMethod; //pSGP4LoadFile->File = bstrTLEFile; //pArray = pSGP4LoadFile->GetSegsFromFile(bstrSSCNum); // 执行轨道计算(预报器计算,并显示) pSGP4Prop->Propagate(); if (pSGP4Prop->Segments->Count == 0) { AfxMessageBox("No valid TLE data loaded!"); } } |
经验证,两种方法都可以通过TLE数据成功加入卫星对象,效果如下图:
继续深入探讨之题目:
- 由上图可以看出,三维视窗绘制的卫星轨道明显可以看出是一个多边形,如何使之更平滑?
- 通过在SSCNum使用通配符,尝试通过TLE数据文件一次加载多个卫星对象。
- SGP4预报器支持自动更新,包括在线自动更新和基于本地数据文件的自动更新,值得尝试一下。