diff --git a/Doc/Project Apollo - NASSP/Checklists/Apollo 11 Checklists.xls b/Doc/Project Apollo - NASSP/Checklists/Apollo 11 Checklists.xls index 91b3d8a9da..f5676c95be 100644 Binary files a/Doc/Project Apollo - NASSP/Checklists/Apollo 11 Checklists.xls and b/Doc/Project Apollo - NASSP/Checklists/Apollo 11 Checklists.xls differ diff --git a/Doc/Project Apollo - NASSP/Checklists/Apollo 11 LM Checklists.xls b/Doc/Project Apollo - NASSP/Checklists/Apollo 11 LM Checklists.xls index c1198dc874..b96e41e1ac 100644 Binary files a/Doc/Project Apollo - NASSP/Checklists/Apollo 11 LM Checklists.xls and b/Doc/Project Apollo - NASSP/Checklists/Apollo 11 LM Checklists.xls differ diff --git a/Doc/Project Apollo - NASSP/Checklists/Apollo 9 LM Checklists.xls b/Doc/Project Apollo - NASSP/Checklists/Apollo 9 LM Checklists.xls index d2a1226277..6e39746dd6 100644 Binary files a/Doc/Project Apollo - NASSP/Checklists/Apollo 9 LM Checklists.xls and b/Doc/Project Apollo - NASSP/Checklists/Apollo 9 LM Checklists.xls differ diff --git a/Missions/ProjectApollo/Apollo 14.cfg b/Missions/ProjectApollo/Apollo 14.cfg index c3551ac064..6884668841 100644 --- a/Missions/ProjectApollo/Apollo 14.cfg +++ b/Missions/ProjectApollo/Apollo 14.cfg @@ -5,6 +5,7 @@ LGCVersion=Luminary178 AEAVersion=FP8 CMtoLMPowerConnectionVersion=1 HasRateAidedOptics=TRUE +LMCWEAVersion=1 CDRVesselName=Al Shepard CMPVesselName=Stu Roosa LMPVesselName=Ed Mitchell diff --git a/Missions/ProjectApollo/Apollo 15.cfg b/Missions/ProjectApollo/Apollo 15.cfg index 878869f325..189b0b0acf 100644 --- a/Missions/ProjectApollo/Apollo 15.cfg +++ b/Missions/ProjectApollo/Apollo 15.cfg @@ -10,6 +10,8 @@ LM_CGZ_Coefficients=6.999290756655724e-09 -7.903615464137980e-05 2.9183085320058 CMtoLMPowerConnectionVersion=2 EmptySMCG=913.9687 1.6681 1.0488 HasRateAidedOptics=TRUE +LMCWEAVersion=1 +CrossPointerReversePolarity=TRUE CDRVesselName=Dave Scott CMPVesselName=Al Worden LMPVesselName=Jim Irwin diff --git a/Missions/ProjectApollo/Apollo 16.cfg b/Missions/ProjectApollo/Apollo 16.cfg index b294971ccf..9208823464 100644 --- a/Missions/ProjectApollo/Apollo 16.cfg +++ b/Missions/ProjectApollo/Apollo 16.cfg @@ -7,6 +7,8 @@ LMDSKYVersion=3 CMtoLMPowerConnectionVersion=2 EmptySMCG=913.9687 1.6681 1.0488 HasRateAidedOptics=TRUE +LMCWEAVersion=1 +CrossPointerReversePolarity=TRUE CDRVesselName=John Young CMPVesselName=Ken Mattingly LMPVesselName=Charlie Duke diff --git a/Missions/ProjectApollo/Apollo 17.cfg b/Missions/ProjectApollo/Apollo 17.cfg index 5f93584980..30aef68c69 100644 --- a/Missions/ProjectApollo/Apollo 17.cfg +++ b/Missions/ProjectApollo/Apollo 17.cfg @@ -7,6 +7,8 @@ LMDSKYVersion=3 CMtoLMPowerConnectionVersion=2 EmptySMCG=913.9687 1.6681 1.0488 HasRateAidedOptics=TRUE +LMCWEAVersion=1 +CrossPointerReversePolarity=TRUE CDRVesselName=Gene Cernan CMPVesselName=Ron Evans LMPVesselName=Jack Schmitt diff --git a/Orbitersdk/samples/ProjectApollo/src_aux/Mission.cpp b/Orbitersdk/samples/ProjectApollo/src_aux/Mission.cpp index c05d67449d..3ab82dff05 100644 --- a/Orbitersdk/samples/ProjectApollo/src_aux/Mission.cpp +++ b/Orbitersdk/samples/ProjectApollo/src_aux/Mission.cpp @@ -111,6 +111,7 @@ namespace mission { EmptySMCG = _V(914.5916, -6.6712, 12.2940); //Includes: empty SM and SLA ring, but no SM RCS bHasRateAidedOptics = false; + CM_IMUDriftRates = _M(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); CM_PIPABias = _V(0.0, 0.0, 0.0); CM_PIPAScale = _V(0.0, 0.0, 0.0); @@ -118,6 +119,10 @@ namespace mission { LM_IMUDriftRates = _M(0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0); LM_PIPABias = _V(0.0, 0.0, 0.0);; LM_PIPAScale = _V(0.0, 0.0, 0.0); + + iLMCWEAVersion = 0; + bCrossPointerReversePolarity = false; + strCDRName = "CDR"; strCMPName = "CMP"; strLMPName = "LMP"; @@ -267,6 +272,13 @@ namespace mission { strncpy(buffer, line + 19, 255); bHasRateAidedOptics = !_strnicmp(buffer, "TRUE", 4); } + else if (!_strnicmp(line, "LMCWEAVersion=", 14)) { + sscanf(line + 14, "%d", &iLMCWEAVersion); + } + else if (!_strnicmp(line, "CrossPointerReversePolarity=", 28)) { + strncpy(buffer, line + 28, 255); + bCrossPointerReversePolarity = !_strnicmp(buffer, "TRUE", 4); + } else if (!_strnicmp(line, "CDRVesselName=", 14)) { strncpy(buffer, line + 14, 255); strCDRName.assign(buffer); @@ -524,6 +536,16 @@ namespace mission { return bHasRateAidedOptics; } + int Mission::GetLMCWEAVersion() const + { + return iLMCWEAVersion; + } + + bool Mission::GetCrossPointerReversePolarity() const + { + return bCrossPointerReversePolarity; + } + void Mission::ReadCueCardLine(char *line, int vehicle) { char buffer[128]; diff --git a/Orbitersdk/samples/ProjectApollo/src_aux/Mission.h b/Orbitersdk/samples/ProjectApollo/src_aux/Mission.h index 411cdf8d2c..53431b5d4b 100644 --- a/Orbitersdk/samples/ProjectApollo/src_aux/Mission.h +++ b/Orbitersdk/samples/ProjectApollo/src_aux/Mission.h @@ -87,6 +87,7 @@ namespace mission VECTOR3 GetCGOfEmptySM() const; //false = Optics mode switch is not bypassed for CMC to optics commands, true = optics mode switch is bypassed for CMC to optics commands (ECP 792) bool HasRateAidedOptics() const; + // MATRIX3 GetCM_IMU_Drift() const; // @@ -99,6 +100,12 @@ namespace mission VECTOR3 GetCM_PIPA_Scale() const; // VECTOR3 GetLM_PIPA_Scale() const; + + //0 = LM-7 and before (ASC PRESS LOW before staging, RCS for HEATER FAILURE CAUTION), 1 = LM-8 and after (both cut and capped) + int GetLMCWEAVersion() const; + //false = Normal polarity (Apollo 14 and earlier), Lateral axis for PGNS and LR input has switched polarity (Apollo 15 and later) + bool GetCrossPointerReversePolarity() const; + //Get cue cards bool GetCSMCueCards(unsigned &counter, unsigned &loc, std::string &meshname, VECTOR3 &ofs); //Name of CDR @@ -155,6 +162,8 @@ namespace mission int iCMtoLMPowerConnectionVersion; VECTOR3 EmptySMCG; bool bHasRateAidedOptics; + int iLMCWEAVersion; + bool bCrossPointerReversePolarity; std::vector CSMCueCards; std::vector LMCueCards; diff --git a/Orbitersdk/samples/ProjectApollo/src_launch/MCC_Mission_G.cpp b/Orbitersdk/samples/ProjectApollo/src_launch/MCC_Mission_G.cpp index f0b5584292..7f42a9efb8 100644 --- a/Orbitersdk/samples/ProjectApollo/src_launch/MCC_Mission_G.cpp +++ b/Orbitersdk/samples/ProjectApollo/src_launch/MCC_Mission_G.cpp @@ -316,23 +316,26 @@ void MCC::MissionSequence_G() case MST_G_LUNAR_ORBIT_ASCENT_DAY_6: //LM Liftoff Evaluation to CMC LM State Vector update UpdateMacro(UTP_NONE, PT_NONE, rtcc->GETEval2(rtcc->calcParams.Insertion + 120.0), 104, MST_G_LUNAR_ORBIT_ASCENT_DAY_7, scrubbed, SubStateTime > 15.0*60.0, MST_G_LUNAR_ORBIT_ASCENT_DAY_2); break; - case MST_G_LUNAR_ORBIT_ASCENT_DAY_7: //CMC LM State Vector update to CSM state vector update - UpdateMacro(UTP_CMCUPLINKONLY, PT_NONE, MoonRev >= 27 && MoonRevTime > 95.0*60.0, 2, MST_G_LUNAR_ORBIT_ASCENT_DAY_8); + case MST_G_LUNAR_ORBIT_ASCENT_DAY_7: //CMC LM State Vector update to CSM DAP Update + UpdateMacro(UTP_CMCUPLINKONLY, PT_NONE, (rtcc->calcParams.src->DockingStatus(0) == 1) && (MoonRev >= 27 && MoonRevTime > 38.0*60.0), 2, MST_G_LUNAR_ORBIT_ASCENT_DAY_8); break; - case MST_G_LUNAR_ORBIT_ASCENT_DAY_8: //CSM state vector update to Preliminary TEI-30 update - UpdateMacro(UTP_CMCUPLINKONLY, PT_NONE, MoonRev >= 29 && MoonRevTime > 40.0*60.0, 1, MST_G_LUNAR_ORBIT_ASCENT_DAY_9); + case MST_G_LUNAR_ORBIT_ASCENT_DAY_8: //CSM DAP Update to CSM state vector update + UpdateMacro(UTP_PADONLY, PT_AP10DAPDATA, MoonRev >= 27 && MoonRevTime > 95.0*60.0, 39, MST_G_LUNAR_ORBIT_ASCENT_DAY_9); break; - case MST_G_LUNAR_ORBIT_ASCENT_DAY_9: //Preliminary TEI-30 update to Final TEI-30 Update - UpdateMacro(UTP_PADONLY, PT_AP11MNV, MoonRev >= 30 && MoonRevTime > 55.0*60.0, 45, MST_G_LUNAR_ORBIT_ASCENT_DAY_10); + case MST_G_LUNAR_ORBIT_ASCENT_DAY_9: //CSM state vector update to Preliminary TEI-30 update + UpdateMacro(UTP_CMCUPLINKONLY, PT_NONE, MoonRev >= 29 && MoonRevTime > 40.0*60.0, 1, MST_G_LUNAR_ORBIT_ASCENT_DAY_10); break; - case MST_G_LUNAR_ORBIT_ASCENT_DAY_10: //Final TEI-30 Update to TEI-31 PAD - UpdateMacro(UTP_PADWITHCMCUPLINK, PT_AP11MNV, SubStateTime > 5.0*60.0, 46, MST_G_LUNAR_ORBIT_ASCENT_DAY_11); + case MST_G_LUNAR_ORBIT_ASCENT_DAY_10: //Preliminary TEI-30 update to Final TEI-30 Update + UpdateMacro(UTP_PADONLY, PT_AP11MNV, MoonRev >= 30 && MoonRevTime > 55.0*60.0, 45, MST_G_LUNAR_ORBIT_ASCENT_DAY_11); break; - case MST_G_LUNAR_ORBIT_ASCENT_DAY_11: //TEI-31 PAD to TEI Evaluation - UpdateMacro(UTP_PADONLY, PT_AP11MNV, rtcc->GETEval2(rtcc->calcParams.TEI + 300.0), 47, MST_G_LUNAR_ORBIT_ASCENT_DAY_12); + case MST_G_LUNAR_ORBIT_ASCENT_DAY_11: //Final TEI-30 Update to TEI-31 PAD + UpdateMacro(UTP_PADWITHCMCUPLINK, PT_AP11MNV, SubStateTime > 5.0*60.0, 46, MST_G_LUNAR_ORBIT_ASCENT_DAY_12); break; - case MST_G_LUNAR_ORBIT_ASCENT_DAY_12: //TEI Evaluation to TEI - UpdateMacro(UTP_NONE, PT_NONE, true, 105, MST_G_TRANSEARTH_1, scrubbed, MoonRevTime > 40.0*60.0, MST_G_LUNAR_ORBIT_ASCENT_DAY_10); + case MST_G_LUNAR_ORBIT_ASCENT_DAY_12: //TEI-31 PAD to TEI Evaluation + UpdateMacro(UTP_PADONLY, PT_AP11MNV, rtcc->GETEval2(rtcc->calcParams.TEI + 300.0), 47, MST_G_LUNAR_ORBIT_ASCENT_DAY_13); + break; + case MST_G_LUNAR_ORBIT_ASCENT_DAY_13: //TEI Evaluation to TEI + UpdateMacro(UTP_NONE, PT_NONE, true, 105, MST_G_TRANSEARTH_1, scrubbed, MoonRevTime > 40.0*60.0, MST_G_LUNAR_ORBIT_ASCENT_DAY_11); break; case MST_G_TRANSEARTH_1: //TEI to PTC REFSMMAT switch (SubState) diff --git a/Orbitersdk/samples/ProjectApollo/src_launch/MCC_Mission_G.h b/Orbitersdk/samples/ProjectApollo/src_launch/MCC_Mission_G.h index 0c6620531d..07ff7fcb37 100644 --- a/Orbitersdk/samples/ProjectApollo/src_launch/MCC_Mission_G.h +++ b/Orbitersdk/samples/ProjectApollo/src_launch/MCC_Mission_G.h @@ -108,6 +108,7 @@ See http://nassp.sourceforge.net/license/ for more details. #define MST_G_LUNAR_ORBIT_ASCENT_DAY_10 169 #define MST_G_LUNAR_ORBIT_ASCENT_DAY_11 170 #define MST_G_LUNAR_ORBIT_ASCENT_DAY_12 171 +#define MST_G_LUNAR_ORBIT_ASCENT_DAY_13 172 #define MST_G_TRANSEARTH_1 200 #define MST_G_TRANSEARTH_2 201 #define MST_G_TRANSEARTH_3 202 diff --git a/Orbitersdk/samples/ProjectApollo/src_launch/RTCC_Mission_G.cpp b/Orbitersdk/samples/ProjectApollo/src_launch/RTCC_Mission_G.cpp index b19452bd0f..8e27574b09 100644 --- a/Orbitersdk/samples/ProjectApollo/src_launch/RTCC_Mission_G.cpp +++ b/Orbitersdk/samples/ProjectApollo/src_launch/RTCC_Mission_G.cpp @@ -639,8 +639,14 @@ bool RTCC::CalculationMTP_G(int fcn, LPVOID &pad, char * upString, char * upDesc PZREAP.RRBIAS = 1285.0; entopt.t_zmin = 145.0*3600.0; + //Temporarily set the minimum pericynthion height constraint to 40 NM. This was apparently done on the actual mission as well to make the desired solution converge + PZREAP.HMINMC = 40.0; + RTEMoonTargeting(&entopt, &res); + //Set back HMINMC to original value + PZREAP.HMINMC = 50.0; + opt.R_LLS = BZLAND.rad[RTCC_LMPOS_BEST]; opt.dV_LVLH = res.dV_LVLH; opt.enginetype = SPSRCSDecision(SPS_THRUST / (calcParams.src->GetMass() + calcParams.tgt->GetMass()), res.dV_LVLH); @@ -1169,13 +1175,20 @@ bool RTCC::CalculationMTP_G(int fcn, LPVOID &pad, char * upString, char * upDesc } } break; - case 33: //CSM DAP DATA + case 33: //CSM DAP DATA (Undocked) { AP10DAPDATA * form = (AP10DAPDATA *)pad; CSMDAPUpdate(calcParams.src, *form, false); } break; + case 39: //CSM DAP DATA (Docked) + { + AP10DAPDATA * form = (AP10DAPDATA *)pad; + + CSMDAPUpdate(calcParams.src, *form, true); + } + break; case 34: //LM DAP DATA { LMACTDATA * form = (LMACTDATA *)pad; @@ -1416,7 +1429,6 @@ bool RTCC::CalculationMTP_G(int fcn, LPVOID &pad, char * upString, char * upDesc sv2 = coast(sv1, 1.0*2.0*3600.0); } - entopt.Inclination = -40.0*RAD; entopt.returnspeed = 1; entopt.RV_MCC = sv2; entopt.vessel = calcParams.src; diff --git a/Orbitersdk/samples/ProjectApollo/src_launch/rtcc.cpp b/Orbitersdk/samples/ProjectApollo/src_launch/rtcc.cpp index 13b896dd22..0ef16db0f7 100644 --- a/Orbitersdk/samples/ProjectApollo/src_launch/rtcc.cpp +++ b/Orbitersdk/samples/ProjectApollo/src_launch/rtcc.cpp @@ -24148,7 +24148,7 @@ void RTCC::PMMREAST(int med, EphemerisData *sv) sv_r.RBI = BODY_EARTH; AST.lat_SPL = rte.EntryLatcor; AST.lng_SPL = rte.EntryLngcor; - AST.SplashdownGMT = rte.t_z; + AST.SplashdownGMT = rte.t_Landing; AST.DV = rte.DV; AST.h_PC = rte.FlybyPeriAlt; } diff --git a/Orbitersdk/samples/ProjectApollo/src_lm/Sat5LMDSC.cpp b/Orbitersdk/samples/ProjectApollo/src_lm/Sat5LMDSC.cpp index 7c4f36f5fe..eca0daf2dd 100644 --- a/Orbitersdk/samples/ProjectApollo/src_lm/Sat5LMDSC.cpp +++ b/Orbitersdk/samples/ProjectApollo/src_lm/Sat5LMDSC.cpp @@ -331,7 +331,7 @@ void Sat5LMDSC::clbkLoadStateEx(FILEHANDLE scn, void *vstatus) { sscanf(line + 5, "%d", &state); } - else if (!strnicmp(line, "APOLLONO", 8)) { + else if (!_strnicmp(line, "APOLLONO", 8)) { sscanf(line + 8, "%d", &ApolloNo); if (sscanf(line + 8, "%d", &ApolloNo) == 1) diff --git a/Orbitersdk/samples/ProjectApollo/src_lm/lemsystems.cpp b/Orbitersdk/samples/ProjectApollo/src_lm/lemsystems.cpp index 7e46db3c80..2745b08057 100644 --- a/Orbitersdk/samples/ProjectApollo/src_lm/lemsystems.cpp +++ b/Orbitersdk/samples/ProjectApollo/src_lm/lemsystems.cpp @@ -3194,7 +3194,7 @@ void CrossPointer::Timestep(double simdt) vy = lem->LR.rate[1] * 0.3048; //Apollo 15 and later had this inversed - if (lem->ApolloNo >= 15) + if (lem->pMission->GetCrossPointerReversePolarity()) { vy *= -1.0; } @@ -3214,7 +3214,7 @@ void CrossPointer::Timestep(double simdt) vy = lgc_lateral*0.3048; //Apollo 15 and later had this inversed - if (lem->ApolloNo >= 15) + if (lem->pMission->GetCrossPointerReversePolarity()) { vy *= -1.0; } diff --git a/Orbitersdk/samples/ProjectApollo/src_lm/lm_cwea.cpp b/Orbitersdk/samples/ProjectApollo/src_lm/lm_cwea.cpp index 92825c566d..f1c73fd554 100644 --- a/Orbitersdk/samples/ProjectApollo/src_lm/lm_cwea.cpp +++ b/Orbitersdk/samples/ProjectApollo/src_lm/lm_cwea.cpp @@ -30,6 +30,7 @@ See http://nassp.sourceforge.net/license/ for more details. #include "LEMcomputer.h" #include "LEM.h" #include "papi.h" +#include "Mission.h" #include "lm_cwea.h" // CWEA @@ -134,7 +135,7 @@ void LEM_CWEA::Timestep(double simdt) { lightlogic = true; } // Fuel and oxidizer pressure < 119.8 psia prior to staging, cut and capped from the CWEA on LM-8 and subsequent - if (((lem->ApolloNo < 14 || lem->ApolloNo == 1301) && lem->stage < 2) && (lem->APSPropellant.GetFuelTrimOrificeOutletPressurePSI() < 119.8 || lem->APSPropellant.GetOxidTrimOrificeOutletPressurePSI() < 119.8)) { + if ((lem->pMission->GetLMCWEAVersion() == 0 && lem->stage < 2) && (lem->APSPropellant.GetFuelTrimOrificeOutletPressurePSI() < 119.8 || lem->APSPropellant.GetOxidTrimOrificeOutletPressurePSI() < 119.8)) { lightlogic = true; } @@ -410,19 +411,19 @@ void LEM_CWEA::Timestep(double simdt) { // RCS Quads < 118.8F or > 190.5F, cut and capped on LM-8 and subsequent //Quad 1 - QD1HeaterCautFF.Set((lem->ApolloNo < 14 || lem->ApolloNo == 1301) && (lem->scera1.GetVoltage(20, 4) < 2.79 || lem->scera1.GetVoltage(20, 4) > 4.725)); + QD1HeaterCautFF.Set(lem->pMission->GetLMCWEAVersion() == 0 && (lem->scera1.GetVoltage(20, 4) < 2.79 || lem->scera1.GetVoltage(20, 4) > 4.725)); QD1HeaterCautFF.Reset(lem->TempMonitorRotary.GetState() == 2); //Quad 2 - QD2HeaterCautFF.Set((lem->ApolloNo < 14 || lem->ApolloNo == 1301) && (lem->scera1.GetVoltage(20, 3) < 2.79 || lem->scera1.GetVoltage(20, 3) > 4.725)); + QD2HeaterCautFF.Set(lem->pMission->GetLMCWEAVersion() == 0 && (lem->scera1.GetVoltage(20, 3) < 2.79 || lem->scera1.GetVoltage(20, 3) > 4.725)); QD2HeaterCautFF.Reset(lem->TempMonitorRotary.GetState() == 3); //Quad 3 - QD3HeaterCautFF.Set((lem->ApolloNo < 14 || lem->ApolloNo == 1301) && (lem->scera1.GetVoltage(20, 2) < 2.79 || lem->scera1.GetVoltage(20, 2) > 4.725)); + QD3HeaterCautFF.Set(lem->pMission->GetLMCWEAVersion() == 0 && (lem->scera1.GetVoltage(20, 2) < 2.79 || lem->scera1.GetVoltage(20, 2) > 4.725)); QD3HeaterCautFF.Reset(lem->TempMonitorRotary.GetState() == 4); //Quad 4 - QD4HeaterCautFF.Set((lem->ApolloNo < 14 || lem->ApolloNo == 1301) && (lem->scera1.GetVoltage(20, 1) < 2.79 || lem->scera1.GetVoltage(20, 1) > 4.725)); + QD4HeaterCautFF.Set(lem->pMission->GetLMCWEAVersion() == 0 && (lem->scera1.GetVoltage(20, 1) < 2.79 || lem->scera1.GetVoltage(20, 1) > 4.725)); QD4HeaterCautFF.Reset(lem->TempMonitorRotary.GetState() == 5); // S-Band Antenna Electronic Drive Assembly < -64.08F or > 152.63F diff --git a/Orbitersdk/samples/ProjectApollo/src_rtccmfd/ARCore.cpp b/Orbitersdk/samples/ProjectApollo/src_rtccmfd/ARCore.cpp index b1d3ac52a8..d2146f1b27 100644 --- a/Orbitersdk/samples/ProjectApollo/src_rtccmfd/ARCore.cpp +++ b/Orbitersdk/samples/ProjectApollo/src_rtccmfd/ARCore.cpp @@ -3726,6 +3726,11 @@ int ARCore::subThread() break; case 23: //Calculate TPI times { + if (target == NULL) + { + Result = DONE; + break; + } SV sv0 = GC->rtcc->StateVectorCalc(target); t_TPI = GC->rtcc->CalculateTPITimes(sv0, TPI_Mode, t_TPIguess, dt_TPI_sunrise); diff --git a/Orbitersdk/samples/ProjectApollo/src_rtccmfd/AnalyticEphemerisGenerator.cpp b/Orbitersdk/samples/ProjectApollo/src_rtccmfd/AnalyticEphemerisGenerator.cpp index 07e6ca17a9..6349386674 100644 --- a/Orbitersdk/samples/ProjectApollo/src_rtccmfd/AnalyticEphemerisGenerator.cpp +++ b/Orbitersdk/samples/ProjectApollo/src_rtccmfd/AnalyticEphemerisGenerator.cpp @@ -279,7 +279,7 @@ void PMMAEG::CALL(AEGHeader &header, AEGDataBlock &in, AEGDataBlock &out) CurrentBlock.Item8 = CurrentBlock.R - tempblock.R; CurrentBlock.Item9 = CurrentBlock.TE - tempblock.TE; dt += -theta_R / (CurrentBlock.l_dot + CurrentBlock.g_dot); - if (abs(theta_R) > 0.0001) + if (abs(theta_R) > 0.00005) { goto NewPMMAEG_V1000; } @@ -581,7 +581,7 @@ void PMMLAEG::CALL(AEGHeader &header, AEGDataBlock &in, AEGDataBlock &out) CurrentBlock.Item8 = CurrentBlock.R - tempblock.R; CurrentBlock.Item9 = CurrentBlock.TE - tempblock.TE; dt += -theta_R / (CurrentBlock.l_dot + CurrentBlock.g_dot); - if (abs(theta_R) > 0.0001) + if (abs(theta_R) > 0.00005) { goto NewPMMLAEG_V1000; } diff --git a/Orbitersdk/samples/ProjectApollo/src_rtccmfd/ApolloRTCCMFD.cpp b/Orbitersdk/samples/ProjectApollo/src_rtccmfd/ApolloRTCCMFD.cpp index 824aa45f93..730d8764fe 100644 --- a/Orbitersdk/samples/ProjectApollo/src_rtccmfd/ApolloRTCCMFD.cpp +++ b/Orbitersdk/samples/ProjectApollo/src_rtccmfd/ApolloRTCCMFD.cpp @@ -966,7 +966,7 @@ void ApolloRTCCMFD::menuSetMPTInitPage() GC->mptInitError = 0; marker = 0; - markermax = 7; + markermax = 5; } void ApolloRTCCMFD::menuSetDescPlanTablePage() @@ -2834,12 +2834,12 @@ bool EntryDesiredInclinationInput(void *id, char *str, void *data) { if (strcmp(dir, "A") == 0) { - ((ApolloRTCCMFD*)data)->set_EntryDesiredInclination(-inc); + ((ApolloRTCCMFD*)data)->set_EntryDesiredInclination(inc); return true; } else if (strcmp(dir, "D") == 0) { - ((ApolloRTCCMFD*)data)->set_EntryDesiredInclination(inc); + ((ApolloRTCCMFD*)data)->set_EntryDesiredInclination(-inc); return true; } } @@ -3748,32 +3748,35 @@ void ApolloRTCCMFD::menuTransferPoweredDescentToMPT() G->TransferPoweredDescentToMPT(); } +void ApolloRTCCMFD::menuCycleMPTTable() +{ + if (GC->rtcc->med_m49.Table == RTCC_MPT_CSM) + { + GC->rtcc->med_m49.Table = GC->rtcc->med_m50.Table = GC->rtcc->med_m51.Table = GC->rtcc->med_m55.Table = RTCC_MPT_LM; + } + else + { + GC->rtcc->med_m49.Table = GC->rtcc->med_m50.Table = GC->rtcc->med_m51.Table = GC->rtcc->med_m55.Table = RTCC_MPT_CSM; + } +} + +void ApolloRTCCMFD::menuCycleMPTMED() +{ + if (G->mptinitmode < 3) + { + G->mptinitmode++; + } + else + { + G->mptinitmode = 0; + } +} + void ApolloRTCCMFD::menuSetMPTInitInput() { switch (marker) { - case 0: - //MED - if (G->mptinitmode < 3) - { - G->mptinitmode++; - } - else - { - G->mptinitmode = 0; - } - break; - case 1: //MPT - if (GC->rtcc->med_m49.Table == RTCC_MPT_CSM) - { - GC->rtcc->med_m49.Table = GC->rtcc->med_m50.Table = GC->rtcc->med_m51.Table = GC->rtcc->med_m55.Table = RTCC_MPT_LM; - } - else - { - GC->rtcc->med_m49.Table = GC->rtcc->med_m50.Table = GC->rtcc->med_m51.Table = GC->rtcc->med_m55.Table = RTCC_MPT_CSM; - } - break; - case 2: //Second option on MED + case 0: //Second option on MED switch (G->mptinitmode) { case 0: //M49: SPS Fuel Remaining @@ -3793,7 +3796,7 @@ void ApolloRTCCMFD::menuSetMPTInitInput() break; } break; - case 3: //Third option on MED + case 1: //Third option on MED switch (G->mptinitmode) { case 0: //M49: CSM RCS Fuel Remaining @@ -3810,7 +3813,7 @@ void ApolloRTCCMFD::menuSetMPTInitInput() break; } break; - case 4: //Fourth option on MED + case 2: //Fourth option on MED switch (G->mptinitmode) { case 0: //M49: S-IVB Fuel Remaining @@ -3827,7 +3830,7 @@ void ApolloRTCCMFD::menuSetMPTInitInput() break; } break; - case 5: //Fifth option on MED + case 3: //Fifth option on MED switch (G->mptinitmode) { case 0: //M49: LM APS Fuel Remaining @@ -3841,7 +3844,7 @@ void ApolloRTCCMFD::menuSetMPTInitInput() break; } break; - case 6: //Sixth option on MED + case 4: //Sixth option on MED switch (G->mptinitmode) { case 0: //M49: LM RCS Fuel Remaining @@ -3855,7 +3858,7 @@ void ApolloRTCCMFD::menuSetMPTInitInput() break; } break; - case 7: //Seventh option on MED + case 5: //Seventh option on MED switch (G->mptinitmode) { case 0: //M49: LM DPS Fuel Remaining diff --git a/Orbitersdk/samples/ProjectApollo/src_rtccmfd/ApolloRTCCMFD.h b/Orbitersdk/samples/ProjectApollo/src_rtccmfd/ApolloRTCCMFD.h index 8a9958b955..9879e5ccc7 100644 --- a/Orbitersdk/samples/ProjectApollo/src_rtccmfd/ApolloRTCCMFD.h +++ b/Orbitersdk/samples/ProjectApollo/src_rtccmfd/ApolloRTCCMFD.h @@ -554,6 +554,8 @@ class ApolloRTCCMFD: public MFD2 { void menuTransferPoweredAscentToMPT(); void menuTransferPoweredDescentToMPT(); void CheckoutMonitorCalc(); + void menuCycleMPTTable(); + void menuCycleMPTMED(); void menuSetMPTInitInput(); void set_MPTInitM55Config(char *cfg); void menuMPTUpdate(); diff --git a/Orbitersdk/samples/ProjectApollo/src_rtccmfd/ApolloRTCCMFD_Display.cpp b/Orbitersdk/samples/ProjectApollo/src_rtccmfd/ApolloRTCCMFD_Display.cpp index f4fb57c7ad..87f694b869 100644 --- a/Orbitersdk/samples/ProjectApollo/src_rtccmfd/ApolloRTCCMFD_Display.cpp +++ b/Orbitersdk/samples/ProjectApollo/src_rtccmfd/ApolloRTCCMFD_Display.cpp @@ -5317,21 +5317,21 @@ bool ApolloRTCCMFD::Update(oapi::Sketchpad *skp) skp->SetTextAlign(oapi::Sketchpad::LEFT); - skp->Text(1 * W / 16, (marker + 4) * H / 16, "*", 1); + skp->Text(1 * W / 16, (marker + 6) * H / 16, "*", 1); skp->Text(10 * W / 16, 5 * H / 16, "MPT:", 4); if (G->mptinitmode == 0) { - skp->Text(2 * W / 16, 4 * H / 16, "MED M49: Fuel Remaining", 23); + skp->Text(2 * W / 16, 4 * H / 14, "MED M49: Fuel Remaining", 23); if (GC->rtcc->med_m49.Table == RTCC_MPT_LM) { - skp->Text(2 * W / 16, 5 * H / 16, "Table: LM", 9); + skp->Text(2 * W / 16, 2 * H / 14, "Table: LM", 9); } else { - skp->Text(2 * W / 16, 5 * H / 16, "Table: CSM", 10); + skp->Text(2 * W / 16, 2 * H / 14, "Table: CSM", 10); } if (GC->rtcc->med_m49.SPSFuelRemaining >= 0) @@ -5411,15 +5411,15 @@ bool ApolloRTCCMFD::Update(oapi::Sketchpad *skp) } else if (G->mptinitmode == 1) { - skp->Text(2 * W / 16, 4 * H / 16, "MED M50: Weights", 16); + skp->Text(2 * W / 16, 4 * H / 14, "MED M50: Weights", 16); if (GC->rtcc->med_m50.Table == RTCC_MPT_LM) { - skp->Text(2 * W / 16, 5 * H / 16, "Table: LM", 9); + skp->Text(2 * W / 16, 2 * H / 14, "Table: LM", 9); } else { - skp->Text(2 * W / 16, 5 * H / 16, "Table: CSM", 10); + skp->Text(2 * W / 16, 2 * H / 14, "Table: CSM", 10); } if (GC->rtcc->med_m50.CSMWT >= 0) @@ -5481,15 +5481,15 @@ bool ApolloRTCCMFD::Update(oapi::Sketchpad *skp) } else if (G->mptinitmode == 2) { - skp->Text(2 * W / 16, 4 * H / 16, "MED M51: Areas", 14); + skp->Text(2 * W / 16, 4 * H / 14, "MED M51: Areas", 14); if (GC->rtcc->med_m51.Table == RTCC_MPT_LM) { - skp->Text(2 * W / 16, 5 * H / 16, "Table: LM", 9); + skp->Text(2 * W / 16, 2 * H / 14, "Table: LM", 9); } else { - skp->Text(2 * W / 16, 5 * H / 16, "Table: CSM", 10); + skp->Text(2 * W / 16, 2 * H / 14, "Table: CSM", 10); } sprintf(Buffer, "CSM %.2f sq ft", GC->rtcc->med_m51.CSMArea / 0.3048 / 0.3048); @@ -5521,15 +5521,15 @@ bool ApolloRTCCMFD::Update(oapi::Sketchpad *skp) } else { - skp->Text(2 * W / 16, 4 * H / 16, "MED M55: Configuration", 22); + skp->Text(2 * W / 16, 4 * H / 14, "MED M55: Configuration", 22); if (GC->rtcc->med_m55.Table == RTCC_MPT_LM) { - skp->Text(2 * W / 16, 5 * H / 16, "Table: LM", 9); + skp->Text(2 * W / 16, 2 * H / 14, "Table: LM", 9); } else { - skp->Text(2 * W / 16, 5 * H / 16, "Table: CSM", 10); + skp->Text(2 * W / 16, 2 * H / 14, "Table: CSM", 10); } if (GC->rtcc->med_m55.ConfigCode == "") diff --git a/Orbitersdk/samples/ProjectApollo/src_rtccmfd/ApollomfdButtons.cpp b/Orbitersdk/samples/ProjectApollo/src_rtccmfd/ApollomfdButtons.cpp index a884e9e11d..24f9593afd 100644 --- a/Orbitersdk/samples/ProjectApollo/src_rtccmfd/ApollomfdButtons.cpp +++ b/Orbitersdk/samples/ProjectApollo/src_rtccmfd/ApollomfdButtons.cpp @@ -2011,16 +2011,16 @@ ApolloRTCCMFDButtons::ApolloRTCCMFDButtons() static const MFDBUTTONMENU mnu59[] = { - { "Set input", 0, 'S' }, + { "Choose Table", 0, 'T' }, + { "Choose MED", 0, 'E' }, + { "Update MPT", 0, 'M' }, { "Previous Item", 0, 'P' }, { "Next Item", 0, 'N' }, - { "", 0, ' ' }, - { "", 0, ' ' }, - { "", 0, ' ' }, + { "Set input", 0, 'S' }, { "Select vehicle", 0, 'D' }, { "Auto update of parameters", 0, 'U' }, - { "Update MPT", 0, 'M' }, + { "", 0, ' ' }, { "", 0, ' ' }, { "Vector Panel Summary", 0, 'P' }, { "Back to menu", 0, 'B' }, @@ -2028,16 +2028,16 @@ ApolloRTCCMFDButtons::ApolloRTCCMFDButtons() RegisterPage(mnu59, sizeof(mnu59) / sizeof(MFDBUTTONMENU)); - RegisterFunction("SET", OAPI_KEY_S, &ApolloRTCCMFD::menuSetMPTInitInput); + RegisterFunction("TAB", OAPI_KEY_A, &ApolloRTCCMFD::menuCycleMPTTable); + RegisterFunction("MED", OAPI_KEY_E, &ApolloRTCCMFD::menuCycleMPTMED); + RegisterFunction("UPD", OAPI_KEY_M, &ApolloRTCCMFD::menuMPTUpdate); RegisterFunction("<<", OAPI_KEY_P, &ApolloRTCCMFD::menuCycleMarkerDown); RegisterFunction(">>", OAPI_KEY_N, &ApolloRTCCMFD::menuCycleMarkerUp); - RegisterFunction("", OAPI_KEY_A, &ApolloRTCCMFD::menuVoid); - RegisterFunction("", OAPI_KEY_C, &ApolloRTCCMFD::menuVoid); - RegisterFunction("", OAPI_KEY_E, &ApolloRTCCMFD::menuVoid); + RegisterFunction("SET", OAPI_KEY_S, &ApolloRTCCMFD::menuSetMPTInitInput); RegisterFunction("TGT", OAPI_KEY_D, &ApolloRTCCMFD::menuMPTInitM50M55Vehicle); RegisterFunction("AUT", OAPI_KEY_U, &ApolloRTCCMFD::menuMPTInitAutoUpdate); - RegisterFunction("UPD", OAPI_KEY_M, &ApolloRTCCMFD::menuMPTUpdate); + RegisterFunction("", OAPI_KEY_C, &ApolloRTCCMFD::menuVoid); RegisterFunction("", OAPI_KEY_N, &ApolloRTCCMFD::menuVoid); RegisterFunction("VPS", OAPI_KEY_P, &ApolloRTCCMFD::menuVectorPanelSummaryPage); RegisterFunction("BCK", OAPI_KEY_B, &ApolloRTCCMFD::menuSetMPTPage); diff --git a/Orbitersdk/samples/ProjectApollo/src_rtccmfd/EntryCalculations.cpp b/Orbitersdk/samples/ProjectApollo/src_rtccmfd/EntryCalculations.cpp index 0415293ee3..0a7af59ff4 100644 --- a/Orbitersdk/samples/ProjectApollo/src_rtccmfd/EntryCalculations.cpp +++ b/Orbitersdk/samples/ProjectApollo/src_rtccmfd/EntryCalculations.cpp @@ -427,14 +427,29 @@ namespace EntryCalculations return u_r; } - void AESR(double r1, double r2, double beta1, double T, double R, double mu, double eps, double &a, double &e, int &k2, int &info, double &V1) - { + void AESR(double r1, double r2, double beta1, double T, double R, double mu, double eps, double &a, double &e, bool &k2, int &info, double &V1) + { + //INPUT: + //r1: first radial distance + //r2: second radial distance + //beta1: flight-path angle for first radius + //T: flight time + //R: radius of the central body + //mu: gravitational constant + //eps: tolerance on time + //OUTPUT: + //a: semimajor axis; or p, the semilatus rectum + //e: eccentricity + //k2: 0 = no apogee passage, 1 = apogee passage + //INFO: 0 = no solution found, 1 = solution found + //V1: reentry velocity + double tan_eta1_2, M_1, q, p, tan_eta2_2, M_2, T_P, DT, T_m, a_m, T_1, DDT_m, esinE_1, ecosE_1, E_1, DT_m, Q, k_1_apo, DT_1; double esinE_2, ecosE_2, E_2, T_12, k_apo, k, B, sec2_eta12; int iter, IH, C_2; C_2 = 1; - k2 = 0; + k2 = false; //On parabolic trajectories the flight path angle (measured from local horizontal!) is always one-half the true anomaly tan_eta1_2 = OrbMech::cot(beta1); //M_1 is twice of parabolic mean anomaly @@ -510,7 +525,7 @@ namespace EntryCalculations { //We have an apogee passage Q = -1.0; - k2 = 1; + k2 = true; iter = 2; k_1_apo = 0.0; T_1 = T_P; @@ -519,7 +534,7 @@ namespace EntryCalculations { //We have no apogee passage Q = 1.0; - k2 = 0; + k2 = false; if (T <= 1.2*T_P) { iter = 1; @@ -542,9 +557,9 @@ namespace EntryCalculations V1 = sqrt(mu*(2.0 / r1 - 1.0 / a)); esinE_1 = r1 * V1*cos(beta1) / sqrt(abs(a)*mu); ecosE_1 = 1.0 - r1 / a; - e = sqrt(esinE_1*esinE_1 + ecosE_1 * ecosE_1); if (a > 0.0) { + e = sqrt(ecosE_1 * ecosE_1 + esinE_1 * esinE_1); //Pythagorean identity for ellipses E_1 = atan2(esinE_1, ecosE_1); if (E_1 < 0) { @@ -560,6 +575,7 @@ namespace EntryCalculations } else { + e = sqrt(ecosE_1 * ecosE_1 - esinE_1 * esinE_1); //Pythagorean identity for hyperbolas E_1 = atanh(esinE_1 / ecosE_1); E_2 = acosh(1.0 / e * (1.0 - r2 / a)); esinE_2 = e * sinh(E_2); @@ -727,249 +743,34 @@ namespace EntryCalculations T = fmod(alpha_go, PI2); } - void Abort(VECTOR3 R0, VECTOR3 V0, double RCON, double dt, double mu, VECTOR3 &DV, VECTOR3 &R_EI, VECTOR3 &V_EI) + double XDOTX2(VECTOR3 a, VECTOR3 b, double DIFG) { - double k4, x2, v2, x2_apo, x2_err; - VECTOR3 V2; - - k4 = -0.10453; + //Calculate alpha given a, b, and DIFG - x2 = k4; - x2_err = 1.0; + double alpha, k; - while (abs(x2_err) > 0.00001) + alpha = acos2(dotp(unit(a), unit(b))); + k = DIFG * (a.x*b.y - a.y*b.x); + if (k < 0) { - time_reentry(R0, V0, RCON, x2, dt, mu, V2, R_EI, V_EI); - - v2 = length(V_EI); - x2_apo = x2; - x2 = ReentryTargetLineTan(v2, false); - x2_err = x2 - x2_apo; + alpha = PI2 - alpha; } - DV = V2 - V0; + return alpha; } - bool Abort_plane(VECTOR3 R0, VECTOR3 V0, double MJD0, double RCON, double dt, double mu, double Incl, double INTER, VECTOR3 &DV, VECTOR3 &R_EI, VECTOR3 &V_EI, double &Incl_apo) + void RA2XYZ4(VECTOR3 R, VECTOR3 V, double &beta, double &A_Z) { - bool NIR; - double k4, x2, v2, x2_apo, x2_err, ra, dec, Omega; - VECTOR3 V2, U_H; - - k4 = -0.10453; - NIR = false; - - x2 = k4; - x2_err = 1.0; - - OrbMech::ra_and_dec_from_r(R0, ra, dec); - //Make sure the inclination is larger than the declination - if (Incl <= abs(dec)) - { - Incl_apo = abs(dec) + 0.0001; - NIR = true; - } - else - { - Incl_apo = Incl; - } - - if (INTER > 0) - { - Omega = ra + asin(tan(dec) / tan(Incl_apo)) + PI; - } - else - { - Omega = ra - asin(tan(dec) / tan(Incl_apo)); - } - U_H = unit(_V(sin(Omega)*sin(Incl_apo), -cos(Omega)*sin(Incl_apo), cos(Incl_apo))); - - while (abs(x2_err) > 0.00001) - { - time_reentry_plane(R0, U_H, RCON, x2, dt, mu, V2, R_EI, V_EI); - - v2 = length(V_EI); - x2_apo = x2; - x2 = ReentryTargetLineTan(v2, false); - x2_err = x2 - x2_apo; - } - DV = V2 - V0; - - return NIR; - } - - void time_reentry(VECTOR3 R0, VECTOR3 V0, double r1, double x2, double dt, double mu, VECTOR3 &V, VECTOR3 &R_EI, VECTOR3 &V_EI) - { - VECTOR3 U_R1, U_V1, eta, U_H; - double r0, lambda, MA1, MA2, beta1, beta5, theta1, theta2, theta3, beta10, xmin, xmax, dxmax, C0, C1, C2, C3, x, dx; - double x_old, dt_err, p, dt_act, dt_err_old, C_FPA; - int i; - - MA1 = -6.986643e7; - C0 = 1.81000432e8; - C1 = 1.5078514; - C2 = -6.49993054e-9; - C3 = 9.769389245e-18; - - U_R1 = unit(R0); - U_V1 = unit(V0); - r0 = length(R0); - C_FPA = dotp(U_R1, U_V1); - if (abs(C_FPA) < 0.99966) - { - eta = crossp(R0, V0); - } - else - { - eta = _V(0.0, 0.0, 1.0); - } - - if (eta.z < 0) - { - eta = -eta; - } - U_H = unit(crossp(eta, R0)); - - MA2 = C0 + C1*r0 + C2*r0*r0 + C3*r0*r0*r0; - - lambda = r0 / r1; - beta1 = 1.0 + x2*x2; - beta5 = lambda*beta1; - theta1 = beta5*lambda - 1.0; - theta2 = 2.0*r0*(lambda - 1.0); - theta3 = sqrt(mu) / r0; - beta10 = beta5*(MA1 - r0) / (MA1 - r1) - 1.0; - if (beta10 < 0.0) - { - xmin = 0.0; - } - else - { - xmin = -sqrt(beta10); - } - dxmax = -xmin / 16.0; - beta10 = beta5*(MA2 - r0) / (MA2 - r1) - 1.0; - if (beta10 < 0.0) - { - xmax = 0.0; - } - else - { - xmax = sqrt(beta10); - } + //Calculate beta, A_Z given R and V + double c, r; - - x = xmin; - dx = dxmax; - dt_err = 10.0; - i = 0; - while (abs(dt_err)>0.005) + r = length(R); + beta = XDOTX2(unit(R), unit(V), 0.0); + c = dotp(R, V) / r; + A_Z = atan2(R.x*V.y - R.y*V.x, r*V.z - c * R.z); + if (A_Z < 0) { - p = theta2 / (theta1 - x*x); - V = (U_R1*x + U_H)*theta3*sqrt(p); - dt_act = OrbMech::time_radius(R0, V, r1, -1.0, mu); - - dt_err = dt - dt_act; - - if (i == 0) - { - dx = -dxmax; - } - else - { - dx = (x - x_old) / (dt_err - dt_err_old)*dt_err; - if (abs(dx) > dxmax) - { - dx = OrbMech::sign(dx)*dxmax; - } - } - - dt_err_old = dt_err; - x_old = x; - x -= dx; - - i++; + A_Z += PI2; } - OrbMech::rv_from_r0v0(R0, V, dt, R_EI, V_EI, mu); - } - - void time_reentry_plane(VECTOR3 R0, VECTOR3 eta, double r1, double x2, double dt, double mu, VECTOR3 &V, VECTOR3 &R_EI, VECTOR3 &V_EI) - { - VECTOR3 U_R1, U_H; - double r0, lambda, MA1, MA2, beta1, beta5, theta1, theta2, theta3, beta10, xmin, xmax, dxmax, C0, C1, C2, C3, x, dx; - double x_old, dt_err, p, dt_act, dt_err_old; - int i; - - MA1 = -6.986643e7; - C0 = 1.81000432e8; - C1 = 1.5078514; - C2 = -6.49993054e-9; - C3 = 9.769389245e-18; - - U_R1 = unit(R0); - r0 = length(R0); - U_H = unit(crossp(eta, R0)); - - MA2 = C0 + C1 * r0 + C2 * r0*r0 + C3 * r0*r0*r0; - - lambda = r0 / r1; - beta1 = 1.0 + x2 * x2; - beta5 = lambda * beta1; - theta1 = beta5 * lambda - 1.0; - theta2 = 2.0*r0*(lambda - 1.0); - theta3 = sqrt(mu) / r0; - beta10 = beta5 * (MA1 - r0) / (MA1 - r1) - 1.0; - if (beta10 < 0.0) - { - xmin = 0.0; - } - else - { - xmin = -sqrt(beta10); - } - dxmax = -xmin / 16.0; - beta10 = beta5 * (MA2 - r0) / (MA2 - r1) - 1.0; - if (beta10 < 0.0) - { - xmax = 0.0; - } - else - { - xmax = sqrt(beta10); - } - - - x = xmin; - dx = dxmax; - dt_err = 10.0; - i = 0; - while (abs(dt_err)>0.005) - { - p = theta2 / (theta1 - x * x); - V = (U_R1*x + U_H)*theta3*sqrt(p); - dt_act = OrbMech::time_radius(R0, V, r1, -1.0, mu); - - dt_err = dt - dt_act; - - if (i == 0) - { - dx = -dxmax; - } - else - { - dx = (x - x_old) / (dt_err - dt_err_old)*dt_err; - if (abs(dx) > dxmax) - { - dx = OrbMech::sign(dx)*dxmax; - } - } - - dt_err_old = dt_err; - x_old = x; - x -= dx; - - i++; - } - OrbMech::rv_from_r0v0(R0, V, dt, R_EI, V_EI, mu); } double landingzonelong(int zone, double lat) @@ -4960,7 +4761,8 @@ void ConicRTEEarthNew::MAIN() //Pre-initialization VECTOR3 DV, V_a_uncal, V_a_cal; double beta_r, dv, U_r, DVC, T, VT_a, VR_a, v_a, beta_a, T_z, alpha, delta, lambda, p, eta_ar, phi, phi_z, theta_z, TP; - int J, J_m, FLAG, QA; + int J, J_m, FLAG; + bool QA; EphemerisData2 sv; J = 0; @@ -5111,7 +4913,8 @@ void ConicRTEEarthNew::INITAL() VECTOR3 R4, R5, R_p, U0_apo; double SAZ, CAZ, T1, T2, A_m, beta_r, p, R_a, A, DV, e, V_a, beta_a, T_1i, T_s, delta_0, Am1, Am2, beta_r_apo, A_Z; double theta_mu, theta_md, K1, K2, U_rmin, T_apo, DNDT, I_0, T, delta, U_r, VR_a, VT_a, eta_ar; - int QA, FLAG; + int FLAG; + bool QA; NOSOLN = 0; STORE = false; @@ -5379,9 +5182,9 @@ bool ConicRTEEarthNew::RUBR(int QA, int QE, double R_a, double U_0, double U_r, //Change in velocity DV = sqrt(U_0*U_0 + V_a * V_a - 2.0*U_0*V_a*cos(beta_a - beta_0)); //Time from abort to perigee - pRTCC->PITFPC(mu, 1 - QA, A, e, R_a, T_ap, Period); + pRTCC->PITFPC(mu, QA, A, e, R_a, T_ap, Period); //Time from reentry to perigee - pRTCC->PITFPC(mu, 1 - QA, A, e, RR, T_rp, Period); + pRTCC->PITFPC(mu, QA, A, e, RR, T_rp, Period); //Time from abort to reentry T = T_ap - T_rp; if (T < 0) @@ -5446,7 +5249,7 @@ void ConicRTEEarthNew::VARMIN() return; } -void ConicRTEEarthNew::VELCOM(double T, double R_a, double &beta_r, double &dt, double &p, int &QA, int &sw6, double &U_r, double &VR_a, double &VT_a, double &beta_a, double &eta_ar, double &DV) +void ConicRTEEarthNew::VELCOM(double T, double R_a, double &beta_r, double &dt, double &p, bool &QA, int &sw6, double &U_r, double &VR_a, double &VT_a, double &beta_a, double &eta_ar, double &DV) { double V_a, C0, C1, C2, S1, DVR, DVT, a, e, beta_rp; int info, TEMP; @@ -6137,7 +5940,8 @@ void ConicRTEEarthNew::TMIN(double &dv, int &FLAG, double &T, double &U_r, doubl { VECTOR3 V_a; double A, e, v_a, beta_a, T1, p, eta_ar, eps1, eps2, T2; - int QA, SW; + int SW; + bool QA; //Tolerances eps1 = 1e-3; @@ -6338,11 +6142,11 @@ void ConicRTEEarthNew::VACOMP(double VR_a, double VT_a, double beta_r, double th if (beta_a > PI05) { - k = 1; + k = 0; } else { - k = 0; + k = 1; } pRTCC->PITFPC(mu, k, A, e, r0, T_ap, Period); @@ -6553,11 +6357,11 @@ double ConicRTEEarthNew::TripTime(double v_a, double beta_a) if (beta_a > PI05) { - k = 1; + k = 0; } else { - k = 0; + k = 1; } pRTCC->PITFPC(mu, k, A, e, r0, T_ap, Period); @@ -6572,27 +6376,23 @@ double ConicRTEEarthNew::TripTime(double v_a, double beta_a) RTEMoon::RTEMoon(RTCC *r, EphemerisData2 sv0, double GMTBASE, double alpha_SID0) : RTCCModule(r) { - hMoon = oapiGetObjectByName("Moon"); - hEarth = oapiGetObjectByName("Earth"); - - this->mjd0 = mjd0; this->GMTBASE = GMTBASE; this->alpha_SID0 = alpha_SID0; this->sv0 = sv0; - mu_E = GGRAV*oapiGetMass(hEarth); - mu_M = GGRAV*oapiGetMass(hMoon); - w_E = PI2 / oapiGetPlanetPeriod(hEarth); - R_E = oapiGetSize(hEarth); - R_M = oapiGetSize(hMoon); - - INRFVsign = true; + hMoon = BODY_MOON; + mu_E = OrbMech::mu_Earth; + mu_M = OrbMech::mu_Moon; + w_E = OrbMech::w_Earth; + R_E = OrbMech::R_Earth; + R_M = OrbMech::R_Moon; + r_r = R_E + 400000.0*0.3048; - cMoon = oapiGetCelbodyInterface(hMoon); dTIG = 30.0; precision = 1; ReturnInclination = 0.0; EntryLng = 0.0; + t_Landing = 0.0; } void RTEMoon::READ(int SMODEI, double IRMAXI, double URMAXI, double RRBI, int CIRI, double HMINI, int EPI, double L2DI, double DVMAXI, double MUZI, double IRKI, double MDMAXI, double TZMINI, double TZMAXI) @@ -6654,11 +6454,13 @@ void RTEMoon::ATP(double *line) bool RTEMoon::MASTER() { - OELEMENTS coe; VECTOR3 DVARR, TIGARR; - double i_r, theta_long, theta_lat, dlng, dt, INTER, R_S, dv; + double i_r, theta_long, theta_lat, dlng, dt, INTER, dv, t_z; + double r_0, v_0, delta_0, alpha_0, beta_0, A_0, z_0, e_0; int IPART, ii; - bool ISOL, IOUT; + bool ISOL, IOUT, q_0; + //0 = noncircumlunar, 1 = circumlunar + bool q_m; IOUT = false; IPART = 1; @@ -6666,53 +6468,64 @@ bool RTEMoon::MASTER() while (IOUT == false) { - coe = OrbMech::coe_from_sv(sv0.R, sv0.V, mu_M); - if (coe.e > 0.5) + pRTCC->PICSSC(true, sv0.R, sv0.V, r_0, v_0, delta_0, alpha_0, beta_0, A_0); + beta_0 = PI05 - beta_0; + + q_0 = false; + z_0 = sv0.R.x*sv0.V.y - sv0.R.y*sv0.V.x; + //Is motion prograde? + if (z_0 >= 0) { - if (coe.TA > PI) - { - //Flyby case (pre pericynthion) - INRFVsign = false; - } - else - { - //PC+2 case (post pericynthion) - INRFVsign = true; - } + q_0 = true; } - else + e_0 = sqrt(1.0 - r_0 * v_0*v_0 / mu_M * (2.0 - r_0 * v_0*v_0 / mu_M)*pow(sin(beta_0), 2)); + + if (pRTCC->PLEFEM(4, sv0.GMT / 3600.0, 0, &X_m0, &U_m0, NULL, NULL)) { - //TEI case - INRFVsign = true; + //TBD: Error } //Normally the pseudostate sphere is 24 Earth radii. Probably doesn't iterate very well if the spacecraft is close to that, so use a slightly larger radius then if (length(sv0.R) >= 23.0*R_E) { - R_S = length(sv0.R) + R_E; + r_s = length(sv0.R) + R_E; } else { - R_S = 24.0*R_E; + r_s = 24.0*R_E; } - //QDFLG = 0; + //Direction of motion logic + QDFLG = false; if (bRTCC) { + double EAI; + //Is position on transearth side of earth-moon line? + EAI = sv0.R.x*X_m0.y - sv0.R.y*X_m0.x; + if (EAI >= 0 || q_0) + { + //Yes, only allow non-circumlunar motion + CIRCUM = 1; + } + //Is trajectory elliptical? + else if (e_0 < 1.0) + { + //Yes, only allow retrograde motion with respect to the Moon + CIRCUM = 1; + QDFLG = true; + } } if (CRIT == 4) { - ISOL = CLL(i_r, INTER, dv); + ISOL = CLL(i_r, INTER, q_m, t_z, dv); } else { - ISOL = MCUA(i_r, INTER, dv); + ISOL = MCUA(i_r, INTER, q_m, t_z, dv); } - if (ISOL == false) return false; - if (LETSGO == 1) break; dTIG = SEARCH(IPART, DVARR, TIGARR, sv0.GMT, dv, IOUT); @@ -6721,18 +6534,18 @@ bool RTEMoon::MASTER() { OrbMech::oneclickcoast(sv0.R, sv0.V, GMTBASE + sv0.GMT / 24.0 / 3600.0, dTIG, sv0.R, sv0.V, hMoon, hMoon); sv0.GMT += dTIG; - IPART++; } } + if (ISOL == false) return false; + //Precision Solution - double TIG = OrbMech::MJDfromGET(sv0.GMT, GMTBASE); t_R = t_z; do { - Vig_apo = ThreeBodyAbort(sv0.R, sv0.V, sv0.GMT, t_R, INRFVsign, R_EI, V_EI, i_r, INTER > 0); + Vig_apo = ThreeBodyAbort(sv0.R, sv0.V, sv0.GMT, t_R, q_m, i_r, INTER, R_EI, V_EI); - EntryCalculations::LNDING(R_EI, V_EI, t_R, alpha_SID0, LD, ICRNGG, r_rbias, theta_long, theta_lat, t_z); + EntryCalculations::LNDING(R_EI, V_EI, t_R, alpha_SID0, LD, ICRNGG, r_rbias, theta_long, theta_lat, t_Landing); if (CRIT == 6) break; EntryCalculations::TBLOOK(LINE, theta_lat, EntryLng); @@ -6771,8 +6584,8 @@ bool RTEMoon::MASTER() H_EI_equ = unit(N); ReturnInclination = -acos(H_EI_equ.z)*INTER; - OrbMech::timetoperi_integ(sv0.R, Vig_apo, TIG, hMoon, hMoon, R_peri, V_peri); - FlybyPeriAlt = length(R_peri) - oapiGetSize(hMoon); + OrbMech::timetoperi_integ(sv0.R, Vig_apo, OrbMech::MJDfromGET(sv0.GMT, GMTBASE), pRTCC->GetGravref(hMoon), pRTCC->GetGravref(hMoon), R_peri, V_peri); + FlybyPeriAlt = length(R_peri) - R_M; return true; } @@ -6806,7 +6619,7 @@ void RTEMoon::MCSSLM(bool &REP, double t_z_apo) VECTOR3 UZTAB1, LAMZTAB1, Vig_apo; double DV_maxs, h_mins, t_zmin_apo, Di_r, T_ar, i_r, INTER, i_r_apo, u_r, indvar, r_p, t_z, t_z1_apo, t_z1_aapo, mu_min, mu_max, GMT_L; int KK, XNRMSS, XX, n2, n1; - bool MCSOL, SRFLG, STAYFL, REPP, NIR, IREP, KIP; + bool MCSOL, SRFLG, STAYFL, REPP, NIR, IREP, KIP, q_d; if (MD_max == 0.0) { @@ -6818,7 +6631,7 @@ void RTEMoon::MCSSLM(bool &REP, double t_z_apo) DV_maxs = DV_max; h_mins = h_min; SRFLG = 0; - h_min = -0.3*oapiGetSize(hEarth); + h_min = -0.3*R_E; DV_max = 100.0*20925738.2 / 3600.0; STAYFL = 0; t_zmin_apo = t_zmin; @@ -6853,8 +6666,7 @@ void RTEMoon::MCSSLM(bool &REP, double t_z_apo) { indvar = u_r; } - Vig_apo = MCDRIV(sv0.R, sv0.V, sv0.GMT, indvar, INRFVsign, i_r, INTER, KIP, t_zmin, R_EI, V_EI, t_z, NIR, i_r_apo, r_p); - REP = 1; + REP = MCDRIV(sv0.R, sv0.V, sv0.GMT, indvar, false, i_r, INTER, KIP, t_zmin, Vig_apo, R_EI, V_EI, t_z, NIR, i_r_apo, r_p, q_d); //TBD EntryCalculations::LNDING(R_EI, V_EI, t_z, alpha_SID0, LD, ICRNGG, r_rbias, lambda_z1, mu_z1, GMT_L); //A @@ -6887,8 +6699,7 @@ void RTEMoon::MCSSLM(bool &REP, double t_z_apo) { indvar = u_r; } - Vig_apo = MCDRIV(sv0.R, sv0.V, sv0.GMT, indvar, INRFVsign, i_r, INTER, KIP, t_zmin, R_EI, V_EI, t_z, NIR, i_r_apo, r_p); - REP = 1; + REP = MCDRIV(sv0.R, sv0.V, sv0.GMT, indvar, false, i_r, INTER, KIP, t_zmin, Vig_apo, R_EI, V_EI, t_z, NIR, i_r_apo, r_p, q_d); //TBD EntryCalculations::LNDING(R_EI, V_EI, t_z, alpha_SID0, LD, ICRNGG, r_rbias, lambda_z1, mu_z1, GMT_L); UZTAB1.y = mu_z1; @@ -6899,22 +6710,33 @@ void RTEMoon::MCSSLM(bool &REP, double t_z_apo) } } -bool RTEMoon::CLL(double &i_r, double &INTER, double &dv) +bool RTEMoon::CLL(double &i_r, double &INTER, bool &q_m, double &t_z, double &dv) { VECTOR3 IRTAB, DVTAB, ZTAB, Vig_apo; - double theta_long, theta_lat, dlng, dt, i_r_apo, TOL, i_rmin, DV_min, delta_S, i_rc, h_p, r_p, D1, D2, DVS, DVSS, i_rs, INS, u_r; + double theta_long, theta_lat, dlng, dt, i_r_apo, TOL, i_rmin, DV_min, delta_S, i_rc, h_p, r_p, D1, D2, DVSS, i_rs, INS, u_r; double t_z1, t_z_apo, indvar, eps, GMT_L, h_mins; - int ISUB, KOUNT, ICNT, jj, ICONVG, ii, ITCNT, LOPCNT; - bool NIR, IOPT, NIRS, KIP; + int ISUB, KOUNT, ICNT, jj, ICONVG, ii, ITCNT, LOPCNT, REP; + bool NIR, IOPT, NIRS, KIP, KFLG, q_d; - ii = 0; - jj = 0; + q_m = false; h_mins = h_min; DV_min = pow(10, 10); ZTAB = _V(0, 0, 0); - DVS = pow(10, 10); + KFLG = false; + solution.dv = pow(10, 10); t_z_apo = 0.0; + if (CIRCUM == 0) + { + KFLG = true; + } + else if (CIRCUM == 2) + { + RTEMoon_CLL_1_AA: + q_m = true; + KFLG = false; + } + KIP = 0; u_r = u_rmax; INTER = 1.0; @@ -6940,7 +6762,7 @@ bool RTEMoon::CLL(double &i_r, double &INTER, double &dv) { indvar = u_r; } - Vig_apo = MCDRIV(sv0.R, sv0.V, sv0.GMT, indvar, INRFVsign, i_r, INTER, KIP, t_zmin, R_EI, V_EI, t_z, NIR, i_r_apo, r_p); + REP = MCDRIV(sv0.R, sv0.V, sv0.GMT, indvar, q_m, i_r, INTER, KIP, t_zmin, Vig_apo, R_EI, V_EI, t_z, NIR, i_r_apo, r_p, q_d); h_p = r_p - R_M; EntryCalculations::LNDING(R_EI, V_EI, t_z, alpha_SID0, LD, ICRNGG, r_rbias, theta_long, theta_lat, GMT_L); @@ -6990,7 +6812,7 @@ bool RTEMoon::CLL(double &i_r, double &INTER, double &dv) { indvar = u_r; } - Vig_apo = MCDRIV(sv0.R, sv0.V, sv0.GMT, indvar, INRFVsign, i_r, INTER, KIP, t_zmin, R_EI, V_EI, t_z, NIR, i_r_apo, r_p); + REP = MCDRIV(sv0.R, sv0.V, sv0.GMT, indvar, q_m, i_r, INTER, KIP, t_zmin, Vig_apo, R_EI, V_EI, t_z, NIR, i_r_apo, r_p, q_d); dv = length(Vig_apo - sv0.V); EntryCalculations::LNDING(R_EI, V_EI, t_z, alpha_SID0, LD, ICRNGG, r_rbias, theta_long, theta_lat, GMT_L); LOPCNT = 0; @@ -7001,12 +6823,13 @@ bool RTEMoon::CLL(double &i_r, double &INTER, double &dv) //This checks if the inclination was specified if (eps != 0.05) { - return true; + goto RTEMoon_CLL_17_B; } TOL = 0.01745; ISUB = 0; DVSS = pow(10, 10); + jj = 0; INTER = -1.0; i_r = i_rmax; ICNT = 0; @@ -7019,7 +6842,7 @@ bool RTEMoon::CLL(double &i_r, double &INTER, double &dv) ii = 0; do { - Vig_apo = MCDRIV(sv0.R, sv0.V, sv0.GMT, t_z_apo, INRFVsign, i_r, INTER, true, t_zmin, R_EI, V_EI, t_z, NIR, i_r_apo, r_p); + REP = MCDRIV(sv0.R, sv0.V, sv0.GMT, t_z_apo, q_m, i_r, INTER, true, t_zmin, Vig_apo, R_EI, V_EI, t_z, NIR, i_r_apo, r_p, q_d); EntryCalculations::LNDING(R_EI, V_EI, t_z, alpha_SID0, LD, ICRNGG, r_rbias, theta_long, theta_lat, GMT_L); EntryCalculations::TBLOOK(LINE, theta_lat, EntryLng); @@ -7036,10 +6859,9 @@ bool RTEMoon::CLL(double &i_r, double &INTER, double &dv) h_p = r_p - R_M; dv = length(Vig_apo - sv0.V); - if (INRFVsign == false && h_p < h_min) + if (q_d && h_p < h_min) { - //TBD - //dv_new = pow(10, 10); + dv = pow(10, 10); } if (NIR && IOPT) @@ -7064,7 +6886,7 @@ bool RTEMoon::CLL(double &i_r, double &INTER, double &dv) { INTER = 1.0; i_r = 0.0; - DV_min = pow(10, 10); + DV_min = 1e-8; ICONVG = 0; } else if (jj == 1) @@ -7087,7 +6909,7 @@ bool RTEMoon::CLL(double &i_r, double &INTER, double &dv) if (i_rk == 0) { - if (abs(dv - DV_min) <= 0.1*0.3048) + if (abs(dv - DV_min) <= 0.1772) //0.0001 er/hr { ICONVG++; if (ICONVG != 1) @@ -7131,33 +6953,65 @@ bool RTEMoon::CLL(double &i_r, double &INTER, double &dv) } } + //Restore best solution i_r_apo = i_rs; INTER = INS; i_r = i_r_apo; dv = DVSS; - return true; +RTEMoon_CLL_17_B: + //Store if DV is smaller than stored solution + if (dv < solution.dv) + { + STORE(1, dv, i_r, INTER, t_z, q_m); + } + if (KFLG) + { + //Other direction of motion still to do? + goto RTEMoon_CLL_1_AA; + } + + bool ISOL = false; + + if (solution.dv < DV_max) + { + ISOL = true; + STORE(2, dv, i_r, INTER, t_z, q_m); + } + + return ISOL; } -bool RTEMoon::MCUA(double &i_r, double &INTER, double &dv) +bool RTEMoon::MCUA(double &i_r, double &INTER, bool &q_m, double &t_z, double &dv) { VECTOR3 IRTAB, DVTAB, ZTAB, DVTAB1, IRTAB1, TZTAB1, Vig_apo; double u_r, r_p, di_r, i_rmin, Di_r, Dt_z, TOL, zc, DV_est1, DV_est2, D1, D2, indvar, i_rmax_apo, SDV, Si_r, SSDV, SSi_r, t_z_apo, eps_ir; - double SSt_z, DVSSS, i_rest, i_rmins, i_rmaxs, Xi_r, t_zmin_apo; - int LOOP, LOCATE, ISUB, LOOPTZ, ISUBP, MM; - bool NIR, KIP, IOPT, IEND, IOPT1, IRFLAG, IRSCAN, ISOL; + double SSt_z, DVSSS, i_rest, i_rmins, i_rmaxs, Xi_r, t_zmin_apo, eps_dv; + int LOOP, LOCATE, ISUB, LOOPTZ, ISUBP, REP; + bool NIR, KIP, IOPT, IEND, IOPT1, IRFLAG, IRSCAN, ISOL, q_d; - SDV = SSDV = pow(10, 10); + zc = 0.0; + + solution.dv = pow(10, 10); i_rmax_apo = i_rmax; t_zmin_apo = t_zmin; - - zc = 0.0; + eps_dv = 0.1772; //0.0001 er/hr + if (CIRCUM < 2) + { + q_m = false; + } + else + { + q_m = true; + } +RTEMoon_MCUA_1_A: i_r = 0.0; LOOP = LOOPTZ = 0; di_r = 0.0; u_r = u_rmax; eps_ir = 0.01; DV_est1 = DV_est2 = pow(10, 10); + SDV = SSDV = pow(10, 10); KIP = false; LOCATE = 5; IRSCAN = 0; @@ -7184,8 +7038,15 @@ bool RTEMoon::MCUA(double &i_r, double &INTER, double &dv) { indvar = u_r; } - Vig_apo = MCDRIV(sv0.R, sv0.V, sv0.GMT, indvar, INRFVsign, i_r, INTER, KIP, t_zmin, R_EI, V_EI, t_z, NIR, Xi_r, r_p); - dv = length(Vig_apo - sv0.V); + REP = MCDRIV(sv0.R, sv0.V, sv0.GMT, indvar, q_m, i_r, INTER, KIP, t_zmin, Vig_apo, R_EI, V_EI, t_z, NIR, Xi_r, r_p, q_d); + if (REP == 0) + { + dv = pow(10, 10); + } + else + { + dv = length(Vig_apo - sv0.V); + } i_r = (i_r - di_r)*INTER; if (dv <= SDV) @@ -7244,7 +7105,7 @@ bool RTEMoon::MCUA(double &i_r, double &INTER, double &dv) } } TOL = min(0.017, 0.5*Di_r); - if (LOOP > 20 || abs(i_r) < 0.001 || abs(dv - DV_est1) < 0.1*0.3048 || (ISUB != 0 && dv > DVTAB.data[ISUB - 1])) + if (LOOP > 20 || abs(i_r) < 0.001 || abs(dv - DV_est1) < eps_dv || (ISUB != 0 && dv > DVTAB.data[ISUB - 1])) { break; } @@ -7303,7 +7164,7 @@ bool RTEMoon::MCUA(double &i_r, double &INTER, double &dv) } dv = SDV; i_r = Si_r; - if (LOOPTZ > 20 || (ISUBP != 0 && SDV > DVTAB1.data[ISUBP - 1]) || abs(dv - DV_est2) < 0.1*0.3048) + if (LOOPTZ > 20 || (ISUBP != 0 && SDV > DVTAB1.data[ISUBP - 1]) || abs(dv - DV_est2) < eps_dv) { i_r = SSi_r; t_z_apo = SSt_z; @@ -7330,7 +7191,6 @@ bool RTEMoon::MCUA(double &i_r, double &INTER, double &dv) { D1 = 5.0*TZTAB1.y - 4.0*TZTAB1.x; D2 = 5.0*TZTAB1.y - 4.0*TZTAB1.z; - MM = 1; if (D1 < TZTAB1.z) { t_z_apo = (TZTAB1.y + TZTAB1.z) / 2.0; @@ -7345,7 +7205,7 @@ bool RTEMoon::MCUA(double &i_r, double &INTER, double &dv) i_rmins = i_rmin; i_rmaxs = i_rmax; Di_r = 0.25*i_rmax; - if (Di_r > 0.017453293) + if (Di_r > 0.17453293) { IRSCAN = 1; i_rmin = max(i_rmins, SSi_r); @@ -7374,36 +7234,63 @@ bool RTEMoon::MCUA(double &i_r, double &INTER, double &dv) INTER = 1.0; } i_r = abs(i_r) + di_r; - Vig_apo = MCDRIV(sv0.R, sv0.V, sv0.GMT, t_z_apo, INRFVsign, i_r, INTER, KIP, t_zmin, R_EI, V_EI, t_z, NIR, Xi_r, r_p); + REP = MCDRIV(sv0.R, sv0.V, sv0.GMT, t_z_apo, q_m, i_r, INTER, KIP, t_zmin, Vig_apo, R_EI, V_EI, t_z, NIR, Xi_r, r_p, q_d); dv = length(Vig_apo - sv0.V); LOOP++; + + //Store solution + if (dv < solution.dv) + { + STORE(1, dv, i_r, INTER, t_z, q_m); + } } i_rmax = i_rmax_apo; t_zmin = t_zmin_apo; ISOL = false; - if (SDV <= pow(10, 9)) + + if (CIRCUM == 0 && q_m == false) + { + q_m = true; + goto RTEMoon_MCUA_1_A; + } + + if (solution.dv <= pow(10, 9)) { + //Restore optimum solution + STORE(2, dv, i_r, INTER, t_z, q_m); ISOL = true; } return ISOL; } -VECTOR3 RTEMoon::ThreeBodyAbort(VECTOR3 R_I, VECTOR3 V_I, double t_I, double t_EI, bool INRFVsign, VECTOR3 &R_EI, VECTOR3 &V_EI, double Incl, bool asc) +VECTOR3 RTEMoon::ThreeBodyAbort(VECTOR3 R_I, VECTOR3 V_I, double t_I, double t_EI, bool q_m, double Incl, double INTER, VECTOR3 &R_EI, VECTOR3 &V_EI) { + //INPUT: + //q_m: 0 = noncircumlunar, 1 = circumlunar + //QDFLG: 0 = use circumlunar or noncircumlunar, 1 = use retrograde motion + EphemerisData sv1, sv2; VECTOR3 R_I_star, delta_I_star, delta_I_star_dot, R_I_sstar, V_I_sstar, V_I_star, R_S, R_I_star_apo, R_E_apo, V_E_apo, V_I_apo; - VECTOR3 dV_I_sstar, R_m, V_m, R_s; - double t_S, tol, dt_S, r_s, EntryInterface, RCON, Incl_apo; - int ITS; + VECTOR3 R_m, V_m; + double t_S, tol, dt_S, Incl_apo, r_s, a, e, u_r, beta_r, beta_r_apo, t_z, a_H, e_H, p_H, theta, beta_a, beta_x; + int ITS, INFO; + bool q_m_out, q_d, q_a, NIR; - r_s = 24.0*OrbMech::R_Earth; - EntryInterface = 400000.0 * 0.3048; - RCON = OrbMech::R_Earth + EntryInterface; tol = 20.0; - pRTCC->PLEFEM(1, t_I / 3600.0, 0, &R_m, &V_m, &R_s, NULL); + //Normally the pseudostate sphere is 24 Earth radii. Probably doesn't iterate very well if the spacecraft is close to that, so use a slightly larger radius then + if (length(sv0.R) >= 23.0*R_E) + { + r_s = length(sv0.R) + R_E; + } + else + { + r_s = 24.0*R_E; + } + + pRTCC->PLEFEM(4, t_I / 3600.0, 0, &R_m, &V_m, NULL, NULL); R_I_star = delta_I_star = delta_I_star_dot = _V(0.0, 0.0, 0.0); V_I_star = V_I; @@ -7418,17 +7305,22 @@ VECTOR3 RTEMoon::ThreeBodyAbort(VECTOR3 R_I, VECTOR3 V_I, double t_I, double t_E { R_I_sstar = R_m + R_I_star + delta_I_star; V_I_sstar = V_m + V_I_star + delta_I_star_dot; - if (Incl != 0) - { - EntryCalculations::Abort_plane(R_I_sstar, V_I_sstar, GMTBASE + t_I / 24.0 / 3600.0, RCON, t_EI - t_I, mu_E, Incl, asc ? 1.0 : -1.0, dV_I_sstar, R_EI, V_EI, Incl_apo); - } - else + + beta_r = 96.5*RAD; + + do { - EntryCalculations::Abort(R_I_sstar, V_I_sstar, RCON, t_EI - t_I, mu_E, dV_I_sstar, R_EI, V_EI); - } - V_I_sstar = V_I_sstar + dV_I_sstar; + EntryCalculations::AESR(r_r, length(R_I_sstar), PI - beta_r, t_EI - t_I, R_E, mu_E, 0.001, a, e, q_a, INFO, u_r); + NIR = FINDUX(R_I_sstar, t_I, r_r, u_r, beta_r, Incl, INTER, q_a, mu_E, V_I_sstar, R_EI, V_EI, t_z, Incl_apo); + + beta_r_apo = beta_r; + beta_r = EntryCalculations::ReentryTargetLine(u_r, ICRNGG == 1); + + } while (abs(beta_r - beta_r_apo) > 0.0002); + V_I_star = V_I_sstar - V_m - delta_I_star_dot; - OrbMech::INRFV(R_I, V_I_star, r_s, INRFVsign, mu_M, V_I_apo, R_S, dt_S); + + INRFV(R_I, V_I_star, r_s, mu_M, q_m, a_H, e_H, p_H, theta, V_I_apo, R_S, dt_S, q_m_out, q_d, beta_a, beta_x); t_S = t_I + dt_S; R_I_star_apo = R_I_star; R_I_star = R_S + V_I_star * (t_I - t_S); @@ -7453,74 +7345,240 @@ VECTOR3 RTEMoon::ThreeBodyAbort(VECTOR3 R_I, VECTOR3 V_I, double t_I, double t_E return V_I_apo; } -VECTOR3 RTEMoon::MCDRIV(VECTOR3 R_I, VECTOR3 V_I, double t_I, double var, bool INRFVsign, double Incl, double INTER, bool KIP, double t_zmin, VECTOR3 &R_EI, VECTOR3 &V_EI, double &T_EI, bool &NIR, double &Incl_apo, double &r_p) +int RTEMoon::MCDRIV(VECTOR3 Y_0, VECTOR3 V_0, double t_0, double var, bool q_m, double Incl, double INTER, bool KIP, double t_zmin, VECTOR3 &V_a, VECTOR3 &R_EI, VECTOR3 &V_EI, double &T_EI, bool &NIR, double &Incl_apo, double &y_p, bool &q_d) { - OELEMENTS coe; - VECTOR3 R_I_star, R_I_sstar, V_I_sstar, V_I_star, R_S, R_I_star_apo, V_I_apo; - VECTOR3 dV_I_sstar, R_m, V_m, R_s; - double t_S, tol, dt_S, r_s, EntryInterface, RCON, p_h, beta_r, u_r; - - r_s = 24.0*oapiGetSize(hEarth); - EntryInterface = 400000.0 * 0.3048; - RCON = oapiGetSize(hEarth) + EntryInterface; - tol = 20.0; + //INPUT: + //Y_0: Selenocentric preabort position vector + //V_0: Selenocentric preabort velocity vector + //t_0: Preabort time + //var: either reentry velocity (KIP=false) or landing time (KIP=true) + //q_m: 0 = noncircumlunar motion postabort, 1 = circumlunar motion postabort + //Incl: Return inclination + //INTER: -1 = A_zr < reentry azimuth for i_r = delta_x, +1 = A_zr > reentry azimuth for i_r = delta_x + //KIP: 0 = reentry velocity is the independent variable, 1 = landing time is the independent variable + //t_zmin: minimum landing time allowed + //OUTPUT: + //REP: 0 = no MCDRIV solution has been found, >0 = a solution has been found in MCDRIV + //V_a: Postabort velocity vector + + //Geocentric transearth pseudostate position vector + VECTOR3 X_x; + //Geocentric transearth pseudostate velocity vector + VECTOR3 U_x; + //Selenocentric position vector at PTS exit + VECTOR3 Y_x; + //Previous value of selenocentric PTS exit position + VECTOR3 Y_x_apo; + //Selenocentric velocity vector at PTS exit + VECTOR3 V_x; + //Previous value of selenocentric PTS exit velocity + VECTOR3 V_x_apo; + //Geocentric position vector of the moon at the postpericynthion pseudostate transformation time + VECTOR3 X_mx; + //Geocentric velocity vector of the moon at the postpericynthion pseudostate transformation time + VECTOR3 U_mx; + //Fictitious abort position vector + VECTOR3 Y_a_apo; + //Selenocentric orbital parameters + double a_h, e_h, p_h; + + double tol, beta_r, u_r, a, e, beta_r_apo, dy_x, dy_x_apo, v_m, T_EI_apo, T_a, P, T_x, t_x, theta, dt_S, beta_a, beta_x, delta_t, Dy_0, t_x_apo; + int INFO, KOUNT, k_x; + bool q_m_out, q_a, dy_xf; + + tol = 63.78165; + q_a = false; if (KIP) { - T_EI = var; + T_EI_apo = var; + u_r = EntryCalculations::URF((T_EI_apo - t_0) / 3600.0, length(X_m0) / 6378165.0)*6378165.0 / 3600.0; } else { u_r = var; - beta_r = EntryCalculations::ReentryTargetLine(u_r, false); } - pRTCC->PLEFEM(1, t_I/3600.0, 0, &R_m, &V_m, &R_s, NULL); + beta_r = EntryCalculations::ReentryTargetLine(u_r, ICRNGG == 1); + +RTEMoon_MCDRIV_1_X: + //Initialize iteration counters + k_x = 1; + KOUNT = 0; + //Initial guess for pseudostate. Position at the center of the Moon, velocity using preabort value + t_x = t_0; + X_mx = X_m0; + U_mx = U_m0; + Y_a_apo = Y_0; + X_x = X_mx; + Y_x = X_x - X_mx; + V_x = V_0; //TBD, not necessary +RTEMoon_MCDRIV_5_S: + //Main loop + if (KIP) + { + //Compute velocity at reentry, if it is not input + EntryCalculations::AESR(r_r, length(X_x), PI - beta_r, T_EI_apo - t_x, R_E, mu_E, 0.001, a, e, q_a, INFO, u_r); + } + + //Compute the geocentric conic (velocity vector) from the geocentric pseudostate + NIR = FINDUX(X_x, t_x, r_r, u_r, beta_r, Incl, INTER, q_a, mu_E, U_x, R_EI, V_EI, T_EI, Incl_apo); + //Save current value of beta_r + beta_r_apo = beta_r; + //Reset convergence flag + dy_xf = false; + //Save previous value of V_x + V_x_apo = V_x; + //Transform the abort velocity vector to selenocentric reference + V_x = U_x - U_mx; +RTEMoon_MCDRIV_7_R: + //Given initial position Y_a_apo and velocity at PTS V_x, calculate initial velocity V_a and position at PTS Y_x_apo + INRFV(Y_a_apo, V_x, r_s, mu_M, q_m, a_h, e_h, p_h, theta, V_a, Y_x_apo, dt_S, q_m_out, q_d, beta_a, beta_x); - for (int i = 0;i < 2;i++) + //Near parabolic orbit? + if (abs(e_h - 1.0) < 1e-5) + { + a_h = p_h; + } + //Calculate time from pericynthion to PTS + pRTCC->PITFPC(mu_M, 0, a_h, e_h, r_s, T_x, P, false); + //Calculate pericynthion radius + y_p = p_h / (1.0 + e_h); + //Near pericynthion + if (length(Y_a_apo) < y_p + 1e-6*R_E) { - R_I_star = _V(0.0, 0.0, 0.0); - V_I_star = V_I; + //Assume time to pericynthion is zero + T_a = 0.0; + } + else + { + //Calculate time from pericynthion to abort + pRTCC->PITFPC(mu_M, q_d, a_h, e_h, length(Y_a_apo), T_a, P, false); + } - do + //Update pseudstate + PSTATE(a_h, e_h, p_h, t_0, T_x, Y_0, Y_a_apo, V_x, theta, beta_a, beta_x, T_a, V_a, t_x_apo, Y_x_apo, Dy_0, delta_t, X_mx, U_mx); + // + dy_x = length(Y_x - Y_x_apo); + + if (dy_xf == false) + { + //Has converged? + if (dy_x <= tol && Dy_0 / length(Y_0) <= tol / 63781650.0 && abs(t_x_apo - t_x) < 0.1) { - R_I_sstar = R_m + R_I_star; - V_I_sstar = V_m + V_I_star; - if (KIP) - { - NIR = EntryCalculations::Abort_plane(R_I_sstar, V_I_sstar, GMTBASE + t_I / 24.0 / 3600.0, RCON, T_EI - t_I, mu_E, Incl, INTER, dV_I_sstar, R_EI, V_EI, Incl_apo); - } - else + //Does solution violate minimum landing time constraint? + if (KIP == 0 && T_EI < t_zmin) { - double MJD_EI; - NIR = FINDUX(R_I_sstar, V_I_sstar, GMTBASE + t_I / 24.0 / 3600.0, RCON, u_r, beta_r, Incl, INTER, false, mu_E, dV_I_sstar, R_EI, V_EI, MJD_EI, Incl_apo); - T_EI = (MJD_EI - GMTBASE)*24.0*3600.0; + KIP = 1; + T_EI_apo = t_zmin; + goto RTEMoon_MCDRIV_1_X; } - V_I_sstar = V_I_sstar + dV_I_sstar; - V_I_star = V_I_sstar - V_m; - OrbMech::INRFV(R_I, V_I_star, r_s, INRFVsign, mu_M, V_I_apo, R_S, dt_S); - t_S = t_I + dt_S; - R_I_star_apo = R_I_star; - R_I_star = R_S + V_I_star * (t_I - t_S); + //Solution has converged + goto RTEMoon_MCDRIV_11_W; + } + } + k_x++; + if (k_x >= k_max) + { + //Error return + return 0; + } - } while (length(R_I_star - R_I_star_apo) > tol); + //Are conics diverging? + if (k_x % 3 == 0 && (dy_x_apo < 1.15*dy_x && dy_x >= tol)) + { + //Average exit velocity vector + v_m = (length(V_x) + length(V_x_apo)) / 2.0; + dy_x_apo = 200.0*6378165.0; + dy_xf = true; + V_x = (V_x + V_x_apo) / 2.0; + V_x = unit(V_x)*v_m; + goto RTEMoon_MCDRIV_7_R; + } + else + { + t_x = t_x_apo; + Y_x = Y_x_apo; + X_x = Y_x + X_mx; + dy_x_apo = dy_x; + goto RTEMoon_MCDRIV_5_S; + } - if (KIP == 0 && T_EI < t_zmin) - { - KIP = 1; - T_EI = t_zmin; - } - else +RTEMoon_MCDRIV_11_W: + //Solution has converged, check if reentry flight-path angle needs to be adjusted + if (KOUNT <= 4) + { + beta_r = EntryCalculations::ReentryTargetLine(u_r, ICRNGG == 1); + KOUNT++; + if (abs(beta_r - beta_r_apo) >= 0.0002) { - break; - } + KOUNT++; + k_x = 1; + goto RTEMoon_MCDRIV_5_S; + } + } + + //Verification + /*char Buffer[128]; + VECTOR3 rr_S, v_S, v_I_star, r_I_star, R_I_star, V_I_star, R_EI2, V_EI2; + double dt; + + if (T_a < -3600.0) + { + double t_I, t_N; + + //Conic propagation to sphere entry point + dt = OrbMech::time_radius(Y_0, -V_a, r_s, 1.0, mu_M); + dt = -dt; + t_N = t_0 + dt; + OrbMech::rv_from_r0v0(Y_0, V_a, dt, rr_S, v_S, mu_M); + //Linear propagation to original time + v_I_star = v_S; + r_I_star = rr_S + v_S * (t_0 - t_N); + //Convert to geocentric pseudostate + R_I_star = X_m0 + r_I_star; + V_I_star = U_m0 + v_I_star; + //Estimate perilune time + dt = OrbMech::timetoperi(Y_0, V_a, mu_M); + t_I = t_0 + dt; + //Propagate geocentric pseudostate to perilune time + OrbMech::rv_from_r0v0(R_I_star, V_I_star, dt, R_I_star, V_I_star, mu_E); + //Get Moon state vector at new time + pRTCC->PLEFEM(4, t_I / 3600.0, 0, &X_mx, &U_mx, NULL, NULL); + //Convert to selenocentric pseudostate + r_I_star = R_I_star - X_mx; + v_I_star = V_I_star - U_mx; + //Linear propagation to sphere entrance + dt = (-dotp(r_I_star, v_I_star) - sqrt(pow(dotp(r_I_star, v_I_star), 2) + dotp(v_I_star, v_I_star) * (pow(r_s, 2) - dotp(r_I_star, r_I_star)))) / dotp(v_I_star, v_I_star); + t_N = t_I + dt; + rr_S = r_I_star + v_I_star * dt; + v_S = v_I_star; + //Conic propagation to specified time. Real perilune state + OrbMech::rv_from_r0v0(rr_S, v_S, t_I - t_N, rr_S, v_S, mu_M); + + //Then same as post-pericynthion + dt = OrbMech::time_radius(rr_S, v_S, r_s, 1.0, mu_M); + OrbMech::rv_from_r0v0(rr_S, v_S, dt, rr_S, v_S, mu_M); + v_I_star = v_S; + r_I_star = rr_S - v_S * dt; + R_I_star = X_mx + r_I_star; + V_I_star = U_mx + v_I_star; + OrbMech::rv_from_r0v0(R_I_star, V_I_star, T_EI - t_I, R_EI2, V_EI2, mu_E); } + else + { + dt = OrbMech::time_radius(Y_0, V_a, r_s, 1.0, mu_M); + OrbMech::rv_from_r0v0(Y_0, V_a, dt, rr_S, v_S, mu_M); + v_I_star = v_S; + r_I_star = rr_S - v_S * dt; + R_I_star = X_m0 + r_I_star; + V_I_star = U_m0 + v_I_star; + OrbMech::rv_from_r0v0(R_I_star, V_I_star, T_EI - t_0, R_EI2, V_EI2, mu_E); + } + sprintf(Buffer, "MCDRIV Debug: Error %lf T_a %lf", length(R_EI - R_EI2), T_a); + oapiWriteLog(Buffer);*/ - coe = OrbMech::coe_from_sv(R_I, V_I_apo, mu_M); - p_h = coe.h*coe.h / mu_M; - r_p = p_h / (1.0 + coe.e); - - return V_I_apo; + return 1; } double RTEMoon::SEARCH(int &IPART, VECTOR3 &DVARR, VECTOR3 &TIGARR, double tig, double dv, bool &IOUT) @@ -7529,8 +7587,8 @@ double RTEMoon::SEARCH(int &IPART, VECTOR3 &DVARR, VECTOR3 &TIGARR, double tig, if (IPART == 1) { - DVARR = _V(1.0, 1.0, 1.0)*pow(10, 10); - TIGARR = _V(1.0, 1.0, 1.0)*pow(10, 10); + DVARR = _V(1e10, 1e10, 1e10); + TIGARR = _V(1e10, 1e10, 1e10); IPART = 2; } @@ -7542,7 +7600,7 @@ double RTEMoon::SEARCH(int &IPART, VECTOR3 &DVARR, VECTOR3 &TIGARR, double tig, TIGARR.z = tig; DVTEST = DVARR.z - DVARR.y; dt = (TIGARR.z - TIGARR.y); - if (abs(dt) < 1.0 || abs(DVTEST) < 0.2*0.3048) + if (IPART == 4 && (abs(dt) < 1.0 || abs(DVTEST) < 0.2*0.3048)) { IOUT = true; } @@ -7555,31 +7613,48 @@ double RTEMoon::SEARCH(int &IPART, VECTOR3 &DVARR, VECTOR3 &TIGARR, double tig, IPART = 3; return 120.0; } - else if (DVTEST < 0) + else if (DVTEST <= 0) { + //Most recent DV smaller than the previous one, continue in this direction return dt; } else { + //DV increasing again, we went past a minimum + IPART = 4; return -dt / 2.0; } } -bool RTEMoon::FINDUX(VECTOR3 R0, VECTOR3 V0, double MJD0, double r_r, double u_r, double beta_r, double i_r, double INTER, bool q_a, double mu, VECTOR3 &DV, VECTOR3 &R_EI, VECTOR3 &V_EI, double &MJD_EI, double &Incl_apo) +bool RTEMoon::FINDUX(VECTOR3 X_x, double t_x, double r_r, double u_r, double beta_r, double i_r, double INTER, bool q_a, double mu, VECTOR3 &U_x, VECTOR3 &R_EI, VECTOR3 &V_EI, double &T_EI, double &Incl_apo) const { - VECTOR3 X_x_equ_u, R_1, u_x_equ, U_x_equ, U_x; - double x_x, E, e, a, eta_r, eta_x, eta_xr, T_r, T_x, P, beta_x, alpha_x, delta_x, sin_delta_r, cos_delta_r, theta, alpha_r, eta_x1, t_z, T_xr; + //INPUTS: + //X_x: Earth-centered position vector at exit from moon's sphere of action (MSA) + //t_x: Time of MSA exit from base time + //r_r: Reentry radius + //beta_r: Reentry flight path angle + //i_r: Return inclination + //INTER: Indicator for which of the two possible orbital planes for a given i_r is specified + //q_a: Apogee passage flag + + //OUTPUT: + //U_x: Velocity vector at MSA exit + //t_z: Time of landing from base time + + VECTOR3 X_x_u, R_1, U_x_u; + double x_x, E, e, a, eta_r, eta_x, eta_xr, T_r, T_x, P, beta_x, alpha_x, delta_x, sin_delta_r, cos_delta_r, theta, alpha_r, eta_x1, t_z, T_xr, T_rz; bool NIR; Incl_apo = i_r; NIR = false; + T_rz = 0.0; //TBD: for now... - x_x = length(R0); - X_x_equ_u = unit(R0); - OrbMech::ra_and_dec_from_r(X_x_equ_u, alpha_x, delta_x); + x_x = length(X_x); + X_x_u = unit(X_x); + OrbMech::ra_and_dec_from_r(X_x_u, alpha_x, delta_x); E = u_r * u_r / mu - 2.0 / r_r; - if (abs(E) < pow(10, -10)) + if (abs(E) < 1e-3 / 6378165.0) { e = 1.0; } @@ -7588,10 +7663,10 @@ bool RTEMoon::FINDUX(VECTOR3 R0, VECTOR3 V0, double MJD0, double r_r, double u_r a = -1.0 / E; e = sqrt(1.0 - r_r * r_r*u_r*u_r*sin(beta_r)*sin(beta_r) / (mu*a)); } - if (abs(e - 1.0) < pow(10, -5)) + if (abs(e - 1.0) < 1e-5) { - a = r_r * u_r*u_r*sin(beta_r)*sin(beta_r) / mu; - eta_r = PI2 * acos(a / r_r - 1.0); + a = pow(r_r, 2) * pow(u_r, 2)*pow(sin(beta_r), 2) / mu; + eta_r = PI2 - acos(a / r_r - 1.0); eta_x = acos(a / x_x - 1.0); } else @@ -7608,14 +7683,14 @@ bool RTEMoon::FINDUX(VECTOR3 R0, VECTOR3 V0, double MJD0, double r_r, double u_r pRTCC->PITFPC(mu, 0, a, e, x_x, T_x, P, false); if (q_a == 0 || (q_a == 1 && E >= 0)) { - t_z = T_x - T_r; + t_z = t_x + T_x - T_r + T_rz; } else { - t_z = P - T_x - T_r; + t_z = t_x + P - T_x - T_r + T_rz; } - T_xr = -t_z; - MJD_EI = MJD0 + T_xr / 24.0 / 3600.0; + T_xr = t_z - t_x - T_rz; + T_EI = t_x + T_xr; beta_x = atan2(1.0 + e * cos(eta_x), e*sin(eta_x)); if (Incl_apo <= abs(delta_x)) @@ -7639,11 +7714,254 @@ bool RTEMoon::FINDUX(VECTOR3 R0, VECTOR3 V0, double MJD0, double r_r, double u_r alpha_r = alpha_x + theta; R_1 = _V(cos(alpha_r)*cos_delta_r, sin(alpha_r)*cos_delta_r, sin_delta_r); eta_x1 = eta_xr; - u_x_equ = EntryCalculations::TVECT(X_x_equ_u, R_1, eta_x1, beta_x); - U_x_equ = u_x_equ * sqrt(u_r*u_r - 2.0*mu*(1.0 / r_r - 1.0 / x_x)); - U_x = U_x_equ; - OrbMech::rv_from_r0v0(R0, U_x, T_xr, R_EI, V_EI, mu); - DV = U_x - V0; + U_x_u = EntryCalculations::TVECT(X_x_u, R_1, eta_x1, beta_x); + U_x = U_x_u * sqrt(u_r*u_r - 2.0*mu*(1.0 / r_r - 1.0 / x_x)); + + OrbMech::rv_from_r0v0(X_x, U_x, T_xr, R_EI, V_EI, mu); return NIR; +} + +void RTEMoon::INRFV(VECTOR3 R_1, VECTOR3 V_2, double r_2, double mu, bool k3, double &a, double &e, double &p, double &theta, VECTOR3 &V_1, VECTOR3 &R_2, double &dt_2, bool &q_m, bool &k_1, double &beta_1, double &beta_2) const +{ + //INPUTS: + //R_1: Initial positon vector + //V_2: Velocity vector at the second position + //r_2: magnitude of the second position vector + //mu: gravitational constant + //k3: 0 = noncircumlunar or retrograde motion as specified by QDFLG, 1 = circumlunar motion + //QDFLG: 0 = use circumlunar or noncircumlunar motion, 1 = use retrograde motion + + //OUTPUTS: + //I: counts the roots from the quartic tested, error flag if I > 5 + //q_m: 0 = noncircumlunar, 1 = circumlunar + //k_1: 0 = no pericenter passage, 1 = pericenter passage + + VECTOR3 r_1_cf, v_2_cf, c; + double psi, cos_psi, sin_psi, A, B, C, r_1, v_2, sin_beta_2, v_1, f, g, DIFG; + double AA[5], RR[4]; + int N; + + DIFG = 1.0; + r_1 = length(R_1); + v_2 = length(V_2); + + if (QDFLG) + { + DIFG = -1.0; + } + + psi = EntryCalculations::XDOTX2(unit(R_1), unit(V_2), DIFG); + + if (QDFLG) + { + if (psi < PI) + { + q_m = false; + } + else + { + q_m = true; + } + } + else + { + q_m = k3; + if (psi < PI || !k3) + { + if (psi >= PI || k3) + { + psi = PI2 - psi; + } + } + } + + r_1 = length(R_1); + v_2 = length(V_2); + r_1_cf = unit(R_1); + v_2_cf = unit(V_2); + + cos_psi = cos(psi); + sin_psi = sin(psi); + + A = r_2 * r_2*v_2*v_2 / mu / r_1; + B = (1.0 - r_2 * v_2*v_2 / mu)*sin_psi; + C = cos_psi * cos_psi; + + //solve quartic + AA[0] = A * A; + AA[1] = 2.0*A*B; + AA[2] = B * B + C - 2.0*A; + AA[3] = -2.0*B; + AA[4] = 1.0 - C; + + OrbMech::SolveQuartic(AA, RR, N); + + if (cos_psi > 0) + { + sin_beta_2 = RR[N - 2]; + } + else + { + sin_beta_2 = RR[N - 1]; + } + + beta_2 = asin(sin_beta_2); + c = unit(crossp(r_1_cf, v_2_cf) / sin_psi); + theta = psi - beta_2; + R_2 = (r_1_cf*cos(theta) + crossp(c, r_1_cf)*sin(theta))*r_2; + v_1 = sqrt(v_2 - 2.0*mu / r_2 + 2.0*mu / r_1); + p = r_2 * r_2*v_2*v_2*sin_beta_2*sin_beta_2 / mu; + f = 1.0 - r_2 * (1.0 - cos(theta)) / p; + g = r_2 * r_1*sin(theta) / sqrt(mu*p); + V_1 = (R_2 - R_1 * f) / g; + a = 1.0 / (2.0 / r_2 - v_2 * v_2 / mu); + e = sqrt(1.0 - p / a); + + dt_2 = OrbMech::time_theta(R_1, V_1, theta, mu); + //VECTOR3 R2_apo, V2_apo; + //OrbMech::rv_from_r0v0(R_1, V_1, dt_2, R2_apo, V2_apo, mu); + + //Determine pericenter passage + //r_1 near pericenter? + if (r_1 < p / (1.0 + e) + 1e-6*R_E) + { + //Close to periapsis solution + e = p / r_1 - 1.0; + beta_1 = PI05; + k_1 = true; + } + else + { + //Not close to periapsis + beta_1 = EntryCalculations::XDOTX2(R_1, V_1, 0.0); + if (beta_1 > PI05) + { + k_1 = true; + } + else + { + k_1 = false; + } + } +} + +void RTEMoon::STORE(int opt, double &dv, double &i_r, double &INTER, double &t_z, bool &q_m) +{ + //1 = store, 2 = restore + if (opt == 1) + { + solution.dv = dv; + solution.i_r = i_r; + solution.INTER = INTER; + solution.q_m = q_m; + solution.t_z = t_z; + } + else + { + dv = solution.dv; + i_r = solution.i_r; + INTER = solution.INTER; + q_m = solution.q_m; + t_z = solution.t_z; + } +} + +void RTEMoon::PSTATE(double a_H, double e_H, double p_H, double t_0, double T_x, VECTOR3 Y_0, VECTOR3 &Y_a_apo, VECTOR3 V_x, double theta, double beta_a, double beta_x, double T_a, VECTOR3 &V_a, double &t_x_aaapo, VECTOR3 &Y_x_apo, double &Dy_0, double &deltat, VECTOR3 &X_mx, VECTOR3 &U_mx) const +{ + //INPUTS: + //a_h: semimajor axis of selenocentric conic + //e_H: eccentricity of selenocentric conic + //p_H: semilatus rectum of selenocentric conic + //t_0: time of abort + //T_x: flight time from pericynthion to PTS exit + //Y_0: Selenocentric preabort position vector + //Y_a_apo: Fictitious abort position vector used in last call to INRFV + //V_x: Selenocentric PTS exit velocity vector + //theta: transfer angle from Y_a_apo to Y_x_apo + //beta_a: postabort flight-path angle + //beta_x: PTS exit flight-path angle of selenocentric conic + //T_a: flight time from pericynthion to the maneuver position + //V_a: Selenocentric postabort velocity vector + //Y_x_apo: Selenocentric PTS exit position vector + //OUTPUTS: + //V_a: Corrected postabort velocity vector + //t_x_aaapo: Postpericynthion pseudostate transformation time for next iteration + //Y_x_apo: Selenocentric PTS exit position vector for next iteration + //Dy_0: Magnitude of the abort position mismatch + + if (T_a < -3600.0) + { + t_x_aaapo = t_0 - T_a; + deltat = T_x; + + bool IERR = pRTCC->PLEFEM(4, t_x_aaapo / 3600.0, 0, &X_mx, &U_mx, NULL, NULL); + if (IERR) + { + //Error + return; + } + + VECTOR3 Y_u, V_u, Y_n_u, V_n_u, Y_n, V_n, U_p_n, X_p_n, X_a_n, U_a_n, Y, V, Y_a, DY_0; + double t_n, f_a, f_x, gamma_p, gamma_v, A, B, C, Deltat; + + t_n = t_x_aaapo - T_x; + f_a = T_a / abs(T_a)*acos((p_H / length(Y_a_apo) - 1.0) / e_H); //Error in RTCC document + f_x = theta + f_a; + Y_u = unit(Y_a_apo); + V_u = unit(V_a); + + gamma_p = beta_a + f_x + f_a; + gamma_v = gamma_p + beta_x - PI; + + Y_n_u = EntryCalculations::TVECT(V_u, Y_u, beta_a, gamma_p); + V_n_u = EntryCalculations::TVECT(V_u, Y_u, beta_a, gamma_v); + + //Pseudostate vector at PTS entry + Y_n = Y_n_u * r_s; + V_n = V_n_u * length(V_x); + + //Linear projection to pericynthion, then convert to geocentric pseudostate + U_p_n = V_n + U_mx; + X_p_n = Y_n + V_n * T_x + X_mx; + + //Propagate geocentric pseudostate from t_x_aaapo to t_0. X_a_n and U_a_n are geocentric pseudostate at time t_0 + Deltat = t_x_aaapo - t_0; + OrbMech::rv_from_r0v0(X_p_n, -U_p_n, Deltat, X_a_n, U_a_n, mu_E); + U_a_n = -U_a_n; + + //Convert to selenocentric pseudostate at time t_0 + Y = X_a_n - X_m0; + V = U_a_n - U_m0; + + //Calculate linear from time from t_0 to PTS entry point + A = dotp(V, V); + B = dotp(V, Y); + C = r_s * r_s - dotp(Y, Y); + + Deltat = (-B - sqrt(B*B + A * C)) / A; + + //Calculate sphere entrance state vector + t_n = t_0 + Deltat; + V_n = V; + Y_n = Y + V * Deltat; + + //Propagate to t_0. New postabort state vector + OrbMech::rv_from_r0v0(Y_n, V_n, -Deltat, Y_a, V_a, mu_M); + + DY_0 = Y_0 - Y_a; + Y_a_apo = Y_a_apo + DY_0; + Dy_0 = length(DY_0); + } + else + { + Dy_0 = 0.0; + t_x_aaapo = t_0; + deltat = T_x - T_a; + U_mx = U_m0; + X_mx = X_m0; + Y_a_apo = Y_0; + } + + Y_x_apo = Y_x_apo - V_x * deltat; } \ No newline at end of file diff --git a/Orbitersdk/samples/ProjectApollo/src_rtccmfd/EntryCalculations.h b/Orbitersdk/samples/ProjectApollo/src_rtccmfd/EntryCalculations.h index de51161c25..348f0ab9d8 100644 --- a/Orbitersdk/samples/ProjectApollo/src_rtccmfd/EntryCalculations.h +++ b/Orbitersdk/samples/ProjectApollo/src_rtccmfd/EntryCalculations.h @@ -54,10 +54,8 @@ namespace EntryCalculations void augekugel(double ve, double gammae, double &phie, double &Te); void landingsite(MATRIX3 Rot_J_B, VECTOR3 REI, VECTOR3 VEI, double MJD_EI, double &lambda, double &phi); void Reentry(MATRIX3 Rot_J_B, VECTOR3 REI, VECTOR3 VEI, double mjd0, bool highspeed, double &EntryLatPred, double &EntryLngPred, double &EntryRTGO, double &EntryVIO, double &EntryRET); - void Abort(VECTOR3 R0, VECTOR3 V0, double RCON, double dt, double mu, VECTOR3 &DV, VECTOR3 &R_EI, VECTOR3 &V_EI); - bool Abort_plane(VECTOR3 R0, VECTOR3 V0, double MJD0, double RCON, double dt, double mu, double Incl, double INTER, VECTOR3 &DV, VECTOR3 &R_EI, VECTOR3 &V_EI, double &Incl_apo); - void time_reentry(VECTOR3 R0, VECTOR3 V0, double r1, double x2, double dt, double mu, VECTOR3 &V, VECTOR3 &R_EI, VECTOR3 &V_EI); - void time_reentry_plane(VECTOR3 R0, VECTOR3 eta, double r1, double x2, double dt, double mu, VECTOR3 &V, VECTOR3 &R_EI, VECTOR3 &V_EI); + double XDOTX2(VECTOR3 a, VECTOR3 b, double DIFG); + void RA2XYZ4(VECTOR3 R, VECTOR3 V, double &beta, double &A_Z); double landingzonelong(int zone, double lat); //Actual RTE processor routines @@ -66,7 +64,7 @@ namespace EntryCalculations void EGTR(VECTOR3 R_geoc, VECTOR3 V_geoc, double GMT, double alpha_SID0, VECTOR3 &R_geogr, VECTOR3 &V_geogr); double INTER(const double *X, const double *Y, int IMAX, double x); double URF(double T, double x); - void AESR(double r1, double r2, double beta1, double T, double R, double mu, double eps, double &a, double &e, int &k2, int &info, double &V1); + void AESR(double r1, double r2, double beta1, double T, double R, double mu, double eps, double &a, double &e, bool &k2, int &info, double &V1); int MINMIZ(VECTOR3 &X, VECTOR3 &Y, VECTOR3 &Z, bool opt, VECTOR3 CUR, double TOL, double &XMIN, double &YMIN); double LNDING(VECTOR3 REI, VECTOR3 VEI, double GMT_EI, double alpha_SIDO0, double LD, int ICRNGG, double r_rbias, double &lambda, double &phi, double &GMT_L); void SIDCOM(double JD0, double DT, double N, double &alpha_go, double &T); @@ -419,7 +417,7 @@ class ConicRTEEarthNew : public RTCCModule void FCUA(int FLAG, VECTOR3 R_a, double &beta_r, double &DV, double &U_r, double &V_a, double &beta_a); void MSDS(double VR_a, double VT_a, double beta_r, double theta, double &delta, double &phi, double &phi_z, double &lambda, double &theta_z); bool RUBR(int QA, int QE, double R_a, double U_0, double U_r, double beta_r, double &A, double &DV, double &e, double &T, double &V_a, double &beta_a); - void VELCOM(double T, double R_a, double &beta_r, double &dt, double &p, int &QA, int &sw6, double &U_r, double &VR_a, double &VT_a, double &beta_a, double &eta_ar, double &DV); + void VELCOM(double T, double R_a, double &beta_r, double &dt, double &p, bool &QA, int &sw6, double &U_r, double &VR_a, double &VT_a, double &beta_a, double &eta_ar, double &DV); void VARMIN(); void TCOMP(double dv, double delta, double &T, double &TP); void TMIN(double &dv, int &FLAG, double &T, double &U_r, double &VT_a, double &VR_a, double &beta_r); @@ -560,6 +558,15 @@ class ConicRTEEarthNew : public RTCCModule VECTOR3 RR_vec, VV_vec; }; +struct RTEMoonStoredSolution +{ + double dv; + double i_r; + double INTER; + bool q_m; + double t_z; +}; + class RTEMoon : public RTCCModule { public: @@ -567,9 +574,6 @@ class RTEMoon : public RTCCModule void ATP(double *line); void READ(int SMODEI, double IRMAXI, double URMAXI, double RRBI, int CIRI, double HMINI, int EPI, double L2DI, double DVMAXI, double MUZI, double IRKI, double MDMAXI, double TZMINI, double TZMAXI); bool MASTER(); - void MCSS(); - bool CLL(double &i_r, double &INTER, double &dv); - bool MCUA(double &i_r, double &INTER, double &dv); void MCSSLM(bool &REP, double t_z_apo); @@ -581,23 +585,28 @@ class RTEMoon : public RTCCModule VECTOR3 Vig_apo; double ReturnInclination; double FlybyPeriAlt; - double t_R, t_z; + double t_R, t_Landing; EphemerisData2 sv0; private: - VECTOR3 ThreeBodyAbort(VECTOR3 R_I, VECTOR3 V_I, double t_I, double t_EI, bool INRFVsign, VECTOR3 &R_EI, VECTOR3 &V_EI, double Incl = 0, bool asc = true); - VECTOR3 MCDRIV(VECTOR3 R_I, VECTOR3 V_I, double t_I, double var, bool INRFVsign, double Incl, double INTER, bool KIP, double t_zmin, VECTOR3 &R_EI, VECTOR3 &V_EI, double &T_EI, bool &NIR, double &Incl_apo, double &r_p); + void MCSS(); + bool CLL(double &i_r, double &INTER, bool &q_m, double &t_z, double &dv); + bool MCUA(double &i_r, double &INTER, bool &q_m, double &t_z, double &dv); + + VECTOR3 ThreeBodyAbort(VECTOR3 R_I, VECTOR3 V_I, double t_I, double t_EI, bool q_m, double Incl, double INTER, VECTOR3 &R_EI, VECTOR3 &V_EI); + int MCDRIV(VECTOR3 Y_0, VECTOR3 V_0, double t_0, double var, bool q_m, double Incl, double INTER, bool KIP, double t_zmin, VECTOR3 &V_a, VECTOR3 &R_EI, VECTOR3 &V_EI, double &T_EI, bool &NIR, double &Incl_apo, double &y_p, bool &q_d); double SEARCH(int &IPART, VECTOR3 &DVARR, VECTOR3 &TIGARR, double tig, double dv, bool &IOUT); - bool FINDUX(VECTOR3 R0, VECTOR3 V0, double MJD0, double r_r, double u_r, double beta_r, double i_r, double INTER, bool q_a, double mu, VECTOR3 &DV, VECTOR3 &R_EI, VECTOR3 &V_EI, double &MJD_EI, double &Incl_apo); + bool FINDUX(VECTOR3 X_x, double t_x, double r_r, double u_r, double beta_r, double i_r, double INTER, bool q_a, double mu, VECTOR3 &U_x, VECTOR3 &R_EI, VECTOR3 &V_EI, double &T_EI, double &Incl_apo) const; + void INRFV(VECTOR3 R_1, VECTOR3 V_2, double r_2, double mu, bool k3, double &a, double &e, double &p, double &theta, VECTOR3 &V_1, VECTOR3 &R_2, double &dt_2, bool &q_m, bool &k_1, double &beta_1, double &beta_2) const; + void STORE(int opt, double &dv, double &i_r, double &INTER, double &t_z, bool &q_m); + void PSTATE(double a_H, double e_H, double p_H, double t_0, double T_x, VECTOR3 Y_0, VECTOR3 &Y_a_apo, VECTOR3 V_x, double theta, double beta_a, double beta_x, double T_a, VECTOR3 &V_a, double &t_x_aaapo, VECTOR3 &Y_x_apo, double &Dy_0, double &deltat, VECTOR3 &X_mx, VECTOR3 &U_mx) const; - OBJHANDLE hMoon, hEarth; + int hMoon; double mu_E, mu_M, w_E, R_E, R_M; //double r_s; //Pseudostate sphere - CELBODY *cMoon; double EntryLng; double dlngapo, dtapo; - bool INRFVsign; - double dTIG, mjd0, GMTBASE; + double dTIG, GMTBASE; double i_rmax, u_rmax; //12 = PTP discrete, 14 = ATP discrete, 16 = UA discrete //22 = PTP tradeoff, 24 = ATP tradeoff @@ -642,7 +651,20 @@ class RTEMoon : public RTCCModule double lambda_z, lambda_z1; //Right ascension at GMT zero double alpha_SID0; + //0 = use circumlunar or noncircumlunar, 1 = use retrograde motion + bool QDFLG; + //Reentry radius + double r_r; + //Radius of the pseudostate transformation sphere + double r_s; + //Position and velocity vector of the Moon at abort time + VECTOR3 X_m0, U_m0; //Alternate target line (lat, lng, lat, lng etc.) double LINE[10]; + + RTEMoonStoredSolution solution; + + //Maximum number of iterations for MCDRIV + const int k_max = 50; }; \ No newline at end of file diff --git a/Orbitersdk/samples/ProjectApollo/src_rtccmfd/OrbMech.cpp b/Orbitersdk/samples/ProjectApollo/src_rtccmfd/OrbMech.cpp index 5c87965047..dcb6be3785 100644 --- a/Orbitersdk/samples/ProjectApollo/src_rtccmfd/OrbMech.cpp +++ b/Orbitersdk/samples/ProjectApollo/src_rtccmfd/OrbMech.cpp @@ -987,114 +987,6 @@ SV coast(SV sv0, double dt) return sv1; } -VECTOR3 ThreeBodyLambert(double t_I, double t_E, VECTOR3 R_I, VECTOR3 V_init, VECTOR3 R_E, VECTOR3 R_m, VECTOR3 V_m, double r_s, double mu_E, double mu_M, VECTOR3 &R_I_star, VECTOR3 &delta_I_star, VECTOR3 &delta_I_star_dot, double tol) -{ - VECTOR3 R_I_sstar, V_I_sstar, V_I_star, R_S, R_I_star_apo, R_E_apo, V_E_apo, V_I; - double t_S, dt_S; - OBJHANDLE hMoon, hEarth; - //R_I_star, delta_I_star, delta_I_star_dot, - - hMoon = oapiGetObjectByName("Moon"); - hEarth = oapiGetObjectByName("Earth"); - - //R_I_star = delta_I_star = delta_I_star_dot = _V(0.0, 0.0, 0.0); - - do - { - do - { - R_I_sstar = R_m + R_I_star + delta_I_star; - - if (t_I - t_E < 0) - { - V_I_sstar = elegant_lambert(R_I_sstar, _V(0.0, 0.0, 0.0), R_E, (t_E - t_I) * 24.0 * 3600.0, 0, true, mu_E); - V_I_star = V_I_sstar - V_m - delta_I_star_dot; - INRFV(R_I, V_I_star, r_s, true, mu_M, V_I, R_S, dt_S); - } - else - { - - V_I_sstar = elegant_lambert(R_I_sstar, _V(0.0, 0.0, 0.0), R_E, -(t_E - t_I) * 24.0 * 3600.0, 0, false, mu_E); - V_I_sstar = -V_I_sstar; - V_I_star = V_I_sstar - V_m - delta_I_star_dot; - INRFV(R_I, -V_I_star, r_s, true, mu_M, V_I, R_S, dt_S); - V_I = -V_I; - dt_S *= -1.0; - } - t_S = t_I + dt_S / 24.0 / 3600.0; - R_I_star_apo = R_I_star; - R_I_star = R_S + V_I_star*(t_I - t_S) * 24.0 * 3600.0; - - } while (length(R_I_star - R_I_star_apo) > tol); - - OrbMech::oneclickcoast(R_I, V_I, t_I, (t_E - t_I) * 24.0 * 3600.0, R_E_apo, V_E_apo, hMoon, hEarth); - rv_from_r0v0(R_E_apo, V_E_apo, (t_I - t_E) * 24.0 * 3600.0, R_I_sstar, V_I_sstar, mu_E); - delta_I_star = R_I_sstar - R_m - R_I_star; - delta_I_star_dot = V_I_sstar - V_m - V_I_star; - - } while (length(R_E - R_E_apo) > tol); - - return V_I; -} - -void INRFV(VECTOR3 R_1, VECTOR3 V_2, double r_2, bool direct, double mu, VECTOR3 &V_1, VECTOR3 &R_2, double &dt_2) -{ - VECTOR3 r_1_cf, v_2_cf, c; - double cos_psi, sin_psi, A, B, C, r_1, v_2, theta, sin_beta_2, v_1, f, g, p, sgn; - double AA[5], RR[4]; - int N; - - if (direct) - { - sgn = 1.0; - } - else - { - sgn = -1.0; - } - - r_1 = length(R_1); - v_2 = length(V_2); - r_1_cf = unit(R_1); - v_2_cf = unit(V_2); - - cos_psi = dotp(unit(R_1), unit(V_2)); - sin_psi = sgn*sqrt(1.0 - cos_psi*cos_psi); - - A = r_2*r_2*v_2*v_2 / mu / r_1; - B = (1.0 - r_2*v_2*v_2 / mu)*sin_psi; - C = cos_psi*cos_psi; - - //solve quartic - AA[0] = A*A; - AA[1] = 2.0*A*B; - AA[2] = B*B + C - 2.0*A; - AA[3] = -2.0*B; - AA[4] = 1.0 - C; - - SolveQuartic(AA, RR, N); - - if (cos_psi > 0) - { - sin_beta_2 = RR[N-2]; - } - else - { - sin_beta_2 = RR[N-1]; - } - - c = unit(crossp(r_1_cf, v_2_cf)/sin_psi); - theta = atan2(sin_psi, cos_psi) - sin_beta_2; - R_2 = (r_1_cf*cos(theta)+crossp(c,r_1_cf)*sin(theta))*r_2; - v_1 = sqrt(v_2 - 2.0*mu / r_2 + 2.0*mu / r_1); - p = r_2*r_2*v_2*v_2*sin_beta_2*sin_beta_2 / mu; - f = 1.0 - r_2*(1.0 - cos(theta)) / p; - g = r_2*r_1*sin(theta) / sqrt(mu*p); - V_1 = (R_2 - R_1*f) / g; - - dt_2 = time_theta(R_1, V_1, theta, mu); -} - void SolveQuartic(double *A, double *R, int &N) { double a, b, c, d, e, p, q, delta, delta0, delta1, S; diff --git a/Orbitersdk/samples/ProjectApollo/src_rtccmfd/OrbMech.h b/Orbitersdk/samples/ProjectApollo/src_rtccmfd/OrbMech.h index 539e2ab26d..6c4cbcbfcb 100644 --- a/Orbitersdk/samples/ProjectApollo/src_rtccmfd/OrbMech.h +++ b/Orbitersdk/samples/ProjectApollo/src_rtccmfd/OrbMech.h @@ -228,8 +228,6 @@ namespace OrbMech { void sv_from_coe(OELEMENTS el, double mu, VECTOR3 &R, VECTOR3 &V); OELEMENTS coe_from_sv(VECTOR3 R, VECTOR3 V, double mu); VECTOR3 elegant_lambert(VECTOR3 R1, VECTOR3 V1, VECTOR3 R2, double dt, int N, bool prog, double mu); - VECTOR3 ThreeBodyLambert(double t_I, double t_E, VECTOR3 R_I, VECTOR3 V_init, VECTOR3 R_E, VECTOR3 R_m, VECTOR3 V_m, double r_s, double mu_E, double mu_M, VECTOR3 &R_I_star, VECTOR3 &delta_I_star, VECTOR3 &delta_I_star_dot, double tol = 1000.0); - void INRFV(VECTOR3 R_1, VECTOR3 V_2, double r_2, bool direct, double mu, VECTOR3 &V_1, VECTOR3 &R_2, double &dt_2); void SolveQuartic(double *A, double *R, int &N); VECTOR3 Vinti(VECTOR3 R1, VECTOR3 V1, VECTOR3 R2, double mjd0, double dt, int N, bool prog, int gravref, int gravin, int gravout, VECTOR3 V_guess, double tol = 0.1); double NSRsecant(VECTOR3 RA, VECTOR3 VA, VECTOR3 RP, VECTOR3 VP, double mjd0, double x, double DH, OBJHANDLE gravref); diff --git a/Orbitersdk/samples/ProjectApollo/src_rtccmfd/rtcc_intermediate_library_programs.cpp b/Orbitersdk/samples/ProjectApollo/src_rtccmfd/rtcc_intermediate_library_programs.cpp index 40746d935b..0488f1eb00 100644 --- a/Orbitersdk/samples/ProjectApollo/src_rtccmfd/rtcc_intermediate_library_programs.cpp +++ b/Orbitersdk/samples/ProjectApollo/src_rtccmfd/rtcc_intermediate_library_programs.cpp @@ -703,7 +703,7 @@ void RTCC::PITFPC(double MU, int K, double AORP, double ECC, double rad, double } else { - eps = 31.390; + eps = 63.78165; } //Parabolic case @@ -721,7 +721,7 @@ void RTCC::PITFPC(double MU, int K, double AORP, double ECC, double rad, double //Calculate time TIME = abs(AORP) / 2.0*sqrt(abs(AORP) / MU)*(TEMP1 + 1.0 / 3.0*pow(TEMP1, 3.0)); - if (K == false) + if (K != 0) { TIME = -TIME; } @@ -752,7 +752,7 @@ void RTCC::PITFPC(double MU, int K, double AORP, double ECC, double rad, double TIME = AORP * sqrt(abs(AORP) / MU)*(E - ECC * (exp(E) - exp(-E)) / 2.0); } - if (K == false) + if (K != 0) { TIME = -TIME; } diff --git a/Scenarios/Project Apollo - NASSP/Apollo - Mission Scenarios/Apollo 11/Apollo 11 - 19 - Before TEI T+135h13min.scn b/Scenarios/Project Apollo - NASSP/Apollo - Mission Scenarios/Apollo 11/Apollo 11 - 19 - Before TEI T+135h13min.scn index 3b59b10502..6fc325aec8 100644 --- a/Scenarios/Project Apollo - NASSP/Apollo - Mission Scenarios/Apollo 11/Apollo 11 - 19 - Before TEI T+135h13min.scn +++ b/Scenarios/Project Apollo - NASSP/Apollo - Mission Scenarios/Apollo 11/Apollo 11 - 19 - Before TEI T+135h13min.scn @@ -7158,7 +7158,7 @@ MCC_BEGIN MCC_scrubbed 0 MCC_MissionType 7 MCC_MissionPhase 4 - MCC_MissionState 170 + MCC_MissionState 171 MCC_SubState 2 MCC_EarthRev 5 MCC_MoonRev 30