diff --git a/Orbitersdk/samples/ProjectApollo/src_launch/MCCPADForms.h b/Orbitersdk/samples/ProjectApollo/src_launch/MCCPADForms.h index 1babdac62a..37f7f8dd80 100644 --- a/Orbitersdk/samples/ProjectApollo/src_launch/MCCPADForms.h +++ b/Orbitersdk/samples/ProjectApollo/src_launch/MCCPADForms.h @@ -106,6 +106,39 @@ struct AP7TPI { double GET; // Time that range,range-rate,azimuth, and elevation parameters are valid }; +// SKYLAB - MANEUVER +struct SLMNV { + double GETI; // TIG + VECTOR3 dV; // P30 dV + double Vc; // EMS dV + double Weight; // Vehicle weight + double pTrim, yTrim; // SPS pitch/yaw trim + double burntime; // Burn time + VECTOR3 Att; // Attitude at TIG + char remarks[256]; // remarks + int type; // 1 = NC1, 2 = NPC, 3 = NC2, 4 = NCC, 5 = NSR + bool prelim; // preliminary or final pad + int Star; // Nav star for orientation check + double Shaft, Trun; // Shaft and trunnion values for orientation check +}; + +// SKYLAB - TERMINAL PHASE INITIATE +struct SLTPI { + SLTPI::SLTPI() + { + GETI = 0.0; + Vg = _V(0, 0, 0); + Backup_dV = _V(0.0, 0.0, 0.0); + Backup_bT = _V(0.0, 0.0, 0.0); + } + // ON THE FORM: + double GETI; // TIG + VECTOR3 Vg; // P40 velocity to be gained + VECTOR3 Backup_dV; // Backup "line-of-sight to Target" dV (fore/aft, left/right, up/down) + VECTOR3 Backup_bT; // Burn time to get dV in backup axes + bool prelim; +}; + // APOLLO 7 - ENTRY UPDATE struct AP7ENT { // Pre-burn diff --git a/Orbitersdk/samples/ProjectApollo/src_launch/MCC_Mission_SL.cpp b/Orbitersdk/samples/ProjectApollo/src_launch/MCC_Mission_SL.cpp index 2061e0f7ed..6dd7b5618b 100644 --- a/Orbitersdk/samples/ProjectApollo/src_launch/MCC_Mission_SL.cpp +++ b/Orbitersdk/samples/ProjectApollo/src_launch/MCC_Mission_SL.cpp @@ -39,43 +39,43 @@ void MCC::MissionSequence_SL() UpdateMacro(UTP_NONE, PT_NONE, mcc_calcs.GETEval(30.0*60.0), 10, MST_SL_RENDEZVOUS_PLAN); break; case MST_SL_RENDEZVOUS_PLAN: //Rendezvous planning to NC1 preliminary update - UpdateMacro(UTP_NONE, PT_NONE, mcc_calcs.GETEval(1.0*3600.0 + 35.0*60.0), 11, MST_SL_PRELIM_NC1); + UpdateMacro(UTP_PADONLY, PT_GENERIC, mcc_calcs.GETEval(1.0*3600.0 + 35.0*60.0), 11, MST_SL_PRELIM_NC1); break; case MST_SL_PRELIM_NC1: //NC1 preliminary update to NC1 final update - UpdateMacro(UTP_PADONLY, PT_AP7MNV, mcc_calcs.GETEval(1.0 * 3600.0 + 55.0*60.0), 12, MST_SL_FINAL_NC1); + UpdateMacro(UTP_PADONLY, PT_SLMNV, mcc_calcs.GETEval(1.0 * 3600.0 + 55.0*60.0), 12, MST_SL_FINAL_NC1); break; case MST_SL_FINAL_NC1: //NC1 final update to NC2 preliminary update - UpdateMacro(UTP_PADWITHCMCUPLINK, PT_AP7MNV, mcc_calcs.GETEval(3.0 * 3600.0 + 5*60.0), 13, MST_SL_PRELIM_NC2); + UpdateMacro(UTP_PADWITHCMCUPLINK, PT_SLMNV, mcc_calcs.GETEval(3.0 * 3600.0 + 5*60.0), 13, MST_SL_PRELIM_NC2); break; case MST_SL_PRELIM_NC2: //NC2 preliminary update to SV uplink - UpdateMacro(UTP_PADONLY, PT_AP7MNV, mcc_calcs.GETEval(3.0 * 3600.0 + 27.0*60.0), 14, MST_SL_NC2_SVs); + UpdateMacro(UTP_PADONLY, PT_SLMNV, mcc_calcs.GETEval(3.0 * 3600.0 + 27.0*60.0), 14, MST_SL_NC2_SVs); break; case MST_SL_NC2_SVs: //SV uplink to NC2 final update UpdateMacro(UTP_CMCUPLINKONLY, PT_NONE, mcc_calcs.GETEval(4.0*3600.0 + 12 * 60.0), 24, MST_SL_FINAL_NC2); break; case MST_SL_FINAL_NC2: //NC2 final update to NCC preliminary update - UpdateMacro(UTP_PADONLY, PT_AP7MNV, SubStateTime > 2.0*60.0, 15, MST_SL_PRELIM_NCC); + UpdateMacro(UTP_PADONLY, PT_SLMNV, SubStateTime > 2.0*60.0, 15, MST_SL_PRELIM_NCC); break; case MST_SL_PRELIM_NCC: //NCC preliminary update to NSR preliminary update - UpdateMacro(UTP_PADONLY, PT_AP7MNV, SubStateTime > 2.0*60.0, 16, MST_SL_PRELIM_NSR); + UpdateMacro(UTP_PADONLY, PT_SLMNV, SubStateTime > 2.0*60.0, 16, MST_SL_PRELIM_NSR); break; case MST_SL_PRELIM_NSR: //NSR preliminary update to NCC final update - UpdateMacro(UTP_PADONLY, PT_AP7MNV, mcc_calcs.GETEval(rtcc->calcParams.CSI - 24.0*60.0), 18, MST_SL_FINAL_NCC); + UpdateMacro(UTP_PADONLY, PT_SLMNV, mcc_calcs.GETEval(rtcc->calcParams.CSI - 24.0*60.0), 18, MST_SL_FINAL_NCC); break; case MST_SL_FINAL_NCC: //NCC final update to NSR final update - UpdateMacro(UTP_PADONLY, PT_AP7MNV, SubStateTime > 2.0*60.0, 17, MST_SL_FINAL_NSR); + UpdateMacro(UTP_PADONLY, PT_SLMNV, SubStateTime > 2.0*60.0, 17, MST_SL_FINAL_NSR); break; case MST_SL_FINAL_NSR: //NSR final update to TPI preliminary update - UpdateMacro(UTP_PADONLY, PT_AP7MNV, mcc_calcs.GETEval(rtcc->calcParams.TPI - 34.0*60.0), 19, MST_SL_PRELIM_TPI); + UpdateMacro(UTP_PADONLY, PT_SLMNV, mcc_calcs.GETEval(rtcc->calcParams.TPI - 34.0*60.0), 19, MST_SL_PRELIM_TPI); break; case MST_SL_PRELIM_TPI: //TPI preliminary update to docking attitude PAD - UpdateMacro(UTP_PADONLY, PT_AP7MNV, SubStateTime > 2.0*60.0, 20, MST_DOCKING_ATTITUDE_PAD); + UpdateMacro(UTP_PADONLY, PT_SLTPI, SubStateTime > 2.0*60.0, 20, MST_DOCKING_ATTITUDE_PAD); break; case MST_DOCKING_ATTITUDE_PAD: //Docking attitude PAD to TPI final update UpdateMacro(UTP_PADONLY, PT_GENERIC, mcc_calcs.GETEval(rtcc->calcParams.TPI - 26.0*60.0), 22, MST_SL_FINAL_TPI); break; case MST_SL_FINAL_TPI: //TPI final update to Skylab Solar Inertial Command - UpdateMacro(UTP_PADONLY, PT_AP7MNV, mcc_calcs.GETEval(rtcc->calcParams.TPI + 21.0*60.0), 21, MST_SL_SOLAR_INERTIAL); + UpdateMacro(UTP_PADONLY, PT_SLTPI, mcc_calcs.GETEval(rtcc->calcParams.TPI + 21.0*60.0), 21, MST_SL_SOLAR_INERTIAL); break; case MST_SL_SOLAR_INERTIAL: //Skylab Solar Inertial Command to UpdateMacro(UTP_NONE, PT_NONE, false, 23, MST_ENTRY); diff --git a/Orbitersdk/samples/ProjectApollo/src_launch/RTCC_Mission_SL.cpp b/Orbitersdk/samples/ProjectApollo/src_launch/RTCC_Mission_SL.cpp index 98a98e5b59..3c0e51c6b6 100644 --- a/Orbitersdk/samples/ProjectApollo/src_launch/RTCC_Mission_SL.cpp +++ b/Orbitersdk/samples/ProjectApollo/src_launch/RTCC_Mission_SL.cpp @@ -126,6 +126,8 @@ bool RTCC::CalculationMTP_SL(int fcn, LPVOID& pad, char* upString, char* upDesc, break; case 11: //RENDEZVOUS PLANNING { + GENERICPAD * form = (GENERICPAD *)pad; + char Buff1[64], Buff2[64]; DKIOpt opt; opt.sv_CSM = StateVectorCalcEphem(calcParams.src); @@ -156,21 +158,28 @@ bool RTCC::CalculationMTP_SL(int fcn, LPVOID& pad, char* upString, char* upDesc, calcParams.CDH = PZREDT.GET[3]; //NSR time calcParams.TPI = PZRPDT.data[0].GETTPI; //TPI time - char Buff1[64], Buff2[64]; OrbMech::format_time_HHMMSS(Buff1, calcParams.Phasing); OrbMech::format_time_HHMMSS(Buff2, calcParams.TPI); - sprintf(upMessage, "NC1: %s, TPI: %s", Buff1, Buff2); + sprintf(form->paddata, "NC1: %s, TPI: %s", Buff1, Buff2); } break; case 12: //NC1 preliminary update - preliminary = true; case 13: //NC1 final update { - AP7MNV* form = (AP7MNV*)pad; + SLMNV* form = (SLMNV*)pad; AP7ManPADOpt manopt; DKIOpt opt; + if (fcn == 12) + { + preliminary = true; + } + else + { + preliminary = false; + } + opt.sv_CSM = StateVectorCalcEphem(calcParams.src); opt.sv_LM = StateVectorCalcEphem(calcParams.tgt); opt.MV = 1; //CSM maneuvers @@ -210,8 +219,10 @@ bool RTCC::CalculationMTP_SL(int fcn, LPVOID& pad, char* upString, char* upDesc, manopt.sv0 = opt.sv_CSM; manopt.WeightsTable = GetWeightsTable(calcParams.src, true, false); - AP7ManeuverPAD(manopt, *form); - sprintf(form->purpose, "NC1"); + SLManeuverPAD(manopt, *form); + + form->type = 1; + form->prelim = preliminary; if (preliminary == false) { @@ -231,14 +242,22 @@ bool RTCC::CalculationMTP_SL(int fcn, LPVOID& pad, char* upString, char* upDesc, } break; case 14: //NC2 preliminary update - preliminary = true; case 15: //NC2 final update { - AP7MNV* form = (AP7MNV*)pad; + SLMNV* form = (SLMNV*)pad; AP7ManPADOpt manopt; DKIOpt opt; double CSMMass; + if (fcn == 14) + { + preliminary = true; + } + else + { + preliminary = false; + } + opt.sv_CSM = StateVectorCalcEphem(calcParams.src); CSMMass = calcParams.src->GetMass(); opt.sv_LM = StateVectorCalcEphem(calcParams.tgt); @@ -280,8 +299,11 @@ bool RTCC::CalculationMTP_SL(int fcn, LPVOID& pad, char* upString, char* upDesc, char Buff1[64]; OrbMech::format_time_HHHMMSSCS(Buff1, calcParams.TPI); - AP7ManeuverPAD(manopt, *form); - sprintf(form->purpose, "NC2"); + SLManeuverPAD(manopt, *form); + + form->type = 3; + form->prelim = preliminary; + if (preliminary) { sprintf(form->remarks, "TPI: %s", Buff1); @@ -289,15 +311,23 @@ bool RTCC::CalculationMTP_SL(int fcn, LPVOID& pad, char* upString, char* upDesc, } break; case 16: //NCC preliminary update - preliminary = true; case 17: //NCC final update { - AP7MNV* form = (AP7MNV*)pad; + SLMNV* form = (SLMNV*)pad; AP7ManPADOpt manopt; TwoImpulseOpt opt; TwoImpulseResuls res; double CSMMass; + if (fcn == 16) + { + preliminary = true; + } + else + { + preliminary = false; + } + opt.mode = 5; opt.T1 = GMTfromGET(calcParams.CSI); opt.T2 = GMTfromGET(calcParams.CDH); @@ -344,17 +374,27 @@ bool RTCC::CalculationMTP_SL(int fcn, LPVOID& pad, char* upString, char* upDesc, manopt.WeightsTable.CC[RTCC_CONFIG_C] = true; manopt.WeightsTable.ConfigWeight = manopt.WeightsTable.CSMWeight = CSMMass; - AP7ManeuverPAD(manopt, *form); - sprintf(form->purpose, "NCC"); + SLManeuverPAD(manopt, *form); + + form->type = 4; + form->prelim = preliminary; } break; case 18: //NSR preliminary update - preliminary = true; case 19: //NSR final update { - AP7MNV* form = (AP7MNV*)pad; + SLMNV* form = (SLMNV*)pad; AP7ManPADOpt manopt; + if (fcn == 18) + { + preliminary = true; + } + else + { + preliminary = false; + } + manopt.TIG = calcParams.CDH; manopt.dV_LVLH = calcParams.DVSTORE1; //Was calculated for NCC PAD manopt.enginetype = RTCC_ENGINETYPE_CSMSPS; @@ -368,24 +408,38 @@ bool RTCC::CalculationMTP_SL(int fcn, LPVOID& pad, char* upString, char* upDesc, manopt.WeightsTable.CC[RTCC_CONFIG_C] = true; manopt.WeightsTable.ConfigWeight = manopt.WeightsTable.CSMWeight = calcParams.SVSTORE1.mass; - AP7ManeuverPAD(manopt, *form); - sprintf(form->purpose, "NSR"); + SLManeuverPAD(manopt, *form); + + form->type = 5; + form->prelim = preliminary; } break; case 20: //TPI preliminary update - preliminary = true; case 21: //TPI final update { - AP7MNV* form = (AP7MNV*)pad; - AP7ManPADOpt manopt; + SLTPI* form = (SLTPI*)pad; + AP7TPIPADOpt manopt; TwoImpulseOpt opt; TwoImpulseResuls res; + VehicleDataBlock sv_A, sv_P; + + sv_A = StateVectorCalcDataBlock(calcParams.src); + sv_P = StateVectorCalcDataBlock(calcParams.tgt); + + if (fcn == 20) + { + preliminary = true; + } + else + { + preliminary = false; + } opt.mode = 5; opt.T1 = -1.0; opt.T2 = -1.0; - opt.sv_C = StateVectorCalcDataBlock(calcParams.src); - opt.sv_T = StateVectorCalcDataBlock(calcParams.tgt); + opt.sv_C = sv_A; + opt.sv_T = sv_P; opt.DH = opt.PhaseAngle = 0.0; opt.Elev = 27.0 * RAD; opt.WT = 130.0 * RAD; @@ -394,20 +448,15 @@ bool RTCC::CalculationMTP_SL(int fcn, LPVOID& pad, char* upString, char* upDesc, calcParams.TPI = res.T1; //Update TPI time - manopt.TIG = res.T1; manopt.dV_LVLH = res.dV_LVLH; - manopt.enginetype = RTCC_ENGINETYPE_CSMSPS; - manopt.HeadsUp = true; - manopt.REFSMMAT = GetREFSMMATfromAGC(&mcc->cm->agc.vagc, true); - manopt.navcheckGET = 0.0; - manopt.sxtstardtime = 0.0; - manopt.UllageDT = 15.0; - manopt.UllageThrusterOpt = true; - manopt.sv0 = opt.sv_C.sv; - manopt.WeightsTable = GetWeightsTable(calcParams.src, true, false); + manopt.TIG = res.T1; + manopt.sv_A = sv_A.sv; + manopt.sv_P = sv_P.sv; + manopt.mass = calcParams.src->GetMass(); + + SLTPIPAD(manopt, *form); - AP7ManeuverPAD(manopt, *form); - sprintf(form->purpose, "TPI"); + form->prelim = preliminary; } break; case 22: //Docking Attitude PAD diff --git a/Orbitersdk/samples/ProjectApollo/src_launch/mcc.cpp b/Orbitersdk/samples/ProjectApollo/src_launch/mcc.cpp index 763e035f3a..7de6e8e6ef 100644 --- a/Orbitersdk/samples/ProjectApollo/src_launch/mcc.cpp +++ b/Orbitersdk/samples/ProjectApollo/src_launch/mcc.cpp @@ -2116,6 +2116,37 @@ void MCC::SaveState(FILEHANDLE scn) { SAVE_INT("MCC_AP7PTCPAD_Type", form->type); } + else if (padNumber == PT_SLMNV) + { + SLMNV * form = (SLMNV *)padForm; + + SAVE_DOUBLE("MCC_SLMNV_GETI", form->GETI); + SAVE_V3("MCC_SLMNV_dV", form->dV); + SAVE_V3("MCC_SLMNV_Att", form->Att); + SAVE_DOUBLE("MCC_SLMNV_Vc", form->Vc); + SAVE_DOUBLE("MCC_SLMNV_burntime", form->burntime); + SAVE_DOUBLE("MCC_SLMNV_Weight", form->Weight); + SAVE_DOUBLE("MCC_SLMNV_pTrim", form->pTrim); + SAVE_DOUBLE("MCC_SLMNV_yTrim", form->yTrim); + SAVE_STRING("MCC_SLMNV_remarks", form->remarks); + SAVE_INT("MCC_SLMNV_type", form->type); + SAVE_BOOL("MCC_SLMNV_PRELIM", form->prelim); + SAVE_DOUBLE("MCC_SLMNV_Shaft", form->Shaft); + SAVE_INT("MCC_SLMNV_Star", form->Star); + SAVE_DOUBLE("MCC_SLMNV_Trun", form->Trun); + } + + else if (padNumber == PT_SLTPI) + { + SLTPI * form = (SLTPI *)padForm; + + SAVE_V3("MCC_SLTPI_Backup_bT", form->Backup_bT); + SAVE_V3("MCC_SLTPI_Backup_dV", form->Backup_dV); + SAVE_DOUBLE("MCC_SLTPI_GETI", form->GETI); + SAVE_V3("MCC_SLTPI_Vg", form->Vg); + SAVE_BOOL("MCC_SLTPI_PRELIM", form->prelim); + } + } // Write uplink buffer here! if (upString[0] != 0 && uplink_size > 0) { SAVE_STRING("MCC_upString", upString); } @@ -2785,6 +2816,37 @@ void MCC::LoadState(FILEHANDLE scn) { LOAD_INT("MCC_AP7PTCPAD_Type", form->type); } + else if (padNumber == PT_SLMNV) + { + SLMNV * form = (SLMNV *)padForm; + + LOAD_DOUBLE("MCC_SLMNV_GETI", form->GETI); + LOAD_V3("MCC_SLMNV_dV", form->dV); + LOAD_V3("MCC_SLMNV_Att", form->Att); + LOAD_DOUBLE("MCC_SLMNV_Vc", form->Vc); + LOAD_DOUBLE("MCC_SLMNV_burntime", form->burntime); + LOAD_DOUBLE("MCC_SLMNV_Weight", form->Weight); + LOAD_DOUBLE("MCC_SLMNV_pTrim", form->pTrim); + LOAD_DOUBLE("MCC_SLMNV_yTrim", form->yTrim); + LOAD_STRING("MCC_SLMNV_remarks", form->remarks, 256); + LOAD_INT("MCC_SLMNV_type", form->type); + LOAD_BOOL("MCC_SLMNV_prelim", form->prelim); + LOAD_DOUBLE("MCC_SLMNV_Shaft", form->Shaft); + LOAD_INT("MCC_SLMNV_Star", form->Star); + LOAD_DOUBLE("MCC_SLMNV_Trun", form->Trun); + } + + else if (padNumber == PT_SLTPI) + { + SLTPI * form = (SLTPI *)padForm; + + LOAD_V3("MCC_SLTPI_Backup_bT", form->Backup_bT); + LOAD_V3("MCC_SLTPI_Backup_dV", form->Backup_dV); + LOAD_DOUBLE("MCC_SLTPI_GETI", form->GETI); + LOAD_V3("MCC_SLTPI_Vg", form->Vg); + LOAD_BOOL("MCC_SLTPI_prelim", form->prelim); + } + LOAD_STRING("MCC_upString", upString, 3072); LOAD_INT("MCC_upType", upType); LOAD_STRING("MCC_upDescr", upDescr, 1024); @@ -2923,7 +2985,7 @@ void MCC::drawPad(bool writetofile){ snprintf(buffer, 1024, "%s", fullString.c_str()); oapiAnnotationSetText(NHpad,buffer); } - break; + break; case PT_AP7TPI: { AP7TPI * form = (AP7TPI *)padForm; @@ -2957,7 +3019,113 @@ void MCC::drawPad(bool writetofile){ oapiAnnotationSetText(NHpad, buffer); } + break; + case PT_SLMNV: + { + SLMNV * form = (SLMNV *)padForm; + int hh, hh2, mm, mm2; + double ss, ss2; + char padprelim[32], tempString1[1024], tempString2[1024]; + OrbMech::SStoHHMMSS(form->GETI, hh, mm, ss, 0.01); + OrbMech::SStoHHMMSS(form->burntime, hh2, mm2, ss2); + + if (form->prelim) + { + sprintf(padprelim, "PRELIMINARY"); + sprintf(tempString1, "\n"); + sprintf(tempString2, "\n"); + } + else + { + sprintf(padprelim, "FINAL"); + sprintf(tempString1, "%+06.0f CSM WGT\n%+07.2f PTRM\n%+07.2f YTRM\n", form->Weight, form->pTrim, form->yTrim); + sprintf(tempString2, "XXXX%02d STAR\n%+07.2f SA\n%+07.3f TA\n", form->Star, form->Shaft, form->Trun); + } + + switch (form->type) + { + case 1: //NC1 + { + snprintf(buffer, 1024, "%s NC1 PAD DATA\n%+06d HR N95\n%+06d MIN TIG NC1\n%+07.2f SEC\n%+07.1f DVX N81\n%+07.1f DVY NC1\n%+07.1f DVZ\nXXX%03.0f R N22\nXXX%03.0f P NC1\nXXX%03.0f Y\n%+07.1f DVC\nXX%d:%02.0f BT\n%s%s%sRemarks:\n", + padprelim, hh, mm, ss, form->dV.x, form->dV.y, form->dV.z, form->Att.x, form->Att.y, form->Att.z, form->Vc, mm2, ss2, tempString1, tempString2, form->remarks); + } + break; + case 2: //NPC + { + snprintf(buffer, 1024, "NPC PAD DATA\nPLANE CHANGE\n%+06d HR N33\n%+06d MIN TIG NPC\n%+07.2f SEC\n%+07.1f DVX N81\n%+07.1f DVY NPC\n%+07.1f DVZ\n%+07.1f DVC\nXX%d:%02.0f BT\n%s\n%sRemarks:\n", + hh, mm, ss, form->dV.x, form->dV.y, form->dV.z, form->Vc, mm2, ss2, tempString1, form->remarks); + } + break; + case 3: //NC2 + { + snprintf(buffer, 1024, "%s NC2 PAD DATA\n%+06d HR N28\n%+06d MIN TIG NC2\n%+07.2f SEC\n%+07.1f DVX N81\n%+07.1f DVY NC2\n%+07.1f DVZ\nXXX%03.0f R N22\nXXX%03.0f P NC2\nXXX%03.0f Y\n%+07.1f DVC\nXX%d:%02.0f BT\n%s%sRemarks:\n", + padprelim, hh, mm, ss, form->dV.x, form->dV.y, form->dV.z, form->Att.x, form->Att.y, form->Att.z, form->Vc, mm2, ss2, tempString1, form->remarks); + } + break; + case 4: //NCC + { + snprintf(buffer, 1024, "%s NCC PAD DATA\n%+06d HR N11\n%+06d MIN TIG NCC\n%+07.2f SEC\n%+07.1f DVX N81\n%+07.1f DVY NCC\n%+07.1f DVZ\n%+07.1f DVC\nXXX%03.0f R N22\nXXX%03.0f P NCC\nXXX%03.0f Y\n%s%sRemarks:\n", + padprelim, hh, mm, ss, form->dV.x, form->dV.y, form->dV.z, form->Vc, form->Att.x, form->Att.y, form->Att.z, tempString1, form->remarks); + } + break; + case 5: //NSR + { + snprintf(buffer, 1024, "%s NSR PAD DATA\n%+06d HR N13\n%+06d MIN TIG NSR\n%+07.2f SEC\n%+07.1f DVX N81\n%+07.1f DVY NSR\n%+07.1f DVZ\n%+07.1f DVC\nXXX%03.0f R N22\nXXX%03.0f P NSR\nXXX%03.0f Y\n%s%sRemarks:\n", + padprelim, hh, mm, ss, form->dV.x, form->dV.y, form->dV.z, form->Vc, form->Att.x, form->Att.y, form->Att.z, tempString1, form->remarks); + } break; + } + oapiAnnotationSetText(NHpad, buffer); + } + break; + case PT_SLTPI: + { + SLTPI * form = (SLTPI *)padForm; + form->prelim; + int hh, mm; + double ss; + char padprelim[32]; + OrbMech::SStoHHMMSS(form->GETI, hh, mm, ss, 0.01); + + if (form->prelim) + { + sprintf(padprelim, "PRELIMINARY"); + } + else + { + sprintf(padprelim, "FINAL"); + } + + sprintf(buffer, "TPI PAD DATA\n%s\n%+06d HR N37\n%+06d MIN TIG TPI\n%+07.2f SEC\n%+07.1f DVX N81\n%+07.1f DVY TPI\n%+07.1f DVZ\n", padprelim, hh, mm, ss, form->Vg.x, form->Vg.y, form->Vg.z); + if (form->Backup_dV.x > 0) + { + sprintf(buffer, "%sF%04.1f/%02.0f DVX LOS/BT N59\n", buffer, abs(form->Backup_dV.x), form->Backup_bT.x); + } + else + { + sprintf(buffer, "%sA%04.1f/%02.0f DVX LOS/BT N59\n", buffer, abs(form->Backup_dV.x), form->Backup_bT.x); + } + if (form->Backup_dV.y > 0) + { + sprintf(buffer, "%sR%04.1f/%02.0f DVY LOS/BT\n", buffer, abs(form->Backup_dV.y), form->Backup_bT.y); + } + else + { + sprintf(buffer, "%sL%04.1f/%02.0f DVY LOS/BT\n", buffer, abs(form->Backup_dV.y), form->Backup_bT.y); + } + if (form->Backup_dV.z > 0) + { + sprintf(buffer, "%sD%04.1f/%02.0f DVZ LOS/BT\n", buffer, abs(form->Backup_dV.z), form->Backup_bT.z); + } + else + { + sprintf(buffer, "%sU%04.1f/%02.0f DVZ LOS/BT\n", buffer, abs(form->Backup_dV.z), form->Backup_bT.z); + } + sprintf(buffer, "%s", buffer); + + oapiAnnotationSetText(NHpad, buffer); + } + break; case PT_AP7ENT: { AP7ENT * form = (AP7ENT *)padForm; @@ -4046,6 +4214,12 @@ void MCC::allocPad(int Number){ case PT_AP7PTCPAD: // AP7PTCPAD padForm = calloc(1, sizeof(AP7PTCPAD)); break; + case PT_SLMNV: // SLMNV + padForm = calloc(1, sizeof(SLMNV)); + break; + case PT_SLTPI: // SLTPI + padForm = calloc(1, sizeof(SLTPI)); + break; case PT_GENERIC: // GENERICPAD padForm = calloc(1, sizeof(GENERICPAD)); break; diff --git a/Orbitersdk/samples/ProjectApollo/src_launch/mcc.h b/Orbitersdk/samples/ProjectApollo/src_launch/mcc.h index 472390a9b5..2ea390cc0c 100644 --- a/Orbitersdk/samples/ProjectApollo/src_launch/mcc.h +++ b/Orbitersdk/samples/ProjectApollo/src_launch/mcc.h @@ -187,6 +187,8 @@ #define PT_AP7WSMRPAD 38 #define PT_AP7P23PAD 39 #define PT_AP7PTCPAD 40 +#define PT_SLMNV 50 +#define PT_SLTPI 51 #define PT_NONE 99 #define PT_GENERIC 100 diff --git a/Orbitersdk/samples/ProjectApollo/src_launch/rtcc.cpp b/Orbitersdk/samples/ProjectApollo/src_launch/rtcc.cpp index 274d83f81f..7936fbade9 100644 --- a/Orbitersdk/samples/ProjectApollo/src_launch/rtcc.cpp +++ b/Orbitersdk/samples/ProjectApollo/src_launch/rtcc.cpp @@ -3733,6 +3733,233 @@ void RTCC::AP7TPIPAD(const AP7TPIPADOpt &opt, AP7TPI &pad) pad.dH_Max = TPIPAD_ddH / 1852.0; } +void RTCC::SLManeuverPAD(const AP7ManPADOpt &opt, SLMNV &pad) +{ + PMMRKJInputArray integin; + int Ierr; + RTCCNIAuxOutputTable aux; + VECTOR3 IMUangles; + double dt, mu, ManPADPTrim, ManPADYTrim, GMT_TIG; + double R_E; + EphemerisData sv1, sv2; + + GMT_TIG = GMTfromGET(opt.TIG); + + //Calculate time of ullage on for burn simulation + if (opt.enginetype == RTCC_ENGINETYPE_CSMSPS) + { + double dt_ullage_overlap; + + if (opt.UllageDT == 0.0) + { + dt_ullage_overlap = 0.0; + } + else + { + dt_ullage_overlap = SystemParameters.MCTSD9; + } + + double gmt_bb = GMT_TIG - opt.UllageDT + dt_ullage_overlap; //GMT of burn begin (ullage) + dt = gmt_bb - opt.sv0.GMT; + + integin.DTU = opt.UllageDT; + } + else + { + dt = GMT_TIG - opt.sv0.GMT; + integin.DTU = 0.0; + } + sv1 = coast(opt.sv0, dt, opt.WeightsTable.ConfigWeight, opt.WeightsTable.ConfigArea, opt.WeightsTable.KFactor, false); + + //Settings for burn simulation + integin.sv0 = sv1; + integin.DENSMULT = opt.WeightsTable.KFactor; + integin.A = opt.WeightsTable.ConfigArea; + integin.CAPWT = opt.WeightsTable.ConfigWeight; + integin.KEPHOP = 0; + integin.KAUXOP = true; + integin.CSMWT = opt.WeightsTable.CSMWeight; + integin.LMAWT = opt.WeightsTable.LMAscWeight; + integin.LMDWT = opt.WeightsTable.LMDscWeight; + integin.MANOP = RTCC_ATTITUDE_PGNS_EXDV; + integin.ThrusterCode = opt.enginetype; + integin.UllageOption = opt.UllageThrusterOpt; + integin.IC = opt.WeightsTable.CC.to_ulong(); + integin.TVC = 1; + integin.KTRIMOP = -1; + integin.DOCKANG = 0.0; + integin.VG = opt.dV_LVLH; + integin.HeadsUpDownInd = opt.HeadsUp; + integin.ExtDVCoordInd = true; + + //Burn simulation + CSMLMPoweredFlightIntegration numin(this, integin, Ierr, NULL, &aux); + numin.PMMRKJ(); + + //Store PAD data from inputs + pad.GETI = opt.TIG; + pad.dV = opt.dV_LVLH / 0.3048; + pad.Weight = opt.WeightsTable.CSMWeight / 0.45359237; + + //Store PAD data from burn simulation + pad.burntime = aux.DT_B; + pad.Vc = aux.DV_C / 0.3048; + if (opt.enginetype == RTCC_ENGINETYPE_CSMRCSMINUS2 || opt.enginetype == RTCC_ENGINETYPE_CSMRCSMINUS4) + { + pad.Vc = -pad.Vc; + } + + //Calculate height of periapsis and apoapsis + if (sv1.RBI == BODY_EARTH) + { + mu = OrbMech::mu_Earth; + R_E = OrbMech::R_Earth; + } + else + { + mu = OrbMech::mu_Moon; + R_E = OrbMech::R_Moon; + } + + //Attitude + VECTOR3 X_P, Y_P, Z_P; + X_P = _V(opt.REFSMMAT.m11, opt.REFSMMAT.m12, opt.REFSMMAT.m13); + Y_P = _V(opt.REFSMMAT.m21, opt.REFSMMAT.m22, opt.REFSMMAT.m23); + Z_P = _V(opt.REFSMMAT.m31, opt.REFSMMAT.m32, opt.REFSMMAT.m33); + + double MG, OG, IG, C; + + MG = asin(dotp(Y_P, aux.X_B)); + C = abs(MG); + + if (abs(C - PI05) < 0.0017) + { + OG = 0.0; + IG = atan2(dotp(X_P, aux.Z_B), dotp(Z_P, aux.Z_B)); + } + else + { + OG = atan2(-dotp(aux.Z_B, Y_P), dotp(aux.Y_B, Y_P)); + IG = atan2(-dotp(aux.X_B, Z_P), dotp(aux.X_B, X_P)); + } + + IMUangles = _V(OG, IG, MG); + + //Round IMU attitude to next degree + pad.Att = OrbMech::imulimit(IMUangles * DEG); + + EphemerisData sv_sxt; + sv_sxt = coast(sv1, opt.sxtstardtime, opt.WeightsTable.ConfigWeight, opt.WeightsTable.ConfigArea, opt.WeightsTable.KFactor, false); + + OrbMech::checkstar(EZJGSTAR, opt.REFSMMAT, pad.Att*RAD, sv_sxt.R, R_E, pad.Star, pad.Trun, pad.Shaft); + + //Trim angles + if (opt.enginetype == RTCC_ENGINETYPE_CSMSPS) + { + ManPADPTrim = aux.P_G - SystemParameters.MCTSPP; + ManPADYTrim = aux.Y_G - SystemParameters.MCTSYP; + pad.pTrim = ManPADPTrim * DEG; + pad.yTrim = ManPADYTrim * DEG; + } + else + { + pad.pTrim = 0.0; + pad.yTrim = 0.0; + } + + pad.Shaft *= DEG; + pad.Trun *= DEG; +} + +void RTCC::SLTPIPAD(const AP7TPIPADOpt &opt, SLTPI &pad) +{ + EphemerisData sv_A2, sv_P2, sv_A3, sv_P3; + double dt1, dt2; + VECTOR3 u, U_L, UX, UY, UZ, U_R, U_R2, U_P, TPIPAD_BT, TPIPAD_dV_LOS; + MATRIX3 Rot1, Rot2; + double TPIPAD_AZ, TPIPAD_R, TPIPAD_Rdot, TPIPAD_ELmin5, TPIPAD_dH, TPIPAD_ddH, TIG_GMT; + VECTOR3 U_F, LOS, U_LOS, NN; + + TIG_GMT = GMTfromGET(opt.TIG); + + dt1 = TIG_GMT - opt.sv_A.GMT; + dt2 = TIG_GMT - opt.sv_P.GMT; + + sv_A3 = coast(opt.sv_A, dt1); + sv_P3 = coast(opt.sv_P, dt2); + + UY = unit(crossp(sv_A3.V, sv_A3.R)); + UZ = unit(-sv_A3.R); + UX = crossp(UY, UZ); + + Rot1 = _M(UX.x, UY.x, UZ.x, UX.y, UY.y, UZ.y, UX.z, UY.z, UZ.z); + + u = unit(crossp(sv_A3.R, sv_A3.V)); + U_L = unit(sv_P3.R - sv_A3.R); + UX = U_L; + UY = unit(crossp(crossp(u, UX), UX)); + UZ = crossp(UX, UY); + + Rot2 = _M(UX.x, UX.y, UX.z, UY.x, UY.y, UY.z, UZ.x, UZ.y, UZ.z); + + TPIPAD_dV_LOS = mul(Rot2, mul(Rot1, opt.dV_LVLH)); + //TPIPAD_dH = abs(length(RP3) - length(RA3)); + double F; + + F = 200.0 * 4.448222; + TPIPAD_BT = _V(abs(0.5*TPIPAD_dV_LOS.x), abs(TPIPAD_dV_LOS.y), abs(TPIPAD_dV_LOS.z))*opt.mass / F; + + VECTOR3 i, j, k, dr, dv, dr0, dv0, Omega; + MATRIX3 Q_Xx; + double t1, t2, dxmin, n, dxmax; + + j = unit(sv_P3.V); + k = unit(crossp(sv_P3.R, j)); + i = crossp(j, k); + Q_Xx = _M(i.x, i.y, i.z, j.x, j.y, j.z, k.x, k.y, k.z); + dr = sv_A3.R - sv_P3.R; + n = length(sv_P3.V) / length(sv_P3.R); + Omega = k*n; + dv = sv_A3.V - sv_P3.V - crossp(Omega, dr); + dr0 = mul(Q_Xx, dr); + dv0 = mul(Q_Xx, dv); + t1 = 1.0 / n*atan(-dv0.x / (3.0*n*dr0.x + 2.0 * dv0.y)); + t2 = 1.0 / n*(atan(-dv0.x / (3.0*n*dr0.x + 2.0 * dv0.y)) + PI); + dxmax = 4.0 * dr0.x + 2.0 / n*dv0.y + dv0.x / n*sin(n*t1) - (3.0 * dr0.x + 2.0 / n*dv0.y)*cos(n*t1); + dxmin = 4.0 * dr0.x + 2.0 / n*dv0.y + dv0.x / n*sin(n*t2) - (3.0 * dr0.x + 2.0 / n*dv0.y)*cos(n*t2); + + sv_A2 = coast(sv_A3, -5.0*60.0); + sv_P2 = coast(sv_P3, -5.0*60.0); + + U_R2 = unit(sv_P2.R - sv_A2.R); + + TPIPAD_dH = -dr0.x; + TPIPAD_ddH = abs(dxmax - dxmin); + TPIPAD_R = abs(length(sv_P2.R - sv_A2.R)); + TPIPAD_Rdot = dotp(sv_P2.V - sv_A2.V, U_R2); + + U_L = unit(sv_P2.R - sv_A2.R); + U_P = unit(U_L - sv_A2.R*dotp(U_L, sv_A2.R) / length(sv_A2.R) / length(sv_A2.R)); + + TPIPAD_ELmin5 = acos(dotp(U_L, U_P*OrbMech::sign(dotp(U_P, crossp(u, sv_A2.R))))); + + U_F = unit(crossp(crossp(sv_A2.R, sv_A2.V), sv_A2.R)); + U_R = unit(sv_A2.R); + LOS = sv_P2.R - sv_A2.R; + U_LOS = unit(LOS - U_R*dotp(LOS, U_R)); + TPIPAD_AZ = acos(dotp(U_LOS, U_F));//atan2(-TPIPAD_dV_LOS.z, TPIPAD_dV_LOS.x); + NN = crossp(U_LOS, U_F); + if (dotp(NN, sv_A2.R) < 0) + { + TPIPAD_AZ = PI2 - TPIPAD_AZ; + } + + pad.Backup_bT = TPIPAD_BT; + pad.Backup_dV = TPIPAD_dV_LOS / 0.3048; + pad.GETI = opt.TIG; + pad.Vg = opt.dV_LVLH / 0.3048; +} + void RTCC::AP9LMTPIPAD(const AP9LMTPIPADOpt &opt, AP9LMTPI &pad) { EphemerisData sv_A1, sv_P1; diff --git a/Orbitersdk/samples/ProjectApollo/src_launch/rtcc.h b/Orbitersdk/samples/ProjectApollo/src_launch/rtcc.h index 619b5eceb4..a0e19a34a8 100644 --- a/Orbitersdk/samples/ProjectApollo/src_launch/rtcc.h +++ b/Orbitersdk/samples/ProjectApollo/src_launch/rtcc.h @@ -2440,6 +2440,7 @@ class RTCC { void TimeUpdate(); public: void AP7TPIPAD(const AP7TPIPADOpt &opt, AP7TPI &pad); + void SLTPIPAD(const AP7TPIPADOpt &opt, SLTPI &pad); void AP9LMTPIPAD(const AP9LMTPIPADOpt &opt, AP9LMTPI &pad); void AP9LMCDHPAD(const AP9LMCDHPADOpt &opt, AP9LMCDH &pad); void TLI_PAD(const TLIPADOpt &opt, TLIPAD &pad); @@ -5159,6 +5160,7 @@ class RTCC { private: void AP7ManeuverPAD(const AP7ManPADOpt &opt, AP7MNV &pad); + void SLManeuverPAD(const AP7ManPADOpt &opt, SLMNV &pad); void navcheck(VECTOR3 R, double GMT, int RBI, double &lat, double &lng, double &alt); void AP7BlockData(AP7BLKOpt *opt, AP7BLK &pad); void AP11BlockData(AP11BLKOpt *opt, P37PAD &pad);