// ==============================================================
// ORBITER MODULE: Raytheon CEV
// by Eric Winchester
//
// Raytheon.cpp
// Reference implementation of Boeing CEV vessel class module
// ==============================================================
#define STRICT
#define ORBITER_MODULE
#include "Raytheon.h"
// ==============================================================
// Specialised vessel class RaytheonCEV
// ==============================================================
// --------------------------------------------------------------
// Constructor
// --------------------------------------------------------------
RaytheonCEV::RaytheonCEV (OBJHANDLE hObj, int fmodel)
: VESSEL2 (hObj, fmodel)
{
mode = 0;
//ofs = _V(0,0,0);
SetConfigOrbit();
tex_main = oapiRegisterExhaustTexture ("RaytheonCEV//omsexhaust");
hCm = oapiLoadMeshGlobal ("RaytheonCEV//cm");
hPm = oapiLoadMeshGlobal ("RaytheonCEV//pm");
hDrogue = oapiLoadMeshGlobal ("RaytheonCEV//cm_droguedeployed");
hMain = oapiLoadMeshGlobal ("RaytheonCEV//cm_maindeployed");
}
// ================================================== ============
// Airfoil coefficient functions
// Return lift, moment and zero-lift drag coefficients as a
// function of angle of attack (alpha or beta)
// ================================================== ============
void VLiftCoeff (double aoa, double M, double Re, double *cl, double *cm, double *cd)
{
static const double step = RAD*30.0;
static const double istep = 1.0/step;
static const int nabsc = 13;
// Angle of attack -180 -150 -120 -90 -60 -30 0 30 60 90 120 150 180
static const double CL[nabsc] = { 0, -0.12, -0.1, 0, 0, 0, 0, 0, 0, 0, 0.1, 0.12, 0};
static const double CM[nabsc] = { 0, -0.0002,-0.0004, -0.0004,-0.0003,-0.0002, 0, 0.0002, 0.0003, 0.0004, 0.0004,0.0002, 0};
// lift and moment coefficients from -180 to 180 in 30 degree steps.
aoa += PI;
int idx = max (0, min (11, (int)(aoa*istep)));
double d = aoa*istep - idx;
*cl = CL[idx] + (CL[idx+1]-CL[idx])*d;
*cm = ( CM[idx] + (CM[idx+1]-CM[idx])*d ) / 10;
*cd = 0.25 + oapiGetInducedDrag (*cl, 1.27, 0.3);
}
// 2. horizontal lift component (vertical stabiliser and body)
void HLiftCoeff (double beta, double M, double Re, double *cl, double *cm, double *cd)
{
static const double step = RAD*30;
static const double istep = 1.0/step;
static const int nabsc = 13;
static const double CL[nabsc] = { 0, -0.1, -0.1, 0, 0, 0, 0, 0, 0, 0, 0.1, 0.1, 0};
beta += PI;
int idx = max (0, min (11, (int)(beta*istep)));
double d = beta*istep - idx;
*cl = CL[idx] + (CL[idx+1]-CL[idx])*d;
*cm = 0.0;
*cd = 0.25 + oapiGetInducedDrag (*cl, 1.27, 0.3);
}
void VLiftCoeff_drogue (double aoa, double M, double Re, double *cl, double *cm, double *cd)
{
static const double step = RAD*15.0;
static const double istep = 1.0/step;
static const int nabsc = 25;
// static const double CL[nabsc] = {0.1, 0.17, 0.2, 0.2, 0.17, 0.1, 0, -0.11, -0.24, -0.3, -0.3, -0.3, -0.02, 0.6355, 0.63, 0.46, 0.28, 0.13, 0.0, -0.16, -0.26, -0.29, -0.24, -0.1, 0.1};
static const double CL[nabsc] = {0.05, 0.08, 0.09, 0.09, 0.08, 0.05, 0.00, -0.05, -0.11, -0.18, -0.24, -0.24, -0.01, 0.30, 0.30, 0.22, 0.13, 0.06, 0.00, -0.08, -0.12, -0.14, -0.11, -0.05, 0.05};
static const double CM[nabsc] = { 0, 0, 0, 0, 0, 0, 0, 0, 0,0.004,0.008, 0.005,0.0024, 0,-0.0024,-0.0014, 0, 0, 0, 0, 0, 0, 0, 0, 0};
// lift and moment coefficients from -180 to 180 in 15 degree steps.
// This uses a documented lift slope of 0.0437/deg, everything else is rather ad-hoc
aoa += PI;
int idx = max (0, min (23, (int)(aoa*istep)));
double d = aoa*istep - idx;
*cl = CL[idx] + (CL[idx+1]-CL[idx])*d;
*cm = CM[idx] + (CM[idx+1]-CM[idx])*d;
*cd = 1 + oapiGetInducedDrag (*cl, 1.5, 0.3);
}
void VLiftCoeff_mainchute (double aoa, double M, double Re, double *cl, double *cm, double *cd)
{
static const double step = RAD*15.0;
static const double istep = 1.0/step;
static const int nabsc = 25;
// static const double CL[nabsc] = {0.1, 0.17, 0.2, 0.2, 0.17, 0.1, 0, -0.11, -0.24, -0.3, -0.3, -0.3, -0.02, 0.6355, 0.63, 0.46, 0.28, 0.13, 0.0, -0.16, -0.26, -0.29, -0.24, -0.1, 0.1};
static const double CL[nabsc] = {0.0, 0.00, 0.00, 0.00, 0.00, 0.00, 0.00, -0.00, -0.00, -0.00, -0.00, -0.00, 0.5, 2.00, 2.50, 0.22, 0.00, 0.00, 0.00, -0.00, -0.00, -0.00, -0.00, -0.00, 0.00};
static const double CM[nabsc] = { 0, 0, 0, 0, 0, 0, 0, 0, 0,0.004,0.008, 0.005,0.0024, 0,-0.0024,-0.0014, 0, 0, 0, 0, 0, 0, 0, 0, 0};
// lift and moment coefficients from -180 to 180 in 15 degree steps.
// This uses a documented lift slope of 0.0437/deg, everything else is rather ad-hoc
aoa += PI;
int idx = max (0, min (23, (int)(aoa*istep)));
double d = aoa*istep - idx;
*cl = 4 * (CL[idx] + (CL[idx+1]-CL[idx])*d); // Multiplied to make up for reduced area
*cm = 0.5*(CM[idx] + (CM[idx+1]-CM[idx])*d);
*cd = 0.7 + oapiGetInducedDrag (*cl, 15, 0.5);
}
// ==============================================================
// API interface
// ==============================================================
DLLCLBK VESSEL *ovcInit (OBJHANDLE hvessel, int flightmodel)
{
return new RaytheonCEV (hvessel, flightmodel);
}
// --------------------------------------------------------------
// Vessel cleanup
// --------------------------------------------------------------
DLLCLBK void ovcExit (VESSEL *vessel)
{
if (vessel) delete (Raytheon*)vessel;
}
// Set the capabilities of the vessel class
DLLCLBK void ovcSetClassCaps (VESSEL *vessel, FILEHANDLE cfg)
{
((RaytheonCEV *) vessel)-> SetConfigOrbit();
}
//===============================
// Read status from scenario file
//===============================
void RaytheonCEV::clbkLoadStateEx (FILEHANDLE scn, void *vs)
{
char *line;
int value;
while (oapiReadScenario_nextline (scn, line)) {
if (!strnicmp (line, "MODE", 4)) {
sscanf (line+4, "%d", &value);
mode = (int) value;
}
else {
ParseScenarioLineEx (line, vs);
// unrecognised option - pass to Orbiter's generic parser
}
}
switch (mode) {
case 0:
case 1:
SetConfigOrbit();
break;
case 2:
SetConfigReentry();
break;
case 3:
SetConfigDrogue();
break;
case 4:
case 5:
SetConfigChute();
break;
case 6:
SetConfigLanded();
break;
}
}
void RaytheonCEV::clbkSaveState (FILEHANDLE scn)
{ // default vessel parameters
SaveDefaultState (scn);
// custom parameters
oapiWriteScenario_int (scn, "MODE", mode);
}
void RaytheonCEV::clbkPostStep (double simt, double simdt, double mjd)
{
// sprintf (oapiDebugString(), "Mode= %d", mode);
if (mode > 2) {
if (oapiGetTimeAcceleration() > 10) // Slow down
oapiSetTimeAcceleration(10);
// AddForce(_V(0,0,-1000), _V(0,3,0));
if ((mode == 4 && GetAirspeed() < 50)) { // fully deploy chute
CreateAirfoil (LIFT_VERTICAL, _V(0,5,-1), VLiftCoeff_mainchute, 16, 0, 0.6);
mode = 5;
}
// Check if we shall cut the chute
if (GetAltitude() < 3.5 && mode <6 ) {
// Create the chute as an individual object
VESSELSTATUS vs;
GetStatus (vs);
vs.flag[0] = 3;
VECTOR3 ofs = {0,0,2};
Local2Rel (ofs, vs.rpos);
VECTOR3 vel = _V(0,30,-30);
VECTOR3 rofs, rvel = {vs.rvel.x, vs.rvel.y, vs.rvel.z};
Local2Rel (ofs, vs.rpos);
GlobalRot (vel, rofs);
vs.rvel.x = rvel.x+rofs.x;
vs.rvel.y = rvel.y+rofs.y;
vs.rvel.z = rvel.z+rofs.z;
char name[256];
strcpy (name, GetName()); strcat (name, "-Chute");
oapiCreateVessel (name, "RaytheonCEV\\Mainchute", vs);
SetConfig6_Landed();
}
}
}
void RaytheonCEV::clbkDrawHUD(void)
{
// draw the default HUD
VESSEL2::clbkDrawHUD (mode, hps, hDC);
//Draw Equivalent airspeed & pressure altitude
if(GetAtmPressure() > 0.0)
{
int d = hps->Markersize/2;
int cx = hps->CX, cy = hps->CY;
char pszBuffer[40];
int bx = 0.5 * cx;
const double EAS_EXP = 2.0/7.0;
const double P0 = 1.01325E6;
double fEAS = 661.48 * sqrt(5.0 * GetAtmPressure()/ATMP * (pow(GetDynPressure() / GetAtmPressure() + 1, EAS_EXP) - 1.0));
sprintf(pszBuffer, "%6.1f KEAS", fEAS);
TextOut(hDC, bx, cy - d, pszBuffer, 11);
}
if (GetAtmPressure() > 7000.0) // About 60,000'; use pressure altitude
{
int d = hps->Markersize/2;
int cx = hps->CX, cy = hps->CY;
char pszBuffer[40];
int bx = 0.5 * cx;
const double EAS_EXP = 2.0/7.0;
const double P0 = 1.01325E6;
bx = 0.5 * (cx + hps->W) - d * 8;
double fHp = (1.0 - pow(GetAtmPressure()/ATMP, 0.190263)) * (288.15/0.00198122);
long H_press = (long)(fHp);
H_press = H_press - H_press % 50;
sprintf(pszBuffer, "%6d' ", H_press);
TextOut(hDC, bx, cy - d, pszBuffer, 9);
} else { // Do inertial altitude instead
int d = hps->Markersize/2;
int cx = hps->CX, cy = hps->CY;
char pszBuffer[40];
int bx = 0.5 * cx;
const double EAS_EXP = 2.0/7.0;
const double P0 = 1.01325E6;
bx = 0.5 * (cx + hps->W) - d * 8;
double fIalt = GetAltitude()/0.3048;
long I_Alt = (long)(fIalt);
I_Alt = I_Alt - I_Alt % 50;
sprintf(pszBuffer, "%6d' I", I_Alt);
TextOut(hDC, bx, cy - d, pszBuffer, 9);
}
//Draw Radar altitude
if(GetAltitude() < 2500.0 * 0.3048)
{
int d = hps->Markersize/2;
int cx = hps->CX, cy = hps->CY;
char pszBuffer[40];
int bx = 0.5 * (cx + hps->W) - d * 8;
const double GEAR_Y = -1.35;
sprintf(pszBuffer, "%6dR", static_cast<long>((GetAltitude() + GEAR_Y)/0.3048));
TextOut(hDC, bx, cy + d, pszBuffer, 7);
}
if(GetThrusterLevel(th_LH2)> 0.0 && GetPropellantMass(ph_LH2) > 0.0)
{
int d = hps->Markersize/2;
int cx = hps->CX, cy = hps->CY;
char pszBuffer[40];
int bx = 0.5 * (cx + hps->W);
double t_co = GetPropellantMass(ph_LH2)/GetPropellantFlowrate(ph_LH2);
sprintf(pszBuffer, "CO %02d:%02d", static_cast<long>(t_co/60.0), static_cast<long>(fmod(t_co, 60.0)));
TextOut(hDC, bx, 80.0, pszBuffer, strlen(pszBuffer));
}
//Draw G-Meter
// if (Vect[0] > 0.0) {
int d = hps->Markersize/2;
int cx = hps->CX, cy = hps->CY;
char pszBuffer[40];
int bx = 0.5 * cx;
VECTOR3 ForceVec, WeightVec;
GetForceVector(ForceVec);
GetWeightVector(WeightVec);
ForceVec -= WeightVec;
G_level = sqrt(pow(ForceVec.x,2)+pow(ForceVec.y,2)+pow(ForceVec.z,2)) / (9.81*GetMass());
sprintf(pszBuffer, " %.2f G", G_level);
TextOut(hDC, bx, cy + d, pszBuffer, strlen(pszBuffer));
// }
}
void RaytheonCEV::SetConfigOrbit(void)
{
SetSize (2);
SetEmptyMass (CEV_EMPTY_MASS);
SetPMI (_V(8.06,8.07,2.08));
SetCrossSections (_V(24.24,24.28,12.74));
SetDockParams (_V(0,0,2.411195), _V(0,0,1), _V(0,1,0));
SetCameraOffset (_V(0,0,2.03));
SetThrusters_Orbit();
mode = 1;
ReloadMeshes();
}
void RaytheonCEV::SetConfigReentry(void)
{
SetSize (2);
SetEmptyMass (CM_EMPTY_MASS);
SetPMI (_V(2.61,2.71,2));
SetCW (0.2, 0.5, 1, 1);
SetCrossSections (_V(15.74,16.03,12.56));
SetRotDrag (_V(0.3,0.3,0.2));
SetTouchdownPoints(_V(0,1.52,-2.19),_V(-1.06,-1.10,-2.19),_V(1.06,1.096,-2.19));
SetSurfaceFrictionCoeff (0.2, 0.2);
CreateAirfoil (LIFT_VERTICAL, _V(0, 0.01,0.1), VLiftCoeff, 5.5, 0, 1.27);
CreateAirfoil (LIFT_HORIZONTAL, _V(0, 0, 0.01), HLiftCoeff, 5.5, 0, 1.27);
SetADCtrlMode (7);
SetThrusters_Reentry();
mode = 2;
ReloadMeshes();
}
void RaytheonCEV::SetConfigDrogue(void)
{
SetSize (2);
SetEmptyMass (CM_EMPTY_MASS);
SetPMI (_V(2.61,2.71,2));
SetCW (0.5, 0.5, 1, 1);
SetCrossSections (_V(15.74,16.03,12.56));
SetRotDrag (_V(0.3,0.3,0.2));
SetTouchdownPoints(_V(0,1.52,-2.19),_V(-1.06,-1.10,-2.19),_V(1.06,1.096,-2.19));
SetSurfaceFrictionCoeff (0.2, 0.2);
CreateAirfoil (LIFT_VERTICAL, _V(0,1,-0.5), VLiftCoeff_drogue, 7, 0, 1.4);
CreateAirfoil (LIFT_HORIZONTAL, _V(0,1,-0.5), HLiftCoeff, 7, 0, 1.4);
ClearThrusterDefinitions();
mode = 3;
ReloadMeshes();
}
void RaytheonCEV::SetConfigChute(void)
{
SetSize (18);
SetEmptyMass (CM_EMPTY_MASS);
SetPMI (_V(2.61,2.71,2));
SetCW (0.5, 0.5, 1, 1);
SetCrossSections (_V(15.74,16.03,12.56));
SetRotDrag (_V(0.3,0.3,0.2));
SetTouchdownPoints(_V(0,1.52,-2.19),_V(-1.06,-1.10,-2.19),_V(1.06,1.096,-2.19));
SetSurfaceFrictionCoeff (0.2, 0.2);
CreateAirfoil (LIFT_VERTICAL, _V(0,5,-1), VLiftCoeff_mainchute, 16, 0, 0.6);
CreateAirfoil (LIFT_HORIZONTAL, _V(0,5,-1), HLiftCoeff, 16, 0, 0.6);
ClearThrusterDefinitions();
mode = 4;
ReloadMeshes();
}
void RaytheonCEV::SetConfigLanded(void)
{
SetSize (2.25);
SetEmptyMass (CM_EMPTY_MASS);
SetPMI (_V(2.61,2.71,2));
ClearAirfoilDefinitions();
SetTouchdownPoints(_V(0,1.52,-2.19),_V(-1.06,-1.10,-2.19),_V(1.06,1.096,-2.19));
SetSurfaceFrictionCoeff (0.3, 0.3);
SetThrustersLanded();
mode = 5;
ReloadMeshes();
}
void RaytheonCEV::ReloadMeshes(void)
{
ClearMeshes();
SetCameraOffset (_V(0,0,2.41)); // docking port
AddMesh (hCm); // Always reender the CM
switch (mode) {
case 0:
case 1: // Orbit config
AddMesh (hPm);
break;
case 2: // Reentry config
case 3: // Drogue config
AddMesh (hDrogue);
break;
case 4: // main
AddMesh (hMain);
break;
case 5:
}
}
int RaytheonCEV::clbkConsumeBufferedKey (DWORD key, bool down, char *kstate)
{
if (!down) return 0; // only process keydown events
// VESSEL *sh = (VESSEL*)vessel;
if (KEYMOD_SHIFT (kstate)) {
} else { // unmodified keys
switch (key) {
case OAPI_KEY_J: // Jettison service module
if ( mode < 2) {
if (oapiGetTimeAcceleration() > 10) // Slow down
oapiSetTimeAcceleration(10);
// Create Ressource Module as an individual object
VESSELSTATUS vs;
GetStatus (vs);
vs.flag[0] = 3;
VECTOR3 ofs = {0,0,0};
Local2Rel (ofs, vs.rpos);
VECTOR3 vel = _V(0,0,-0.2);
VECTOR3 rofs, rvel = {vs.rvel.x, vs.rvel.y, vs.rvel.z};
Local2Rel (ofs, vs.rpos);
GlobalRot (vel, rofs);
vs.rvel.x = rvel.x+rofs.x;
vs.rvel.y = rvel.y+rofs.y;
vs.rvel.z = rvel.z+rofs.z;
char name[256]= {"aaa"};
strcpy (name, GetName()); strcat (name, "-PM");
oapiCreateVessel (name, "RaytheonCEV\\PM", vs);
SetConfig2_Reentry();
}
return 1;
// Deploy drogue and chute
case OAPI_KEY_C:
double speed;
char name[256];
OBJHANDLE hvessel;
if (GetAltitude() > 20000)
return 1; // dont open the chute above 40 km
strcpy (name, GetName());
hvessel=oapiGetVesselByName(name);
oapiGetAirspeed(hvessel, &speed);
if (( mode == 2) && (speed < 1000)) {
SetConfig3_Drogue();
return 1;
}
if ((mode == 3) && (speed < 120)) {
SetConfig4_Chute();
// Create the drogue as an individual object
//VESSELSTATUS vs;
//GetStatus (vs);
//vs.flag[0] = 3;
//VECTOR3 ofs = {0,0,0};
//Local2Rel (ofs, vs.rpos);
//VECTOR3 vel = _V(0,0,-2);
//VECTOR3 rofs, rvel = {vs.rvel.x, vs.rvel.y, vs.rvel.z};
//Local2Rel (ofs, vs.rpos);
//GlobalRot (vel, rofs);
//vs.rvel.x = rvel.x+rofs.x;
//vs.rvel.y = rvel.y+rofs.y;
//vs.rvel.z = rvel.z+rofs.z;
//char name[256];
//strcpy (name, GetName()); strcat (name, "-Drogue");
//oapiCreateVessel (name, "RaytheonCEV\\CEV2-Drogue", vs);
//}
//return 1;
//case OAPI_KEY_E:
// do_eva();
//return 1;
//case OAPI_KEY_S: // Deploy solar panels
// if (mode < 2) { // use while in orbit mode only
// solar = 1;
// ReloadMeshes();
}
return 1;
} // end switch
} // end else
return 0;
}
//===============================
// Create thrusters for the resource module
// ===============================
void RaytheonCEV::SetThrusters_Orbit()
{
ClearThrusterDefinitions();
ClearPropellantResources();
ph_pm = CreatePropellantResource (MAX_PM_FUEL); // PM propellant
SetDefaultPropellantResource(ph_pm);
THRUSTER_HANDLE th_main;
th_main = CreateThruster (_V(-0.7723747, 0, -4.94) _V(0,0, 1), MAX_MAIN_THRUST, ph_pm, ISP);
AddExhaust (th_main, 3.0, 1.0, tex_main);
th_rcs[ 0] = CreateThruster (_V( 1,0, 3), _V(0, 1,0), MAX_RCS_THRUST, ph_pm, ISP);
th_rcs[ 1] = CreateThruster (_V( 1,0, 3), _V(0,-1,0), MAX_RCS_THRUST, ph_pm, ISP);
th_rcs[ 2] = CreateThruster (_V(-1,0, 3), _V(0, 1,0), MAX_RCS_THRUST, ph_pm, ISP);
th_rcs[ 3] = CreateThruster (_V(-1,0, 3), _V(0,-1,0), MAX_RCS_THRUST, ph_pm, ISP);
th_rcs[ 4] = CreateThruster (_V( 1,0,-3), _V(0, 1,0), MAX_RCS_THRUST, ph_pm, ISP);
th_rcs[ 5] = CreateThruster (_V( 1,0,-3), _V(0,-1,0), MAX_RCS_THRUST, ph_pm, ISP);
th_rcs[ 6] = CreateThruster (_V(-1,0,-3), _V(0, 1,0), MAX_RCS_THRUST, ph_pm, ISP);
th_rcs[ 7] = CreateThruster (_V(-1,0,-3), _V(0,-1,0), MAX_RCS_THRUST, ph_pm, ISP);
th_rcs[ 8] = CreateThruster (_V( 1,0, 3), _V(-1,0,0), MAX_RCS_THRUST, ph_pm, ISP);
th_rcs[ 9] = CreateThruster (_V(-1,0, 3), _V( 1,0,0), MAX_RCS_THRUST, ph_pm, ISP);
th_rcs[10] = CreateThruster (_V( 1,0,-3), _V(-1,0,0), MAX_RCS_THRUST, ph_pm, ISP);
th_rcs[11] = CreateThruster (_V(-1,0,-3), _V( 1,0,0), MAX_RCS_THRUST, ph_pm, ISP);
th_rcs[12] = CreateThruster (_V( 0,0,-3), _V(0,0, 1), MAX_RCS_THRUST, ph_pm, ISP);
th_rcs[13] = CreateThruster (_V( 0,0, 3), _V(0,0,-1), MAX_RCS_THRUST, ph_pm, ISP);
th_group[0] = th_rcs[0];
th_group[1] = th_rcs[2];
th_group[2] = th_rcs[5];
th_group[3] = th_rcs[7];
CreateThrusterGroup (th_group, 4, THGROUP_ATT_PITCHUP);
th_group[0] = th_rcs[1];
th_group[1] = th_rcs[3];
th_group[2] = th_rcs[4];
th_group[3] = th_rcs[6];
CreateThrusterGroup (th_group, 4, THGROUP_ATT_PITCHDOWN);
th_group[0] = th_rcs[0];
th_group[1] = th_rcs[4];
th_group[2] = th_rcs[3];
th_group[3] = th_rcs[7];
CreateThrusterGroup (th_group, 4, THGROUP_ATT_BANKLEFT);
th_group[0] = th_rcs[1];
th_group[1] = th_rcs[5];
th_group[2] = th_rcs[2];
th_group[3] = th_rcs[6];
CreateThrusterGroup (th_group, 4, THGROUP_ATT_BANKRIGHT);
th_group[0] = th_rcs[0];
th_group[1] = th_rcs[4];
th_group[2] = th_rcs[2];
th_group[3] = th_rcs[6];
CreateThrusterGroup (th_group, 4, THGROUP_ATT_UP);
th_group[0] = th_rcs[1];
th_group[1] = th_rcs[5];
th_group[2] = th_rcs[3];
th_group[3] = th_rcs[7];
CreateThrusterGroup (th_group, 4, THGROUP_ATT_DOWN);
th_group[0] = th_rcs[8];
th_group[1] = th_rcs[11];
CreateThrusterGroup (th_group, 2, THGROUP_ATT_YAWLEFT);
th_group[0] = th_rcs[9];
th_group[1] = th_rcs[10];
CreateThrusterGroup (th_group, 2, THGROUP_ATT_YAWRIGHT);
th_group[0] = th_rcs[8];
th_group[1] = th_rcs[10];
CreateThrusterGroup (th_group, 2, THGROUP_ATT_LEFT);
th_group[0] = th_rcs[9];
th_group[1] = th_rcs[11];
CreateThrusterGroup (th_group, 2, THGROUP_ATT_RIGHT);
CreateThrusterGroup (th_rcs+12, 1, THGROUP_ATT_FORWARD);
CreateThrusterGroup (th_rcs+13, 1, THGROUP_ATT_BACK);
//=======================================
// Create thrusters for the capsule alone
// ======================================
void RaytheonCEV::SetThrustersReentry()
{
ClearThrusterDefinitions();
ClearPropellantResources();
ph_CM = CreatePropellantResource (MAX_CM_FUEL); // CM propellant
SetDefaultPropellantResource(ph_CM);
th_rcs[ 0] = CreateThruster (_V( 1,0, 3), _V(0, 1,0), MAX_RCS_THRUST, ph_pm, ISP);
th_rcs[ 1] = CreateThruster (_V( 1,0, 3), _V(0,-1,0), MAX_RCS_THRUST, ph_pm, ISP);
th_rcs[ 2] = CreateThruster (_V(-1,0, 3), _V(0, 1,0), MAX_RCS_THRUST, ph_pm, ISP);
th_rcs[ 3] = CreateThruster (_V(-1,0, 3), _V(0,-1,0), MAX_RCS_THRUST, ph_pm, ISP);
th_rcs[ 4] = CreateThruster (_V( 1,0,-3), _V(0, 1,0), MAX_RCS_THRUST, ph_pm, ISP);
th_rcs[ 5] = CreateThruster (_V( 1,0,-3), _V(0,-1,0), MAX_RCS_THRUST, ph_pm, ISP);
th_rcs[ 6] = CreateThruster (_V(-1,0,-3), _V(0, 1,0), MAX_RCS_THRUST, ph_pm, ISP);
th_rcs[ 7] = CreateThruster (_V(-1,0,-3), _V(0,-1,0), MAX_RCS_THRUST, ph_pm, ISP);
th_rcs[ 8] = CreateThruster (_V( 1,0, 3), _V(-1,0,0), MAX_RCS_THRUST, ph_pm, ISP);
th_rcs[ 9] = CreateThruster (_V(-1,0, 3), _V( 1,0,0), MAX_RCS_THRUST, ph_pm, ISP);
th_rcs[10] = CreateThruster (_V( 1,0,-3), _V(-1,0,0), MAX_RCS_THRUST, ph_pm, ISP);
th_rcs[11] = CreateThruster (_V(-1,0,-3), _V( 1,0,0), MAX_RCS_THRUST, ph_pm, ISP);
th_rcs[12] = CreateThruster (_V( 0,0,-3), _V(0,0, 1), MAX_RCS_THRUST, ph_pm, ISP);
th_rcs[13] = CreateThruster (_V( 0,0, 3), _V(0,0,-1), MAX_RCS_THRUST, ph_pm, ISP);
th_group[0] = th_rcs[0];
th_group[1] = th_rcs[2];
th_group[2] = th_rcs[5];
th_group[3] = th_rcs[7];
CreateThrusterGroup (th_group, 4, THGROUP_ATT_PITCHUP);
th_group[0] = th_rcs[1];
th_group[1] = th_rcs[3];
th_group[2] = th_rcs[4];
th_group[3] = th_rcs[6];
CreateThrusterGroup (th_group, 4, THGROUP_ATT_PITCHDOWN);
th_group[0] = th_rcs[0];
th_group[1] = th_rcs[4];
th_group[2] = th_rcs[3];
th_group[3] = th_rcs[7];
CreateThrusterGroup (th_group, 4, THGROUP_ATT_BANKLEFT);
th_group[0] = th_rcs[1];
th_group[1] = th_rcs[5];
th_group[2] = th_rcs[2];
th_group[3] = th_rcs[6];
CreateThrusterGroup (th_group, 4, THGROUP_ATT_BANKRIGHT);
th_group[0] = th_rcs[0];
th_group[1] = th_rcs[4];
th_group[2] = th_rcs[2];
th_group[3] = th_rcs[6];
CreateThrusterGroup (th_group, 4, THGROUP_ATT_UP);
th_group[0] = th_rcs[1];
th_group[1] = th_rcs[5];
th_group[2] = th_rcs[3];
th_group[3] = th_rcs[7];
CreateThrusterGroup (th_group, 4, THGROUP_ATT_DOWN);
th_group[0] = th_rcs[8];
th_group[1] = th_rcs[11];
CreateThrusterGroup (th_group, 2, THGROUP_ATT_YAWLEFT);
th_group[0] = th_rcs[9];
th_group[1] = th_rcs[10];
CreateThrusterGroup (th_group, 2, THGROUP_ATT_YAWRIGHT);
th_group[0] = th_rcs[8];
th_group[1] = th_rcs[10];
CreateThrusterGroup (th_group, 2, THGROUP_ATT_LEFT);
th_group[0] = th_rcs[9];
th_group[1] = th_rcs[11];
CreateThrusterGroup (th_group, 2, THGROUP_ATT_RIGHT);
CreateThrusterGroup (th_rcs+12, 1, THGROUP_ATT_FORWARD);
CreateThrusterGroup (th_rcs+13, 1, THGROUP_ATT_BACK);
}
//=======================================
// Create thrusters for the landing
// ======================================
void RaytheonCEV::SetThrustersLanded()
{
// ClearThrusterDefinitions();
// ClearPropellantResources();
ph_CM = CreatePropellantResource (20); // ground braking propellant
THRUSTER_HANDLE th_att_lin[16];
th_att_lin[0] = CreateThruster (_V(2,-2,-1), _V(-0.2, 1, 0), 10000, ph_CM, RCS_ISP);
th_att_lin[1] = CreateThruster (_V(2,-2,2), _V(-0.2, 1, 0), 5000, ph_CM, RCS_ISP);
th_att_lin[2] = CreateThruster (_V(-2,-2,-1), _V(0.2, 1, 0), 10000, ph_CM, RCS_ISP);
th_att_lin[3] = CreateThruster (_V(-2,-2,2), _V(0.2, 1, 0), 5000, ph_CM, RCS_ISP);
CreateThrusterGroup (th_att_lin, 4, THGROUP_ATT_UP);
SetThrusterGroupLevel(THGROUP_ATT_UP, 1);
}