From d1f35f2d5b95584fd5a3ac587bdd04ea0a9c719e Mon Sep 17 00:00:00 2001 From: indy91 Date: Thu, 11 Jan 2024 16:59:18 +0100 Subject: [PATCH] First attempt at new LM RCS behavior --- .../ProjectApollo/src_lm/LEMcomputer.cpp | 27 ++- .../samples/ProjectApollo/src_lm/lmscs.cpp | 229 +++--------------- .../samples/ProjectApollo/src_lm/lmscs.h | 11 +- .../ProjectApollo/src_sys/apolloguidance.cpp | 146 +++++++++++ .../ProjectApollo/src_sys/apolloguidance.h | 26 ++ 5 files changed, 226 insertions(+), 213 deletions(-) diff --git a/Orbitersdk/samples/ProjectApollo/src_lm/LEMcomputer.cpp b/Orbitersdk/samples/ProjectApollo/src_lm/LEMcomputer.cpp index d210fc9e37..c5d5240550 100644 --- a/Orbitersdk/samples/ProjectApollo/src_lm/LEMcomputer.cpp +++ b/Orbitersdk/samples/ProjectApollo/src_lm/LEMcomputer.cpp @@ -49,11 +49,8 @@ LEMcomputer::LEMcomputer(SoundLib &s, DSKY &display, IMU &im, CDU &sc, CDU &tc, isLGC = true; - /* FIXME LOAD FILE SHOULD BE SET IN SCENARIO */ - //InitVirtualAGC("Config/ProjectApollo/Luminary099.bin"); - - /* FIXME REMOVE THIS LATER, THIS IS TEMPORARY FOR TESTING ONLY AND SHOULD BE IN THE SCENARIO LATER */ - /* LM PAD LOAD FOR LUMINARY 099 AND APOLLO 11 - OFFICIAL VERSION */ + ThrustOnDelay = 30; // 0.019 seconds in units of 1/1600 seconds + ThrustOffDelay = 24; // 0.015 seconds in units of 1/1600 seconds Start(); } @@ -86,9 +83,12 @@ void LEMcomputer::agcTimestep(double simt, double simdt) if (LastCycled == 0) { // Use simdt as difference if new run LastCycled = (simt - simdt); lem->PCM.last_update = LastCycled; + LastRCSTime = LastCycled; } double ThisTime = LastCycled; // Save here + InitRCSActivity(); + long cycles = (long)((simt - LastCycled) / 0.00001171875); // Get number of CPU cycles to do LastCycled += (0.00001171875 * cycles); // Preserve the remainder long x = 0; @@ -98,8 +98,15 @@ void LEMcomputer::agcTimestep(double simt, double simdt) if ((ThisTime - lem->PCM.last_update) > 0.00015625) { // If a step is needed lem->PCM.Timestep(ThisTime); // do it } + if (ThisTime - LastRCSTime > 6.25e-04) // 1/1600 second + { + MonitorRCSActivity(); + LastRCSTime = ThisTime; + } x++; } + + CalculateRCSDutyCycle(); } void LEMcomputer::Run () @@ -178,7 +185,7 @@ void LEMcomputer::Timestep(double simt, double simdt) lem->PCM.last_update = simt - simdt; } lem->PCM.Timestep(simt); - + ResetRCSDutyCycle(); // and do nothing more. return; } @@ -261,14 +268,14 @@ void LEMcomputer::ProcessChannel13(ChannelValue val){ void LEMcomputer::ProcessChannel5(ChannelValue val){ // This is now handled inside the ATCA - LEM *lem = (LEM *) OurVessel; - lem->atca.ProcessLGC(5,val.to_ulong()); + //LEM *lem = (LEM *) OurVessel; + //lem->atca.ProcessLGC(5,val.to_ulong()); } void LEMcomputer::ProcessChannel6(ChannelValue val){ // This is now handled inside the ATCA - LEM *lem = (LEM *) OurVessel; - lem->atca.ProcessLGC(6,val.to_ulong()); + //LEM *lem = (LEM *) OurVessel; + //lem->atca.ProcessLGC(6,val.to_ulong()); } void LEMcomputer::ProcessChannel142(ChannelValue val) { diff --git a/Orbitersdk/samples/ProjectApollo/src_lm/lmscs.cpp b/Orbitersdk/samples/ProjectApollo/src_lm/lmscs.cpp index 4913939c65..c8aad22918 100644 --- a/Orbitersdk/samples/ProjectApollo/src_lm/lmscs.cpp +++ b/Orbitersdk/samples/ProjectApollo/src_lm/lmscs.cpp @@ -41,6 +41,9 @@ #include "Mission.h" #include "LEM.h" +//To convert LGC channels 5+6 consequitely to NASSP LM RCS thruster numbers +static const int LGCThrusterConversion[16] = {6, 10, 15, 7, 4, 12, 11, 5, 2, 13, 8, 3, 0, 9, 14, 1}; + // RATE GYRO ASSEMBLY LEM_RGA::LEM_RGA() @@ -176,7 +179,7 @@ ATCA::ATCA(){ void ATCA::Init(LEM *vessel, h_HeatLoad *hl){ lem = vessel; ATCAHeat = hl; - int x = 0; while (x < 16) { pgns_jet_request[x] = false; ags_jet_request[x] = false; jet_driver[x] = false; jet_request[x] = 0; jet_last_request[x] = 0; jet_start[x] = 0; jet_stop[x] = 0; x++; } + int x = 0; while (x < 16) { ags_jet_request[x] = false; jet_driver[x] = 0.0; jet_request[x] = 0; x++; } } double ATCA::GetPrimPowerVoltage() { @@ -376,7 +379,7 @@ void ATCA::Timestep(double simt, double simdt) { VECTOR3 V_atterr; //Amplifier - for (i = 0;i < 3;i++) + for (i = 0; i < 3; i++) { V_atterr.data[i] = aea_attitude_error.data[i] * atterrtransformer; } @@ -465,7 +468,7 @@ void ATCA::Timestep(double simt, double simdt) { //INPUT SUMMING AMPLIFIER VECTOR3 V_sum; - for (i = 0;i < 3;i++) + for (i = 0; i < 3; i++) { V_sum.data[i] = (V_atterr.data[i] - V_attrate.data[i] + V_acarate.data[i])*gain_insumamp; Limiter(V_sum.data[i], 12.0); //Limit to 12V @@ -507,7 +510,7 @@ void ATCA::Timestep(double simt, double simdt) { Deadband(V_sum.x, widedb_thres); } - for (i = 0;i < 3;i++) + for (i = 0; i < 3; i++) { V_sum.data[i] *= 4.57; Limiter(V_sum.data[i], 12.0); @@ -517,7 +520,7 @@ void ATCA::Timestep(double simt, double simdt) { Deadband(V_sum.z, narrowdb_thres_y); Deadband(V_sum.y, narrowdb_thres_rp); Deadband(V_sum.x, narrowdb_thres_rp); - for (i = 0;i < 3;i++) + for (i = 0; i < 3; i++) { V_sum.data[i] *= 2.0; } @@ -705,7 +708,7 @@ void ATCA::Timestep(double simt, double simdt) { //PULSE RATIO (DE)MODULATOR - for (i = 0;i < 8;i++) + for (i = 0; i < 8; i++) { if (abs(SummingAmplifierOutput[i]) > 0.5) { @@ -746,13 +749,13 @@ void ATCA::Timestep(double simt, double simdt) { pitchGimbalError = 0.0; rollGimbalError = 0.0; - for (i = 0;i < 8;i++) + for (i = 0; i < 8; i++) { PRMPulse[i] = false; } } - for (i = 0;i < 16;i++) + for (i = 0; i < 16; i++) { ags_jet_request[i] = 0; } @@ -903,19 +906,26 @@ void ATCA::Timestep(double simt, double simdt) { int x = 0; // *** JET DRIVER *** - for (x = 0;x < 16;x++) + for (x = 0; x < 16; x++) { - if ((hasPrimPower && pgns_jet_request[x]) || (hasAbortPower && ags_jet_request[x])) + if (hasPrimPower) { - jet_driver[x] = true; + //For the PGNS, get the duty cycle from the AGC class + jet_driver[x] = lem->agc.GetRCSDutyCycle(LGCThrusterConversion[x]); + } + else if (hasAbortPower && ags_jet_request[x]) + { + //For the AGS, raise RCS thrust level by a minimum impulse firing + jet_driver[x] = lem->GetRCSThrusterLevel(x); + jet_driver[x] += 0.0105 / simdt; + jet_driver[x] = min(1.0, jet_driver[x]); } else { - jet_driver[x] = false; + jet_driver[x] = 0.0; } } - /* THRUSTER TABLE: 0 A1U 8 A3U 1 A1F 9 A3R @@ -932,11 +942,11 @@ void ATCA::Timestep(double simt, double simdt) { // RCS pressurized? // This code should be in a RCS specific class - for (x = 0;x < 16;x++) + for (x = 0; x < 16; x++) { - jet_request[x] = false; + jet_request[x] = 0.0; - if (jet_driver[x]) + if (jet_driver[x] > 0.0) { switch (x) { // SYS A @@ -945,7 +955,7 @@ void ATCA::Timestep(double simt, double simdt) { if (lem->RCS_A_QUAD1_TCA_CB.Voltage() > 24) { lem->RCS_A_QUAD1_TCA_CB.DrawPower(46); - jet_request[x] = true; + jet_request[x] = jet_driver[x]; } break; case 6: // QUAD 2 @@ -953,7 +963,7 @@ void ATCA::Timestep(double simt, double simdt) { if (lem->RCS_A_QUAD2_TCA_CB.Voltage() > 24) { lem->RCS_A_QUAD2_TCA_CB.DrawPower(46); - jet_request[x] = true; + jet_request[x] = jet_driver[x]; } break; case 8: // QUAD 3 @@ -961,7 +971,7 @@ void ATCA::Timestep(double simt, double simdt) { if (lem->RCS_A_QUAD3_TCA_CB.Voltage() > 24) { lem->RCS_A_QUAD3_TCA_CB.DrawPower(46); - jet_request[x] = true; + jet_request[x] = jet_driver[x]; } break; case 14: // QUAD 4 @@ -969,7 +979,7 @@ void ATCA::Timestep(double simt, double simdt) { if (lem->RCS_A_QUAD4_TCA_CB.Voltage() > 24) { lem->RCS_A_QUAD4_TCA_CB.DrawPower(46); - jet_request[x] = true; + jet_request[x] = jet_driver[x]; } break; // SYS B @@ -978,7 +988,7 @@ void ATCA::Timestep(double simt, double simdt) { if (lem->RCS_B_QUAD1_TCA_CB.Voltage() > 24) { lem->RCS_B_QUAD1_TCA_CB.DrawPower(46); - jet_request[x] = true; + jet_request[x] = jet_driver[x]; } break; case 4: // QUAD 2 @@ -986,7 +996,7 @@ void ATCA::Timestep(double simt, double simdt) { if (lem->RCS_B_QUAD2_TCA_CB.Voltage() > 24) { lem->RCS_B_QUAD2_TCA_CB.DrawPower(46); - jet_request[x] = true; + jet_request[x] = jet_driver[x]; } break; case 10: // QUAD 3 @@ -994,7 +1004,7 @@ void ATCA::Timestep(double simt, double simdt) { if (lem->RCS_B_QUAD3_TCA_CB.Voltage() > 24) { lem->RCS_B_QUAD3_TCA_CB.DrawPower(46); - jet_request[x] = true; + jet_request[x] = jet_driver[x]; } break; case 12: // QUAD 4 @@ -1002,156 +1012,21 @@ void ATCA::Timestep(double simt, double simdt) { if (lem->RCS_B_QUAD4_TCA_CB.Voltage() > 24) { lem->RCS_B_QUAD4_TCA_CB.DrawPower(46); - jet_request[x] = true; + jet_request[x] = jet_driver[x]; } break; } } } - //char Buffer[128]; - // *** THRUSTER MAINTENANCE *** x = 0; while (x < 16) { - double power = 0; - // Process jet request list to generate start and stop times. - if (jet_request[x] == 1 && jet_last_request[x] == 0) { - // New fire request - jet_start[x] = simt; - jet_stop[x] = 0; - //sprintf_s(Buffer, "Start %lf %d", jet_start[x], x); - //oapiWriteLog(Buffer); - } - else if (jet_request[x] == 0 && jet_last_request[x] == 1) { - // New stop request - jet_stop[x] = simt; - //Minimum impulse - if (jet_stop[x] < jet_start[x] + 0.013) - { - jet_stop[x] = jet_start[x] + 0.013; - } - //sprintf_s(Buffer, "Stop %lf %d", jet_stop[x], x); - //oapiWriteLog(Buffer); - } - jet_last_request[x] = jet_request[x]; // Keep track of changes - - if (jet_start[x] == 0 && jet_stop[x] == 0) { lem->SetRCSJet(x, false); x++; continue; } // Done - // sprintf(oapiDebugString(),"Jet %d fire %f stop %f",x,jet_start[x],jet_stop[x]); - - //Calculate power level. If the function returns true reset everything to zero - if (CalculateThrustLevel(simt, jet_start[x], jet_stop[x], simdt, power)) - { - power = 0; jet_start[x] = 0; jet_stop[x] = 0; - } - - /*if (power > 0) - { - sprintf_s(Buffer, "%lf %d %lf %lf", simt, x, power, oapiGetTimeAcceleration()); - oapiWriteLog(Buffer); - }*/ - - lem->SetRCSJetLevelPrimary(x, power); + lem->SetRCSJetLevelPrimary(x, jet_request[x]); x++; } } -bool ATCA::CalculateThrustLevel(double simt, double t_start, double t_stop, double simdt, double &power) -{ - //This function calculates the power level from the total impulse of the RCS burn, considering electrical on and off delays - //The delays are taken from the MIT hybrid simulator of the LM, 19ms step delay for engine on, 15ms delay for engine off - //No thrust rise or decay are simulated anymore - if (t_stop == 0) - { - //Easiest case. No stop commanded yet - if (simt - t_start > 0.019) - { - //Even simpler, full thrust for the entire simdt - power = 1.0; - } - else - { - //Thruster on happens this timestep - power = ImpulseOn(simt - t_start, simdt) / simdt; - } - } - else - { - //Engine stop has been commanded - if (simt - t_stop > 0.015) - { - //We are past engine firing. Return true to indicate resetting start/stop times - power = 0.0; - return true; - } - else - { - //Engine stop might happen soon - if (simt - t_start > 0.019) - { - //We are past engine start delay, so use ImpulseOff - power = ImpulseOff(simt - t_stop, simdt) / simdt; - } - else - { - //Here things get more complicated - //Calculate time when engine stop delay is over - double t_stopa = t_stop + 0.015; - //Will this happen in this timestep? - if (t_stopa > simt + simdt) - { - //No, just consider the ImpulseOn function like normal - power = ImpulseOn(simt - t_start, simdt) / simdt; - } - else - { - //Use ImpulseOn, but with time biased to cut off the engine on time - power = ImpulseOn(simt - t_start, t_stopa - simt) / simdt; - } - } - } - } - return false; -} - -double ATCA::ImpulseOn(double t0, double dt) -{ - if (t0 + dt < 0.019) - { - //No thrust - return 0.0; - } - else if (t0 > 0.019) - { - //Full thrust for the entire dt - return dt; - } - else - { - //t0 is before thrust on - return dt - (0.019 - t0); - } -} - -double ATCA::ImpulseOff(double t0, double dt) -{ - if (t0 > 0.015) - { - //Thrust off - return 0.0; - } - else if (t0 + dt < 0.015) - { - //Thrust still on - return dt; - } - else - { - //Thruster off mid step - return 0.015 - t0; - } -} - void ATCA::SystemTimestep(double simdt) { if (lem->SCS_ATCA_CB.IsPowered() && lem->CDR_SCS_ATCA_CB.IsPowered() && !lem->scca2.GetK12() && !lem->ModeControlPGNSSwitch.IsDown()) @@ -1169,40 +1044,6 @@ void ATCA::SystemTimestep(double simdt) } } -// Process thruster commands from LGC -void ATCA::ProcessLGC(int ch, int val){ - if(!hasPrimPower){ val = 0; } // If not in primary mode, force jets off (so jets will switch off at programmed times) - // When in primary, thruster commands are passed from LGC to jets. - switch(ch){ - case 05: - LMChannelValue5 ch5; - ch5.Value = val; - if(ch5.Bits.B4U != 0){ pgns_jet_request[12] = 1; }else{ pgns_jet_request[12] = 0; } - if(ch5.Bits.A4D != 0){ pgns_jet_request[15] = 1; }else{ pgns_jet_request[15] = 0; } - if(ch5.Bits.A3U != 0){ pgns_jet_request[8] = 1; }else{ pgns_jet_request[8] = 0; } - if(ch5.Bits.B3D != 0){ pgns_jet_request[11] = 1; }else{ pgns_jet_request[11] = 0; } - if(ch5.Bits.B2U != 0){ pgns_jet_request[4] = 1; }else{ pgns_jet_request[4] = 0; } - if(ch5.Bits.A2D != 0){ pgns_jet_request[7] = 1; }else{ pgns_jet_request[7] = 0; } - if(ch5.Bits.A1U != 0){ pgns_jet_request[0] = 1; }else{ pgns_jet_request[0] = 0; } - if(ch5.Bits.B1D != 0){ pgns_jet_request[3] = 1; }else{ pgns_jet_request[3] = 0; } - break; - case 06: - LMChannelValue6 ch6; - ch6.Value = val; - if(ch6.Bits.B3A != 0){ pgns_jet_request[10] = 1; }else{ pgns_jet_request[10] = 0; } - if(ch6.Bits.B4F != 0){ pgns_jet_request[13] = 1; }else{ pgns_jet_request[13] = 0; } - if(ch6.Bits.A1F != 0){ pgns_jet_request[1] = 1; }else{ pgns_jet_request[1] = 0; } - if(ch6.Bits.A2A != 0){ pgns_jet_request[6] = 1; }else{ pgns_jet_request[6] = 0; } - if(ch6.Bits.B2L != 0){ pgns_jet_request[5] = 1; }else{ pgns_jet_request[5] = 0; } - if(ch6.Bits.A3R != 0){ pgns_jet_request[9] = 1; }else{ pgns_jet_request[9] = 0; } - if(ch6.Bits.A4R != 0){ pgns_jet_request[14] = 1; }else{ pgns_jet_request[14] = 0; } - if(ch6.Bits.B1L != 0){ pgns_jet_request[2] = 1; }else{ pgns_jet_request[2] = 0; } - break; - default: - sprintf(oapiDebugString(),"ATCA::ProcessLGC: Bad channel %o",ch); - } -} - double ATCA::PRMOnTime(double X) { //X is normalized voltage (0 to 1) diff --git a/Orbitersdk/samples/ProjectApollo/src_lm/lmscs.h b/Orbitersdk/samples/ProjectApollo/src_lm/lmscs.h index 74ce11d2db..ab97aab090 100644 --- a/Orbitersdk/samples/ProjectApollo/src_lm/lmscs.h +++ b/Orbitersdk/samples/ProjectApollo/src_lm/lmscs.h @@ -67,7 +67,6 @@ class ATCA { double GetMinus6VDCSupplyVoltage(); void Timestep(double simt, double simdt); // Timestep void SystemTimestep(double simdt); - void ProcessLGC(int ch, int val); // To process LGC commands void SaveState(FILEHANDLE scn); void LoadState(FILEHANDLE scn); @@ -88,12 +87,9 @@ class ATCA { h_HeatLoad *ATCAHeat; int lgc_err_x,lgc_err_y,lgc_err_z; // LGC attitude error counters int lgc_err_ena; // LGC error counter enabled - bool pgns_jet_request[16]; bool ags_jet_request[16]; - bool jet_driver[16]; - int jet_request[16]; // Jet request list - int jet_last_request[16]; // Jet request list at last timestep - double jet_start[16],jet_stop[16]; // RCS jet start/stop times + double jet_driver[16]; // Required RCS duty cycle + double jet_request[16]; // Jet request list protected: double PRMOnTime(double X); @@ -101,9 +97,6 @@ class ATCA { bool PRMTimestep(int n, double simdt, double t_on, double t_off); void Limiter(double &val, double lim); void Deadband(double &val, double thres); - double ImpulseOn(double t0, double dt); - double ImpulseOff(double t0, double dt); - bool CalculateThrustLevel(double simt, double t_start, double t_stop, double simdt, double &power); VECTOR3 aea_attitude_error; VECTOR3 aca_rates; diff --git a/Orbitersdk/samples/ProjectApollo/src_sys/apolloguidance.cpp b/Orbitersdk/samples/ProjectApollo/src_sys/apolloguidance.cpp index a4290b72fc..6e06c91426 100644 --- a/Orbitersdk/samples/ProjectApollo/src_sys/apolloguidance.cpp +++ b/Orbitersdk/samples/ProjectApollo/src_sys/apolloguidance.cpp @@ -78,6 +78,18 @@ ApolloGuidance::ApolloGuidance(SoundLib &s, DSKY &display, IMU &im, CDU &sc, CDU TrackerAlarm = false; GimbalLockAlarm = false; + for (i = 0; i < 16; i++) + { + AccumulatedThrust[i] = 0; + ThrustOnDelayCounter[i] = 0; + ThrustOffDelayCounter[i] = 0; + RCSDutyCycle[i] = 0.0; + } + RCSCycleCounter = 0; + ThrustOnDelay = 16; //In units of 1/1600 seconds. Should be overloaded in CMC and LGC constructor. + ThrustOffDelay = 16; //In units of 1/1600 seconds.Should be overloaded in CMC and LGC constructor. + LastRCSTime = 0.0; + // // Virtual AGC. // @@ -959,6 +971,140 @@ int16_t ApolloGuidance::ConvertDecimalToAGCOctal(double x, bool highByte) return i; } +void ApolloGuidance::InitRCSActivity() +{ + for (int i = 0; i < 16; i++) + { + AccumulatedThrust[i] = 0; + } + + RCSCycleCounter = 0; +} + +void ApolloGuidance::MonitorRCSActivity() +{ + bool RCSOn; + + for (int i = 0; i < 16; i++) + { + if (i < 8) + { + RCSOn = (OutputChannel[05] >> i) & 1; + } + else + { + RCSOn = (OutputChannel[06] >> (i - 8)) & 1; + } + + //If RCS is commanded on count up the delay counter. The second condition forces it to count to conclusion. + if (RCSOn || (ThrustOnDelayCounter[i] > 0 && ThrustOnDelayCounter[i] < ThrustOnDelay)) + { + ThrustOnDelayCounter[i]++; + } + + //If ThrustOnDelayCounter is zero we can skip this + if (ThrustOnDelayCounter[i] > 0) + { + //Similar to ThrustOnDelayCounter, ThrustOffDelayCounter is being forced to count to conclusion + if (!RCSOn || (ThrustOffDelayCounter[i] > 0 && ThrustOffDelayCounter[i] < ThrustOffDelay)) + { + ThrustOffDelayCounter[i]++; + } + } + + //If ThrustOffDelayCounter has reached ThrustOffDelay then we reset everything + if (ThrustOffDelayCounter[i] >= ThrustOffDelay) + { + ThrustOnDelayCounter[i] = 0; + ThrustOffDelayCounter[i] = 0; + } + else + { + //If ThrustOnDelayCounter has reached ThrustOnDelay then we have thrust + if (ThrustOnDelayCounter[i] >= ThrustOnDelay) + { + AccumulatedThrust[i]++; + } + } + + /*if (RCSOn) + { + //On command + if (ThrustOnDelayCounter[i] >= ThrustOnDelay) + { + //Thruster on + AccumulatedThrust[i]++; + } + else + { + //Thruster starting up + ThrustOnDelayCounter[i]++; + ThrustOffDelayCounter[i] = 0; + } + } + else + { + //Off command + if (ThrustOnDelayCounter[i] >= ThrustOnDelay) + { + if (ThrustOffDelayCounter[i] >= ThrustOffDelay) + { + //Reset + ThrustOnDelayCounter[i] = ThrustOffDelayCounter[i] = 0; + } + else + { + //Thruster still on + ThrustOffDelayCounter[i]++; + AccumulatedThrust[i]++; + } + } + else + { + //Reset + ThrustOnDelayCounter[i] = 0; + } + }*/ + } + + RCSCycleCounter++; +} + +void ApolloGuidance::CalculateRCSDutyCycle() +{ + for (int i = 0; i < 16; i++) + { + if (RCSCycleCounter > 0) + { + RCSDutyCycle[i] = (double)AccumulatedThrust[i] / RCSCycleCounter; + } + else + { + //In the unlikely case that no cycles were done (requires at least 160 Hz at 0.1x) calculate the duty cycle from current state + if (ThrustOnDelayCounter[i] >= ThrustOnDelay && ThrustOffDelayCounter[i] < ThrustOffDelay) + { + RCSDutyCycle[i] = 1.0; + } + else + { + RCSDutyCycle[i] = 0.0; + } + } + } +} + +void ApolloGuidance::ResetRCSDutyCycle() +{ + for (int i = 0; i < 16; i++) + { + RCSDutyCycle[i] = 0.0; + } +} + +double ApolloGuidance::GetRCSDutyCycle(int i) +{ + return RCSDutyCycle[i]; +} // // Virtual AGC functions. diff --git a/Orbitersdk/samples/ProjectApollo/src_sys/apolloguidance.h b/Orbitersdk/samples/ProjectApollo/src_sys/apolloguidance.h index a353d8e968..66ffe35b70 100644 --- a/Orbitersdk/samples/ProjectApollo/src_sys/apolloguidance.h +++ b/Orbitersdk/samples/ProjectApollo/src_sys/apolloguidance.h @@ -320,6 +320,9 @@ class ApolloGuidance: public Runnable bool GetTrackerAlarm() { return TrackerAlarm; } bool GetGimbalLockAlarm() { return GimbalLockAlarm; } + // RCS activity to RCS control electronics + double GetRCSDutyCycle(int i); + /// /// \brief Interrupts /// @@ -375,6 +378,19 @@ class ApolloGuidance: public Runnable int16_t ConvertDecimalToAGCOctal(double x, bool highByte); + // + // Functions to keep track of RCS activity + // + + // Reset RCS activity counters (run before AGC timestep) + void InitRCSActivity(); + // To keep track of channel 5 and 6 activity (run within AGC timestep) + void MonitorRCSActivity(); + // Calculates what percentage of a timestep the RCS should be fired (run after AGC timestep) + void CalculateRCSDutyCycle(); + // Run when AGC is powered off + void ResetRCSDutyCycle(); + /// /// \brief Are we running the reset program? /// @@ -475,6 +491,16 @@ class ApolloGuidance: public Runnable bool ProgAlarm; bool TrackerAlarm; bool GimbalLockAlarm; + + // RCS activity variables + int ThrustOnDelayCounter[16]; + int ThrustOffDelayCounter[16]; + int AccumulatedThrust[16]; + int RCSCycleCounter; + int ThrustOnDelay; + int ThrustOffDelay; + double RCSDutyCycle[16]; + double LastRCSTime; }; //