diff --git a/AstroLib.sln b/AstroLib.sln index 72c5ad097db1bd401ec75a1abe04916597c32d3b..b39cf851d43c64ebe1edd058a6ab6fe5d8312f0f 100644 --- a/AstroLib.sln +++ b/AstroLib.sln @@ -1,7 +1,7 @@  Microsoft Visual Studio Solution File, Format Version 12.00 -# Visual Studio 14 -VisualStudioVersion = 14.0.23107.0 +# Visual Studio Version 17 +VisualStudioVersion = 17.6.33829.357 MinimumVisualStudioVersion = 10.0.40219.1 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "AstroLib", "AstroLib\AstroLib.vcxproj", "{7EACEEBD-39A5-4708-8D6C-2AF7275FF08B}" EndProject @@ -22,6 +22,11 @@ Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Examples", "Examples\Exampl EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ParallelSim", "ParallelSim\ParallelSim.vcxproj", "{C5BD0DEB-8148-49C6-9000-5077C4A74E6D}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MultiRendezvous", "MultiRendezvous\MultiRendezvous.vcxproj", "{BA8DF975-D3D0-4E76-B967-901368AFFE4D}" + ProjectSection(ProjectDependencies) = postProject + {7EACEEBD-39A5-4708-8D6C-2AF7275FF08B} = {7EACEEBD-39A5-4708-8D6C-2AF7275FF08B} + EndProjectSection +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -66,8 +71,19 @@ Global {C5BD0DEB-8148-49C6-9000-5077C4A74E6D}.Release|Win32.Build.0 = Release|Win32 {C5BD0DEB-8148-49C6-9000-5077C4A74E6D}.Release|x64.ActiveCfg = Release|x64 {C5BD0DEB-8148-49C6-9000-5077C4A74E6D}.Release|x64.Build.0 = Release|x64 + {BA8DF975-D3D0-4E76-B967-901368AFFE4D}.Debug|Win32.ActiveCfg = Debug|Win32 + {BA8DF975-D3D0-4E76-B967-901368AFFE4D}.Debug|Win32.Build.0 = Debug|Win32 + {BA8DF975-D3D0-4E76-B967-901368AFFE4D}.Debug|x64.ActiveCfg = Debug|x64 + {BA8DF975-D3D0-4E76-B967-901368AFFE4D}.Debug|x64.Build.0 = Debug|x64 + {BA8DF975-D3D0-4E76-B967-901368AFFE4D}.Release|Win32.ActiveCfg = Release|Win32 + {BA8DF975-D3D0-4E76-B967-901368AFFE4D}.Release|Win32.Build.0 = Release|Win32 + {BA8DF975-D3D0-4E76-B967-901368AFFE4D}.Release|x64.ActiveCfg = Release|x64 + {BA8DF975-D3D0-4E76-B967-901368AFFE4D}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {C41E03FF-4D0A-44DF-AA4B-52A8CED3E8A7} + EndGlobalSection EndGlobal diff --git a/MultiRendezvous/MultiRendezvous.vcxproj b/MultiRendezvous/MultiRendezvous.vcxproj new file mode 100644 index 0000000000000000000000000000000000000000..410e7fcad3b9f23a001fd0e3b4ae9a8151f73468 --- /dev/null +++ b/MultiRendezvous/MultiRendezvous.vcxproj @@ -0,0 +1,165 @@ + + + + + Debug + Win32 + + + Release + Win32 + + + Debug + x64 + + + Release + x64 + + + + 16.0 + Win32Proj + {ba8df975-d3d0-4e76-b967-901368affe4d} + MultiRendezvous + 8.1 + + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + Application + true + v140 + Unicode + + + Application + false + v140 + true + Unicode + + + + + + + + + + + + + + + + + + + + + $(VC_IncludePath);$(WindowsSDK_IncludePath);../AstroLib + $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86../AstroLib + + + $(VC_IncludePath);$(WindowsSDK_IncludePath);../AstroLib + $(VC_LibraryPath_x86);$(WindowsSDK_LibraryPath_x86);$(NETFXKitsDir)Lib\um\x86../AstroLib + + + $(VC_IncludePath);$(WindowsSDK_IncludePath);../AstroLib + + + $(VC_IncludePath);$(WindowsSDK_IncludePath);../AstroLib + + + + Level3 + true + WIN32;_DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + .\;.\Src; + + + Console + true + + + + + Level3 + true + true + true + WIN32;NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + .\;.\Src; + + + Console + true + true + true + + + + + Level3 + true + _DEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + .\;.\Src + + + Console + true + + + + + Level3 + true + true + true + NDEBUG;_CONSOLE;%(PreprocessorDefinitions) + true + .\;.\Src + + + Console + true + true + true + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/MultiRendezvous/MultiRendezvous.vcxproj.filters b/MultiRendezvous/MultiRendezvous.vcxproj.filters new file mode 100644 index 0000000000000000000000000000000000000000..1b35f6bcc025bc9b997b8fceef8ceb5ea28d64c0 --- /dev/null +++ b/MultiRendezvous/MultiRendezvous.vcxproj.filters @@ -0,0 +1,54 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;c++;cppm;ixx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;h++;hm;inl;inc;ipp;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + 头文件 + + + + + 源文件 + + + 源文件 + + + 源文件 + + + 源文件 + + + \ No newline at end of file diff --git a/MultiRendezvous/MultiRendezvous.vcxproj.user b/MultiRendezvous/MultiRendezvous.vcxproj.user new file mode 100644 index 0000000000000000000000000000000000000000..88a550947edbc3c5003a41726f0749201fdb6822 --- /dev/null +++ b/MultiRendezvous/MultiRendezvous.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file diff --git a/MultiRendezvous/Src/ChCtrl.cpp b/MultiRendezvous/Src/ChCtrl.cpp new file mode 100644 index 0000000000000000000000000000000000000000..e32b2b79fa7aa250b468db99ca6811d3b7432d74 --- /dev/null +++ b/MultiRendezvous/Src/ChCtrl.cpp @@ -0,0 +1,262 @@ +// ChCtrl.cpp: implementation of the CChCtrl class. +// +////////////////////////////////////////////////////////////////////// + + +#include "ChCtrl.h" +#include "izzoLam.h" + + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CChCtrl::CChCtrl() +{ + m_UseMeasureRandom = 0; + m_UseEngineRandom = 0; + m_PosStdDev = 0; + m_VelStdDev = 0; + for (int i = 0; i < 100; i++) + { + m_FlyTime[i] = 0; + } + m_PulseNum = 0; +} + +CChCtrl::~CChCtrl() +{ + +} + + +//********************************************************************* +/// 初始化 +/// @author Wang Hua +/// @Date 2005.11.16 +//********************************************************************* +void CChCtrl::Init() +{ + for (int i = 0; i < 100; i++) + { + m_FlyTime[i] = 0; + } + m_PulseNum = 0; + + //随机数初始化 + int seed = AsRandomSeed(); + for (int i=0; i<3; i++) + { + m_RandomPos[i].Init(seed-i*3-1); + m_RandomVel[i].Init(seed-i*3-2); + m_RandomEng[i].Init(seed-i*3-3); + } +} + + +//******************************************************************** +/// 测量计算,包含测量误差 +/// @author Wang Hua +/// @Date 2022-6-29 +/// @Input +/// @Param chPos 追踪位置 +/// @Param chVel 追踪速度 +/// @Param tgPos 目标位置 +/// @Param tgVel 目标速度 +/// @Output +/// @Param relPos 相对位置 +/// @Param relVel 相对速度 +//******************************************************************** +void CChCtrl::Measure(const CCoord& chPos, const CCoord& chVel, + const CCoord& tgPos, const CCoord& tgVel, + CCoord& relPos, CCoord& relVel) +{ + //计算相对位置速度 + AsStateToVVLHRelState(chPos, chVel, tgPos, tgVel, relPos, relVel); + + //增加测量偏差 + if (m_UseMeasureRandom==0) + { + return; + } + else if (m_UseMeasureRandom==1) + { + relPos[0] += m_RandomPos[0].Gauss()*m_PosStdDev; + relPos[1] += m_RandomPos[1].Gauss()*m_PosStdDev; + relPos[2] += m_RandomPos[2].Gauss()*m_PosStdDev; + relVel[0] += m_RandomVel[0].Gauss()*m_VelStdDev; + relVel[1] += m_RandomVel[1].Gauss()*m_VelStdDev; + relVel[2] += m_RandomVel[2].Gauss()*m_VelStdDev; + } + +} + + +//******************************************************************** +/// 计算执行结构执行后的脉冲 +/// @author Wang Hua +/// @Date 2022-6-29 +/// @In/Out +/// @Param impulse 相对位置 +//******************************************************************** +void CChCtrl::Engine(CCoord& impulse) +{ + //增加测量偏差 + if (m_UseEngineRandom==0) + { + return; + } + else if (m_UseEngineRandom==1) + { + impulse[0] += m_RandomEng[0].Gauss()*m_EngStdDev; + impulse[1] += m_RandomEng[1].Gauss()*m_EngStdDev; + impulse[2] += m_RandomEng[2].Gauss()*m_EngStdDev; + } + +} + + +//******************************************************************** +/// 根据CW方程/lambert方程外推计算下一步需要施加的冲量 +/// @Author Wang Hua/Wang Hanwei +/// @Date 2005.11.17 +/// @Input +/// @Param chPos 追踪位置(m) +/// @Param chVel 追踪速度(m/s) +/// @Param tgPos 目标位置(m) +/// @Param tgVel 目标速度(m/s) +/// @Param endRelPos 制导终点所需相对位置(m) +/// @Param flyTime 制导飞行时间 +/// @Output +/// @Param impulse 计算得到的冲量 +//******************************************************************** +void CChCtrl::GuidanceImpulse1( + const CCoord& chPos, const CCoord& chVel, + const CCoord& tgPos, const CCoord& tgVel, + const CCoord& endRelPos, + double flyTime, CCoord& impulse) +{ + if(1){ + double orbAngVel; + CCoord OrbAngVelVec; + CCoord relPos, relVel, m_tgPos, m_tgVel, m_tgPos1, m_tgVel1; + Measure(tgPos, tgVel, chPos, chVel, relPos, relVel); + AsVVLHRelStateToState(relPos, relVel, chPos, chVel, m_tgPos, m_tgVel); + COrbit m_Orbit; + for (int i = 0; i < flyTime; i++) + { + m_Orbit.OrbitStep(1, m_tgPos, m_tgVel); + } + AsVVLHRelStateToState(endRelPos, CCoord(0,0,0), m_tgPos, m_tgVel, m_tgPos1, m_tgVel1); + m_tgPos = m_tgPos1; + double r1[3]{ chPos[0], chPos[1], chPos[2] }, r2[3]{ m_tgPos[0],m_tgPos[1],m_tgPos[2] }, tof = flyTime, mu = 3.986e14, v1[1][3], v2[1][3]; + int way = 1, multi_revs = 0; + solve_lambert_izzo(r1, r2, tof, mu, way, multi_revs, v1, v2); + CCoord impulse2(v1[0][0], v1[0][1], v1[0][2]); + AsStateToVVLHRelState(chPos, impulse2, chPos, chVel, m_tgPos, impulse); + Engine(impulse); + }else{ + double orbAngVel; + CCoord impulse2; + CCoord OrbAngVelVec; + CCoord relPos, relVel; + Measure(chPos, chVel, tgPos, tgVel, relPos, relVel); + AsCartStateToOrbAngVel(tgPos, tgVel, OrbAngVelVec); + orbAngVel = OrbAngVelVec.Norm(); + AsCWImpulse(relPos, relVel, endRelPos, + CCoord(0, 0, 0), flyTime, orbAngVel, impulse, impulse2); + Engine(impulse); + } + +} + + +//******************************************************************** +//根据CW方程外推计算下一步需要施加的冲量,准备开始调姿 +/// @Author Wang Hua +/// @Date 2005.11.17 +/// @Input +/// @Param chPos 追踪位置(m) +/// @Param chVel 追踪速度(m/s) +/// @Param tgPos 目标位置(m) +/// @Param tgVel 目标速度(m/s) +/// @Param endRelPos 制导终点所需相对速度(m/s) +/// @Output +/// @Param impulse 计算得到的冲量 +//******************************************************************** +void CChCtrl::GuidanceImpulse2(const CCoord& chPos, const CCoord& chVel, + const CCoord& tgPos, const CCoord& tgVel, + const CCoord& endRelVel, CCoord& impulse) +{ + CCoord relPos, relVel; + + Measure(chPos, chVel, tgPos, tgVel, relPos, relVel); + impulse = -relVel; +} + + +//********************************************************************* +/// 计算控制,直接加冲量 +/// @author Wang Hua +/// @Date 2006.8.12 +/// @Param step 时间步长 +/// @Param chPos 惯性系中的追踪器位置(m) +/// @Param chVel 惯性系中的追踪器速度(m/s) +/// @Param tgPos 惯性系中的目标器位置(m) +/// @Param tgVel 惯性系中的目标器速度(m/s) +/// @Param flyTimeApproach 接近段飞行时间 +/// @Output +/// @Param isEnd 是否本阶段结束 +/// @Param impulse VVLH系中的脉冲 +/// @Return +//********************************************************************* +void CChCtrl::TimeAdvance(double step, + const CCoord& chPos, const CCoord& chVel, + const CCoord& tgPos, const CCoord& tgVel, + double flyTimeApproach, const CCoord& endPos, + bool& isEnd, CCoord& impulse, int aim) +{ + isEnd = false; + impulse.SetDataAll(0); + + //至终端 + if (m_PulseNum==0) + { + m_PulseNum = 1; + GuidanceImpulse1(chPos, chVel, tgPos, tgVel, endPos, flyTimeApproach, impulse); + double t = 0; + for (int i = 0; i <= 3; i++) + { + t = t + m_FlyTime[i]; + } + CCTime c_t(2024, 3, 11, 12, 0, 0.0+t); + AsTimeToJD(c_t, t); + printf("儒略日(JD):%f 远距离脉冲分量:%f %f %f \n", t, impulse[0], impulse[1], impulse[2]); + } + //终端冲量 + else if (m_PulseNum==1 && m_FlyTime[aim] >=flyTimeApproach) + { + double t = 0; + for (int i = 0; i <= 3; i++) + { + t = t + m_FlyTime[i]; + } + CCTime c_t(2024, 3, 11, 12, 0, 0.0 + t); + AsTimeToJD(c_t, t); + GuidanceImpulse2(chPos, chVel, tgPos, tgVel, endPos, impulse); + printf("儒略日(JD):%f 近距离脉冲分量:%f %f %f \n", t, impulse[0], impulse[1], impulse[2]); + printf("儒略日(JD):%f 观测目标%d \n", t, aim + 1); + m_PulseNum = 2; + } + else if (m_PulseNum == 2 && m_FlyTime[aim] >= flyTimeApproach+1800) + { + isEnd = true; + m_PulseNum = 0; + } + + //脉冲施加后时间累积 + m_FlyTime[aim] += step; +} + + + diff --git a/MultiRendezvous/Src/ChCtrl.h b/MultiRendezvous/Src/ChCtrl.h new file mode 100644 index 0000000000000000000000000000000000000000..962982dbbfe34725f2faa108905e386383ad8f35 --- /dev/null +++ b/MultiRendezvous/Src/ChCtrl.h @@ -0,0 +1,63 @@ +// ChCtrl.h: interface for the CChCtrl class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(_CHCTRL_H__) +#define _CHCTRL_H__ + + +#include "AstroLib.h" + + +// +//追踪器制导控制类 +// +class CChCtrl +{ +public: + CChCtrl(); + virtual ~CChCtrl(); + + void Init(); + void TimeAdvance(double step, + const CCoord& chPos, const CCoord& chVel, const CCoord& tgPos, const CCoord& tgVel, + double flyTimeApproach, const CCoord& endPos, bool& isEnd, CCoord& impulse, int aim); + + +private: + void GuidanceImpulse1( + const CCoord& chPos, const CCoord& chVel, + const CCoord& tgPos, const CCoord& tgVel, const CCoord& endRelPos, + double flyTime, CCoord& impulse); + void GuidanceImpulse2(const CCoord& chPos, const CCoord& chVel, const CCoord& tgPos, const CCoord& tgVel, + const CCoord& endRelVel, CCoord& impulse); + + void Measure(const CCoord& chPos, const CCoord& chVel, + const CCoord& tgPos, const CCoord& tgVel, + CCoord& relPos, CCoord& relVel); + void Engine(CCoord& impulse); + +public: + //测量误差 + int m_UseMeasureRandom; // 是否考虑测量误差:0=无随机;1=随机 + int m_UseEngineRandom; // 是否考虑执行误差:0=无随机;1=随机 + double m_PosStdDev; // 位置测量标准差 + double m_VelStdDev; // 速度测量标准差 + double m_EngStdDev; // 执行误差标准差 + + // + //内部参数 + // +private: + double m_FlyTime[100]; // 从施加上一次冲量开始的飞行时间 + int m_PulseNum; // 冲量次数 + + CRandom m_RandomPos[3]; // 位置随机数 + CRandom m_RandomVel[3]; // 速度随机数 + CRandom m_RandomEng[3]; // 执行机构随机数 + + +}; + + +#endif // !defined(_CHCTRL_H__) diff --git a/MultiRendezvous/Src/IzzoLam.h b/MultiRendezvous/Src/IzzoLam.h new file mode 100644 index 0000000000000000000000000000000000000000..ba268706b55d78a817eff8dc10c57b882e311fc4 --- /dev/null +++ b/MultiRendezvous/Src/IzzoLam.h @@ -0,0 +1,23 @@ +#ifndef IZZOLAM_H +#define IZZOLAM_H + +/** + * Calculates the solution to the Lambert's problem using the Izzo algorithm. + * + * @param r1 The position vector of the departure point. + * @param r2 The position vector of the arrival point. + * @param tof The time of flight between the departure and arrival points. + * @param mu The gravitational parameter of the central body. + * @param way The direction of the transfer: 1 for short way, -1 for long way. + * @param multi_revs The maximum number of complete revolutions allowed. + * @param v1 The velocity vector at the departure point (output parameter). + * @param v2 The velocity vector at the arrival point (output parameter). + * + * @return 0 if the algorithm successfully converges, -1 otherwise. + * + * @throws ErrorType if there was an error in the calculation. + */ +int solve_lambert_izzo(double r1[3], double r2[3], double tof, double mu, int way, int multi_revs, + double v1[][3], double v2[][3]); + +#endif // IZZOLAM_H \ No newline at end of file diff --git a/MultiRendezvous/Src/ObserveGEO.cpp b/MultiRendezvous/Src/ObserveGEO.cpp new file mode 100644 index 0000000000000000000000000000000000000000..b006a38f9dfe7a6a8a57215c13d5092659e1cfa6 --- /dev/null +++ b/MultiRendezvous/Src/ObserveGEO.cpp @@ -0,0 +1,222 @@ +// ObserveGEO.cpp : Defines the entry point for the console application. +// + +#include +#include +#include "ObserveGEO.h" +using namespace std; + +//*********************************************************************** +/// 仿真主程序 +/// @Author Wang Hua +/// @Date 2010-4-15 +//*********************************************************************** +void CRendezvous::Main() +{ + + bool isEnd = false; + + //步长 + double step = 5; + + //初始化 + Initialization(); + + + //循环到仿真结束 + while (!isEnd) + { + isEnd = TimeAdvance(step); + m_Time += step; + } + + //结果报告生成 + ReportGeneration(); + +} + + + +//*********************************************************************** +/// 初始化 +/// @Author Wang Hua +/// @Date 2010-4-15 +//*********************************************************************** +void CRendezvous::Initialization() +{ + //初始化时间 + m_Time = 0; + + //初始化追踪器和目标器 + CCoord chPos(-1.219064685855942e+07, -4.036403817972275e+07, 4.757418138915581e+04), chVel(2.943490270326994e+03, -8.890749827986162e+02, -13.681119407780425); + CCoord tgPos, tgVel; + AsVVLHRelStateToState(CCoord(100000, 0, 0), CCoord(0, 0, 0), + chPos, chVel, tgPos, tgVel); + m_ChDyn.SetName("Chase"); + m_ChDyn.SetPos(chPos); + m_ChDyn.SetVel(chVel); + m_TgDyn.resize(3); + m_TgDyn.at(0).SetName("Target0"); + m_TgDyn.at(0).SetPos(tgPos); + m_TgDyn.at(0).SetVel(tgVel); + AsVVLHRelStateToState(CCoord(200000, 0, 0), CCoord(0, 0, 0), + chPos, chVel, tgPos, tgVel); + m_TgDyn.at(1).SetName("Target1"); + m_TgDyn.at(1).SetPos(tgPos); + m_TgDyn.at(1).SetVel(tgVel); + AsVVLHRelStateToState(CCoord(400000, 0, 0), CCoord(0, 0, 0), + chPos, chVel, tgPos, tgVel); + m_TgDyn.at(2).SetName("Target2"); + m_TgDyn.at(2).SetPos(tgPos); + m_TgDyn.at(2).SetVel(tgVel); + + //初始化控制误差 + m_ChCtrl.m_UseMeasureRandom = 0; + m_ChCtrl.m_UseEngineRandom = 0; + m_ChCtrl.m_PosStdDev = 0.1; + m_ChCtrl.m_VelStdDev = 0.002; + m_ChCtrl.m_EngStdDev = 0.002; + + //初始化动力学和控制 + m_TgDyn.at(0).Init(); + m_TgDyn.at(1).Init(); + m_TgDyn.at(2).Init(); + m_ChDyn.Init(); + m_ChCtrl.Init(); + + //清空缓存 + m_HistoryData.m_TimeList.resize(0); + m_HistoryData.m_chList.resize(0); + m_HistoryData.m_ch_vList.resize(0); + //m_HistoryData.m_tg0List.resize(0); + //m_HistoryData.m_tg0_vList.resize(0); + m_HistoryData.m_tg1List.resize(0); + m_HistoryData.m_tg1_vList.resize(0); + m_HistoryData.m_tg2List.resize(0); + m_HistoryData.m_tg2_vList.resize(0); +} + + +//*********************************************************************** +/// 时间推进 +/// @Author Wang Hua +/// @Date 2010-4-15 +/// @Return true=仿真结束 +//*********************************************************************** +bool CRendezvous::TimeAdvance(double step) +{ + bool isEnd = false; + CCoord impulse; + vector t_list(3); + t_list[0] = 20000; t_list[1] = 20000; t_list[2] = 40000;//访问时间 + + //追踪器和目标器推进 + m_ChCtrl.TimeAdvance(step, m_ChDyn.GetPos(), m_ChDyn.GetVel(), m_TgDyn.at(m_aim).GetPos(), m_TgDyn.at(m_aim).GetVel(), + t_list[m_aim], CCoord(0, 0, 1000), isEnd, impulse, m_aim); + m_ChDyn.TimeAdvance(step, 1, impulse); + m_TgDyn.at(0).TimeAdvance(step, 0, CCoord(0, 0, 0)); + m_TgDyn.at(1).TimeAdvance(step, 0, CCoord(0, 0, 0)); + m_TgDyn.at(2).TimeAdvance(step, 0, CCoord(0, 0, 0)); + + //保存中间数据 + + m_HistoryData.m_TimeList.push_back(m_Time); + + AsStateToVVLHRelState(m_ChDyn.GetPos(), m_ChDyn.GetVel(),m_TgDyn.at(0).GetPos(), m_TgDyn.at(0).GetVel(), + m_RelPos, m_RelVel); + m_HistoryData.m_chList.push_back(m_RelPos); + m_HistoryData.m_ch_vList.push_back(m_RelVel); + if (m_aim == 0) + { + if (m_RelPos.Norm() < 5000) + { + cout << m_Time << "秒,可以看见目标1"<< endl; + } + } + + + AsStateToVVLHRelState(m_TgDyn.at(1).GetPos(), m_TgDyn.at(1).GetVel(),m_TgDyn.at(0).GetPos(), m_TgDyn.at(0).GetVel(), + m_RelPos, m_RelVel); + m_HistoryData.m_tg1List.push_back(m_RelPos); + m_HistoryData.m_tg1_vList.push_back(m_RelVel); + if (m_aim == 1) + { + if ((m_TgDyn.at(1).GetPos() - m_ChDyn.GetPos()).Norm() < 5000) + { + cout << m_Time << "秒,可以看见目标2" << endl; + } + } + + AsStateToVVLHRelState(m_TgDyn.at(2).GetPos(), m_TgDyn.at(2).GetVel(),m_TgDyn.at(0).GetPos(), m_TgDyn.at(0).GetVel(), + m_RelPos, m_RelVel); + m_HistoryData.m_tg2List.push_back(m_RelPos); + m_HistoryData.m_tg2_vList.push_back(m_RelVel); + if (m_aim == 2) + { + if ((m_TgDyn.at(2).GetPos() - m_ChDyn.GetPos()).Norm() < 5000) + { + cout << m_Time << "秒,可以看见目标3" << endl; + } + } + + if (isEnd == true) + { + m_aim += 1; + isEnd = false; + } + if (m_aim > 2) + { + isEnd = true; + } + return isEnd; +} + + +//*********************************************************************** +/// 结果报告生成 +/// @Author Wang Hua +/// @Date 2010-4-15 +//*********************************************************************** +void CRendezvous::ReportGeneration() +{ + ofstream oss(".\\Output\\RelPosVel.txt"); + int n = m_HistoryData.m_TimeList.size(); + for (int i = 0; i < n; i++) + { + oss << m_HistoryData.m_TimeList[i] << " " + << m_HistoryData.m_chList[i][0] << " " + << m_HistoryData.m_chList[i][1] << " " + << m_HistoryData.m_chList[i][2] << " " + << m_HistoryData.m_tg1List[i][0] << " " + << m_HistoryData.m_tg1List[i][1] << " " + << m_HistoryData.m_tg1List[i][2] << " " + << m_HistoryData.m_tg2List[i][0] << " " + << m_HistoryData.m_tg2List[i][1] << " " + << m_HistoryData.m_tg2List[i][2] << endl; + } + oss.close(); + + m_ChDyn.ReportGeneration(); + m_TgDyn[0].ReportGeneration(); + +} + + +int main() +{ + printf("*****************************************************************\n"); + printf("* ObserveGEO Example\n"); + printf("*****************************************************************\n\n"); + + + //执行交会对接仿真 + CRendezvous sim; + sim.Main(); //标称仿真 + //sim.MainMonteCarlo(); //MonteCarlo仿真 + + return 0; +} + + + + diff --git a/MultiRendezvous/Src/ObserveGEO.h b/MultiRendezvous/Src/ObserveGEO.h new file mode 100644 index 0000000000000000000000000000000000000000..77af2a130ba7d8f83e17f70628c46c0da5160d4b --- /dev/null +++ b/MultiRendezvous/Src/ObserveGEO.h @@ -0,0 +1,60 @@ + +#if !defined(AFX_ASTROLIBEXAMPLES_H__A94E219F_5EC1_4DF2_973D_CFEB16259FBE__INCLUDED_) +#define AFX_ASTROLIBEXAMPLES_H__A94E219F_5EC1_4DF2_973D_CFEB16259FBE__INCLUDED_ + +#pragma once + +#include "AstroLib.h" +#include "Spacecraft.h" +#include "ChCtrl.h" + + +// +//航天器交会对接总控 +// +class CRendezvous +{ +public: + void Main(); // 仿真主程序 + +private: + void Initialization(); // 初始化 + bool TimeAdvance(double step); // 时间推进 + void ReportGeneration(); // 结果报告生成 + + +public: + double m_Time; // 仿真时间 + int m_aim = 0; + CCoord m_RelPos; // 相对速度 + CCoord m_RelVel; // 相对速度 + +public: + //保存仿真中间数据 + struct CHistoryData + { + std::vector m_TimeList; // 仿真总共消耗时间[s] + std::vector m_chList; // 相对位置状态[m] + std::vector m_tg1List; // 相对位置状态[m] + std::vector m_tg2List; // 相对位置状态[m] + + std::vector m_ch_vList; // 相对速度状态[m/s] + std::vector m_tg1_vList; // 相对速度状态[m/s] + std::vector m_tg2_vList; // 相对速度状态[m/s] + + std::vector m_sun0List; // 阳光角[弧度] + std::vector m_sun1List; // 阳光角[弧度] + std::vector m_sun2List; // 阳光角[弧度] + }; + CHistoryData m_HistoryData; // 历史数据 + +private: + CChCtrl m_ChCtrl; // 追踪器控制 + CSpacecraft m_ChDyn; // 追踪器动力学 + std::vector m_TgDyn; // 目标器动力学 + +}; + + + +#endif // !defined(AFX_ASTROLIBEXAMPLES_H__A94E219F_5EC1_4DF2_973D_CFEB16259FBE__INCLUDED_) diff --git a/MultiRendezvous/Src/Spacecraft.cpp b/MultiRendezvous/Src/Spacecraft.cpp new file mode 100644 index 0000000000000000000000000000000000000000..d35bcd2a8643250e02436fd57ff79896dac4aa34 --- /dev/null +++ b/MultiRendezvous/Src/Spacecraft.cpp @@ -0,0 +1,122 @@ +// Spacecraft.cpp: implementation of the CSpacecraft class. +// +////////////////////////////////////////////////////////////////////// + +#include "Spacecraft.h" + +using namespace std; + + + +////////////////////////////////////////////////////////////////////// +// Construction/Destruction +////////////////////////////////////////////////////////////////////// + +CSpacecraft::CSpacecraft() +{ + // ʼ + m_Name = "Vehicle"; + m_ElapsedSec = 0.0; + m_Pos[0] = 0.0; + m_Pos[1] = 0.0; + m_Pos[2] = 0.0; +} + + +CSpacecraft::~CSpacecraft() +{ + +} + + +//******************************************************************** +//ʼ,״̬ļ,ʼ +//Author: Wang Hua +//Date: 2005.10.22 +//Input: fileName Ҫĺļ +//******************************************************************** +void CSpacecraft::Init() +{ + //ֵ + m_ElapsedSec = 0.0; //Epoch second set to zero. + + //ʷ + m_HistoryData.m_ElapsedSec.resize(0); + m_HistoryData.m_Pos.resize(0); + m_HistoryData.m_Vel.resize(0); +} + + +//******************************************************************** +/// ʱstepλ,,̬ +/// @Author Wang Hua +/// @Date 2004.11.19 +/// @Input +/// @Param step ʱ䲽 +/// @Param burnCoordSys ϵ: 0=J2000;1=VVLH;2=VNC;3=ϵ +/// @Param burnValue ܵij +/// @Output +/// @Return +//******************************************************************** +void CSpacecraft::TimeAdvance(double step, int burnCoordSys, + const CCoord& burnValue) +{ + CCoord burnValueInertial, burnValueBody, momentVCF, sunPos; + CMatrix mtx; + + // ٶ + switch (burnCoordSys) + { + case 0: + m_Vel += burnValue; + break; + case 1: + AsVVLHToICSMtx(m_Pos, m_Vel, mtx); + m_Vel += burnValue.RotateTo(mtx); + break; + } + + // + m_Orbit.OrbitStep(step, m_Pos, m_Vel); + + // ʱ + m_ElapsedSec += step; + + UpdateBuffer(); +} + + +//******************************************************************** +//ݻ +//Author: Wang Hua +//Date: 2005.10.22 +//******************************************************************** +void CSpacecraft::UpdateBuffer() +{ + m_HistoryData.m_ElapsedSec.push_back(m_ElapsedSec); + m_HistoryData.m_Pos.push_back(m_Pos); + m_HistoryData.m_Vel.push_back(m_Vel); +} + + +//*********************************************************************** +/// +/// @Author Wang Hua +/// @Date 2022-6-30 +//*********************************************************************** +void CSpacecraft::ReportGeneration() +{ + ofstream oss(".\\Output\\" + m_Name + ".txt"); + int n = m_HistoryData.m_ElapsedSec.size(); + for (int i = 0; i < n; i++) + { + oss << m_HistoryData.m_ElapsedSec[i] << " " + << m_HistoryData.m_Pos[i][0] << " " + << m_HistoryData.m_Pos[i][1] << " " + << m_HistoryData.m_Pos[i][2] << " " + << m_HistoryData.m_Vel[i][0] << " " + << m_HistoryData.m_Vel[i][1] << " " + << m_HistoryData.m_Vel[i][2] << endl; + } + oss.close(); +} \ No newline at end of file diff --git a/MultiRendezvous/Src/Spacecraft.h b/MultiRendezvous/Src/Spacecraft.h new file mode 100644 index 0000000000000000000000000000000000000000..63b8b797c05402ebc252052f5219d5142c1aa590 --- /dev/null +++ b/MultiRendezvous/Src/Spacecraft.h @@ -0,0 +1,132 @@ +// Spacecraft.h: interface for the CSpacecraft class. +// +////////////////////////////////////////////////////////////////////// + +#if !defined(_Spacecraft_H__INCLUDED_) +#define _Spacecraft_H__INCLUDED_ + +#pragma once + + +#include "AstroLib.h" +#include + + +// +//ѧ,˺IJͲ +// +class CSpacecraft +{ + // + // Operation. + // +public: + CSpacecraft(); + virtual ~CSpacecraft(); + + + // + //Բ + // + inline void SetName(const std::string& name); // ú + inline void SetPos(const CCoord& pos); // úλ + inline void SetVel(const CCoord& vel); // úٶ + inline void SetElapsedSec(double sec); // ۼʱ + inline const std::string& GetName() const; // õ + inline const CCoord& GetPos() const; // õλ + inline const CCoord& GetVel() const; // õٶ + inline double GetElapsedSec() const; // õۼʱ + + void Init(); // ʼ + void TimeAdvance(double step, int burnCoordSys, + const CCoord& burnValue); // ʱƽ + void ReportGeneration(); // + +private: + // + //м + // + void UpdateBuffer(); + + // + // Attribute. + // +public: + std::string m_Name; // + CCoord m_Pos; // λ,Ĺϵʾ + CCoord m_Vel; // ٶ,Ĺϵʾ + double m_ElapsedSec; // ۼʱ(s) + + +public: + // + //ݻ + // + struct CHistoryData + { + std::vector m_ElapsedSec; // ܹʱ[s] + std::vector m_Pos; // λ״̬[m] + std::vector m_Vel; // ٶ״̬[m/s] + }; + CHistoryData m_HistoryData; // ʷ + +protected: + COrbit m_Orbit; // + +}; + + +// +//inline function. +// + +// ú +void CSpacecraft::SetName(const std::string& name) +{ + m_Name = name; +} + +// ú״̬ +inline void CSpacecraft::SetPos(const CCoord& pos) +{ + m_Pos = pos; +} + +inline void CSpacecraft::SetVel(const CCoord& vel) +{ + m_Vel = vel; +} + +// ۼʱ +inline void CSpacecraft::SetElapsedSec(double sec) +{ + m_ElapsedSec = sec; +} + +// õ +inline const std::string& CSpacecraft::GetName() const +{ + return m_Name; +} + +// õ״̬ +inline const CCoord& CSpacecraft::GetPos() const +{ + return m_Pos; +} + +inline const CCoord& CSpacecraft::GetVel() const +{ + return m_Vel; +} + +// õۼʱ +inline double CSpacecraft::GetElapsedSec() const +{ + return m_ElapsedSec; +} + + + + +#endif // !defined(_Spacecraft_H__INCLUDED_) diff --git a/MultiRendezvous/Src/izzoLam.cpp b/MultiRendezvous/Src/izzoLam.cpp new file mode 100644 index 0000000000000000000000000000000000000000..c645f7d87a7a5a74800fda86fa27c211b5f2a589 --- /dev/null +++ b/MultiRendezvous/Src/izzoLam.cpp @@ -0,0 +1,37 @@ +#include "izzoLam.h" +#include +#include "lambert_problem_t.hpp" + +int solve_lambert_izzo(double r1[3], double r2[3], double tof, double mu, int way, int multi_revs, + double v1[][3], double v2[][3]) { + + int dimV = multi_revs * 2 + 1; + memset(v1, 0, sizeof(double) * 3 * dimV); memset(v2, 0, sizeof(double) * 3 * dimV); + + const Vector3 r1vec(r1[0], r1[1], r1[2]); + const Vector3 r2vec(r2[0], r2[1], r2[2]); + + lambert_problem lp(r1vec, r2vec, tof, mu, way, multi_revs); + lp.Solve(); + std::vector> v1ls = lp.get_v1(); + std::vector> v2ls = lp.get_v2(); + + for (size_t i = 0; i < v1ls.size(); i++) { + v1[i][0] = v1ls[i][0]; + v1[i][1] = v1ls[i][1]; + v1[i][2] = v1ls[i][2]; + v2[i][0] = v2ls[i][0]; + v2[i][1] = v2ls[i][1]; + v2[i][2] = v2ls[i][2]; + } + + return 0; +} + + +//{ +// double r1[3]{ 41960184.323318355,3473991.642108842,-96064.78455976033 }, r2[3]{ -6441593.34, 41608179.66, 13233.21 }, tof = 43200, mu = 3.986e14, v1[1][3], v2[1][3]; +// int way = 1, multi_revs = 0; +// solve_lambert_izzo(r1, r2, tof, mu, way, multi_revs, v1, v2); +// cout << v1[0][0] << endl; +//} \ No newline at end of file diff --git a/MultiRendezvous/Src/lambert_problem.hpp b/MultiRendezvous/Src/lambert_problem.hpp new file mode 100644 index 0000000000000000000000000000000000000000..cbf4cc9f0b05108fdca9c7520d88eef89f0b97d1 --- /dev/null +++ b/MultiRendezvous/Src/lambert_problem.hpp @@ -0,0 +1,63 @@ +#ifndef LAMBERT_PROBLEM_H +#define LAMBERT_PROBLEM_H + +#include "myvector_t.hpp" + +#define _USE_MATH_DEFINES +#include + +#include +#include + +#define Vector3T Vector3 + +template class lambert_problem { +public: + /** + * @brief Construct a new lambert problem object + * + * @param r1 first cartesian position + * @param r2 second cartesian position + * @param tof time of flight + * @param mu gravity parameter + * @param sl 1: short way transfer; -1: long way transfer + * @param multi_revs maximum number of multirevolutions to compute + */ + lambert_problem(const Vector3T &r1 = {1, 0, 0}, const Vector3T &r2 = {0, 1, 0}, + const ST &tof = M_PI_2, const double &mu = 1., const int &sl = 1, + const int &multi_revs = 6); + void Solve(); + void SolveTimeEquation(); + void ConstructTerminalVecolityComponent(const ST &x, ST &vr1, ST &vr2, ST &vt1, ST &vt2) const; + void CalTerminalVelocities(const ST &x, Vector3T &v1, Vector3T &v2) const; + + const std::vector &get_v1() const; + const std::vector &get_v2() const; + const Vector3T &get_r1() const; + const Vector3T &get_r2() const; + const ST &get_tof() const; + const double &get_mu() const; + ST get_lambda() const { return m_lambda; } + ST get_T() const { return sqrt(2.0 * m_mu / m_s / m_s / m_s) * m_tof; } + const std::vector &get_x() const; + const std::vector &get_iters() const; + int get_Nmax() const; + +private: + const Vector3T m_r1, m_r2; + const ST m_tof; + const double m_mu; + std::vector m_v1; + std::vector m_v2; + std::vector m_iters; + std::vector m_x; + ST m_s, m_c, m_lambda; + int m_Nmax; + int m_multi_revs; + + Vector3T ir1_, ir2_, ih_, it1_, it2_; +}; + +//#undef _USE_MATH_DEFINES + +#endif diff --git a/MultiRendezvous/Src/lambert_problem_t.hpp b/MultiRendezvous/Src/lambert_problem_t.hpp new file mode 100644 index 0000000000000000000000000000000000000000..fe5f563a38ff5ef2a9f691173f2c5a6811fe13c4 --- /dev/null +++ b/MultiRendezvous/Src/lambert_problem_t.hpp @@ -0,0 +1,349 @@ + +#ifndef LAMBERT_PROBLEM_T_H +#define LAMBERT_PROBLEM_T_H + +#include + +#include "lambert_problem.hpp" +#include + +template +void LambdaT2Pos(const T &lambda, const T &capsT, const double tof, const double mu, T &rx, T &ry) { + double s = cbrt(2 * mu * pow(tof / capsT, 2)); + double c = (1 - lambda * lambda) * s; + + rx = 2 * s * s - 2 * s * c - 2 * s + c + 1; + double sctemp = s * (1 + c - s); + ry = 2 * sqrt(sctemp * (c - sctemp)); +} +template T hypergeometricF(T z, double tol) { + T Sj = 1.0; + T Cj = 1.0; + double err = 1.0; + T Cj1 = 0.0; + T Sj1 = 0.0; + int j = 0; + while (err > tol) { + Cj1 = Cj * (3.0 + j) * (1.0 + j) / (2.5 + j) * z / (j + 1); + err = fabs(Cj1); + Sj1 = Sj + Cj1; + Sj = Sj1; + Cj = Cj1; + j = j + 1; + } + return Sj; +} + +template T x2tofLagrange(const T &lambda, const T &x, const int N) { + T a = 1.0 / (1.0 - x * x); + if (a > 0) // ellipse + { + T alfa = 2.0 * acos(x); + T beta = 2.0 * asin(sqrt(lambda * lambda / a)); + if (lambda < 0.0) beta = -beta; + T tof = ((a * sqrt(a) * ((alfa - sin(alfa)) - (beta - sin(beta)) + 2.0 * M_PI * N)) / 2.0); + return tof; + } else { + T alfa = 2.0 * acosh(x); + T beta = 2.0 * asinh(sqrt(-lambda * lambda / a)); + if (lambda < 0.0) beta = -beta; + T tof = (-a * sqrt(-a) * ((beta - sinh(beta)) - (alfa - sinh(alfa))) / 2.0); + return tof; + } +} +template T x2tof(const T &lambda, const T &x, const int N) { + double battin = 0.01; + double lagrange = 0.2; + double dist = fabs(x - 1); + if (dist < lagrange && dist > battin) { // We use Lagrange tof expression + return x2tofLagrange(lambda, x, N); + } + + T K = lambda * lambda; + T E = x * x - 1.0; + T z = sqrt(1 + K * E); + if (dist < battin) { // We use Battin series tof expression + T eta = z - lambda * x; + T S1 = 0.5 * (1.0 - lambda - x * eta); + T Q = hypergeometricF(S1, 1e-11); + Q = 4.0 / 3.0 * Q; + T tof = (eta * eta * eta * Q + 4.0 * lambda * eta) / 2.0; + if (N > 0) tof += N * M_PI / sqrt(-E * E * E); + return tof; + } else { // We use Lancaster tof expresion + T rho = (E < 0.0) ? -E : E; + T y = sqrt(rho); + T g = x * z - lambda * E; + T d = 0.0; + if (E < 0) { + T l = acos(g); + d = N * M_PI + l; + } else { + T f = y * (z - lambda * x); + d = log(f + g); + } + T tof = (x - lambda * z - d / y) / E; + return tof; + } +} + +template +void dTdx(T &DT, T &DDT, T &DDDT, const T &x, const T &lambda, const T &capsT) { + T l2 = lambda * lambda; + T l3 = l2 * lambda; + T umx2 = 1.0 - x * x; + T y = sqrt(1.0 - l2 * umx2); + T y2 = y * y; + T y3 = y2 * y; + DT = 1.0 / umx2 * (3.0 * capsT * x - 2.0 + 2.0 * l3 * x / y); + DDT = 1.0 / umx2 * (3.0 * capsT + 5.0 * x * DT + 2.0 * (1.0 - l2) * l3 / y3); + DDDT = 1.0 / umx2 * (7.0 * x * DDT + 8.0 * DT - 6.0 * (1.0 - l2) * l2 * l3 * x / y3 / y2); +} + +template int householder(const T &capsT, const T &lambda, T &x0, const int N, + const double eps, const int iter_max) { + int it = 0; + double err = 1.0; + double xnew = 0.0; + double tof = 0.0, delta = 0.0, DT = 0.0, DDT = 0.0, DDDT = 0.0; + while ((err > eps) && (it < iter_max)) { + tof = x2tof(lambda, x0, N); + dTdx(DT, DDT, DDDT, x0, lambda, tof); + delta = tof - capsT; + double DT2 = DT * DT; + xnew = x0 + - delta * (DT2 - delta * DDT / 2.0) + / (DT * (DT2 - delta * DDT) + DDDT * delta * delta / 6.0); + err = fabs(x0 - xnew); + x0 = xnew; + it++; + } + return it; +} + +template +lambert_problem::lambert_problem(const Vector3T &r1, const Vector3T &r2, const ST &tof, + const double &mu, const int &sl, const int &multi_revs) + : m_r1(r1), m_r2(r2), m_tof(tof), m_mu(mu), m_multi_revs(multi_revs) { + // 0 - Sanity checks + if (tof <= 0) { + throw std::domain_error("Time of flight is negative!"); + } + if (mu <= 0) { + throw std::domain_error("Gravity parameter is zero or negative!"); + } + if (std::abs(sl) != 1) { + throw std::domain_error("Transfer direction is not 1(short) or -1(long)!"); + } + + // 1 - Getting lambda and T + m_c = sqrt((r2[0] - r1[0]) * (r2[0] - r1[0]) + (r2[1] - r1[1]) * (r2[1] - r1[1]) + + (r2[2] - r1[2]) * (r2[2] - r1[2])); + ST R1 = m_r1.norm(); + ST R2 = m_r2.norm(); + m_s = (m_c + R1 + R2) / 2.0; + ST T = sqrt(2.0 * m_mu / m_s / m_s / m_s) * m_tof; + ST lambda2 = 1.0 - m_c / m_s; + m_lambda = sl * sqrt(lambda2); + + // 2.1 - Let us first detect the maximum number of revolutions for which there + // exists a solution + m_Nmax = static_cast(floor(T / M_PI)); + ST T00 = acos(m_lambda) + m_lambda * sqrt(1.0 - lambda2); + ST T0 = (T00 + m_Nmax * M_PI); + ST DT = 0.0, DDT = 0.0, DDDT = 0.0; + if (m_Nmax > 0) { + if (T < T0) { // We use Halley iterations to find xM and TM + int it = 0; + double err = 1.0; + ST T_min = T0; + ST x_old = 0.0, x_new = 0.0; + while (1) { + dTdx(DT, DDT, DDDT, x_old, m_lambda, T_min); + if (!(DT == 0.0)) { + x_new = x_old - DT * DDT / (DDT * DDT - DT * DDDT / 2.0); + } + err = fabs(x_old - x_new); + if ((err < 1e-13) || (it > 12)) { + break; + } + T_min = x2tof(m_lambda, x_new, m_Nmax); + x_old = x_new; + it++; + } + if (T_min > T) { + m_Nmax -= 1; + } + } + } + // We exit this if clause with Nmax being the maximum number of revolutions + // for which there exists a solution. We crop it to m_multi_revs + m_Nmax = std::min(m_multi_revs, m_Nmax); + + // 2.2 We now allocate the memory for the output variables + m_v1.resize(m_Nmax * 2 + 1); + m_v2.resize(m_Nmax * 2 + 1); + m_iters.resize(m_Nmax * 2 + 1); + m_x.resize(m_Nmax * 2 + 1); + + // + ir1_ = m_r1 / sqrt(m_r1[0] * m_r1[0] + m_r1[1] * m_r1[1] + m_r1[2] * m_r1[2]); + ir2_ = m_r2 / sqrt(m_r2[0] * m_r2[0] + m_r2[1] * m_r2[1] + m_r2[2] * m_r2[2]); + ih_ = ir1_.cross(ir2_); + ih_ = ih_ / sqrt(ih_[0] * ih_[0] + ih_[1] * ih_[1] + ih_[2] * ih_[2]); + if (ih_[2] == 0) { + // std::cout + // << "Warn: Angular momentum vector has no z component, set ih = + // [0,0,1]!" + // << std::endl; + ih_ = {0, 0, 1}; + } + if (m_lambda < 0) ih_ = ih_ * -1; + it1_ = ih_.cross(ir1_); + // it1_ /= sqrt(it1_[0] * it1_[0] + it1_[1] * it1_[1] + it1_[2] * it1_[2]); + it2_ = ih_.cross(ir2_); + // it2_ /= sqrt(it2_[0] * it2_[0] + it2_[1] * it2_[1] + it2_[2] * it2_[2]); +} +template void lambert_problem::SolveTimeEquation() { + // 3 - We may now find all solutions in x,y + // 3.1 0 rev solution + // 3.1.1 initial guess + ST lambda2 = 1.0 - m_c / m_s; + ST lambda3 = lambda2 * m_lambda; + ST T = sqrt(2.0 * m_mu / m_s / m_s / m_s) * m_tof; + ST T00 = acos(m_lambda) + m_lambda * sqrt(1.0 - lambda2); + ST T1 = 2.0 / 3.0 * (1.0 - lambda3); + if (T >= T00) { + m_x[0] = -(T - T00) / (T - T00 + 4); + } else if (T <= T1) { + m_x[0] = T1 * (T1 - T) / (2.0 / 5.0 * (1 - lambda2 * lambda3) * T) + 1; + } else { + m_x[0] = pow((T / T00), 0.69314718055994529 / log(T1 / T00)) - 1.0; + } + // 3.1.2 Householder iterations + m_iters[0] = householder(T, m_lambda, m_x[0], 0, 1e-5, 15); + // 3.2 multi rev solutions + ST tmp; + for (int i = 1; i < m_Nmax + 1; ++i) { + // 3.2.1 left Householder iterations + tmp = pow((i * M_PI + M_PI) / (8.0 * T), 2.0 / 3.0); + m_x[2 * i - 1] = (tmp - 1) / (tmp + 1); + m_iters[2 * i - 1] = householder(T, m_lambda, m_x[2 * i - 1], i, 1e-8, 15); + // 3.2.1 right Householder iterations + tmp = pow((8.0 * T) / (i * M_PI), 2.0 / 3.0); + m_x[2 * i] = (tmp - 1) / (tmp + 1); + m_iters[2 * i] = householder(T, m_lambda, m_x[2 * i], i, 1e-8, 15); + } +} +template void lambert_problem::Solve() { + SolveTimeEquation(); + // 4 - For each found x value we reconstruct the terminal velocities + ST vr1, vt1, vr2, vt2; + for (size_t i = 0; i < m_x.size(); ++i) { + ConstructTerminalVecolityComponent(m_x[i], vr1, vr2, vt1, vt2); + for (int j = 0; j < 3; ++j) m_v1[i][j] = vr1 * ir1_[j] + vt1 * it1_[j]; + for (int j = 0; j < 3; ++j) m_v2[i][j] = vr2 * ir2_[j] + vt2 * it2_[j]; + } +} + +template +void lambert_problem::ConstructTerminalVecolityComponent(const ST &x, ST &vr1, ST &vr2, ST &vt1, + ST &vt2) const { + ST R1 = m_r1.norm(); + ST R2 = m_r2.norm(); + ST gamma = sqrt(m_mu * m_s / 2.0); + ST rho = (R1 - R2) / m_c; + ST sigma = sqrt(1 - rho * rho); + ST lambda2 = 1.0 - m_c / m_s; + ST y = sqrt(1.0 - lambda2 + lambda2 * x * x); + vr1 = gamma * ((m_lambda * y - x) - rho * (m_lambda * y + x)) / R1; + vr2 = -gamma * ((m_lambda * y - x) + rho * (m_lambda * y + x)) / R2; + ST vt = gamma * sigma * (y + m_lambda * x); + vt1 = vt / R1; + vt2 = vt / R2; +} +template +void lambert_problem::CalTerminalVelocities(const ST &x, Vector3T &v1, Vector3T &v2) const { + ST vr1, vt1, vr2, vt2; + ConstructTerminalVecolityComponent(x, vr1, vr2, vt1, vt2); + + // Vector3T v1, v2; + v1 = vr1 * ir1_ + vt1 * it1_; + v2 = vr2 * ir2_ + vt2 * it2_; +} + +/// Gets velocity at r1 +/** + * + * \return an std::vector containing 3-d arrays with the cartesian components of + * the velocities at r1 for all 2N_max+1 solutions + */ +template const std::vector &lambert_problem::get_v1() const { + return m_v1; +} + +/// Gets velocity at r2 +/** + * + * \return an std::vector containing 3-d arrays with the cartesian components of + * the velocities at r2 for all 2N_max+1 solutions + */ +template const std::vector &lambert_problem::get_v2() const { + return m_v2; +} + +/// Gets r1 +/** + * + * \return a 3-d array with the cartesian components of r1 + */ +template const Vector3T &lambert_problem::get_r1() const { return m_r1; } + +/// Gets r2 +/** + * + * \return a 3-d array with the cartesian components of r2 + */ +template const Vector3T &lambert_problem::get_r2() const { return m_r2; } + +/// Gets the time of flight between r1 and r2 +/** + * + * \return the time of flight + */ +template const ST &lambert_problem::get_tof() const { return m_tof; } + +/// Gets the x variable +/** + * Gets the x variable for each solution found (0 revs, 1,1,2,2,3,3 .... N,N) + * + * \return the x variables in an std::vector + */ +template const std::vector &lambert_problem::get_x() const { return m_x; } + +/// Gets gravitational parameter +/** + * + * \return the gravitational parameter + */ +template const double &lambert_problem::get_mu() const { return m_mu; } + +/// Gets number of iterations +/** + * + * \return an std::vector containing the iterations taken to compute each one of + * the solutions + */ +template const std::vector &lambert_problem::get_iters() const { + return m_iters; +} + +/// Gets N_max +/** + * + * \return the maximum number of revolutions. The number of solutions to the + * problem will be Nmax*2 +1 + */ +template int lambert_problem::get_Nmax() const { return m_Nmax; } + +#endif \ No newline at end of file diff --git a/MultiRendezvous/Src/myvector_t.hpp b/MultiRendezvous/Src/myvector_t.hpp new file mode 100644 index 0000000000000000000000000000000000000000..0bfca8a2c03aeb5247692df7949fccde7028fa77 --- /dev/null +++ b/MultiRendezvous/Src/myvector_t.hpp @@ -0,0 +1,73 @@ +#ifndef MYVECTOR_H +#define MYVECTOR_H +#include + +template class Vector3 { +public: + T x, y, z; + + Vector3(T x_val = 0, T y_val = 0, T z_val = 0) : x(x_val), y(y_val), z(z_val) {} + + Vector3 operator+(const Vector3& other) const { + return Vector3(x + other.x, y + other.y, z + other.z); + } + + Vector3 operator-(const Vector3& other) const { + return Vector3(x - other.x, y - other.y, z - other.z); + } + + Vector3 operator*(T scalar) const { return Vector3(x * scalar, y * scalar, z * scalar); } + + Vector3 operator/(T scalar) const { + if (scalar == 0) { + throw std::invalid_argument("Division by zero."); + } + return Vector3(x / scalar, y / scalar, z / scalar); + } + + T& operator[](int index) { + if (index < 0 || index >= 3) { + throw std::out_of_range("Index out of range."); + } + + if (index == 0) { + return x; + } else if (index == 1) { + return y; + } else { + return z; + } + } + + const T& operator[](int index) const { + if (index < 0 || index >= 3) { + throw std::out_of_range("Index out of range."); + } + + if (index == 0) { + return x; + } else if (index == 1) { + return y; + } else { + return z; + } + } + + T dot(const Vector3& other) const { return x * other.x + y * other.y + z * other.z; } + + Vector3 cross(const Vector3& other) const { + return Vector3(y * other.z - z * other.y, z * other.x - x * other.z, x * other.y - y * other.x); + } + + T norm() const { return std::sqrt(x * x + y * y + z * z); } + + Vector3 normalized() const { + T n = norm(); + if (n != 0) { + return Vector3(x / n, y / n, z / n); + } + return *this; + } +}; + +#endif \ No newline at end of file diff --git a/SimDoF6/SimDoF6.vcxproj.user b/SimDoF6/SimDoF6.vcxproj.user new file mode 100644 index 0000000000000000000000000000000000000000..88a550947edbc3c5003a41726f0749201fdb6822 --- /dev/null +++ b/SimDoF6/SimDoF6.vcxproj.user @@ -0,0 +1,4 @@ + + + + \ No newline at end of file