Surveyor Source Code

From OrbiterWiki
Revision as of 22:43, 21 September 2005 by Kwan3217 (talk | contribs)
Jump to navigation Jump to search
// ==============================================================
//                 ORBITER MODULE: Surveyor
//                Copyright (C) 2005 Kwan3217
//       Released under the Gnu Free Documentation License
//
// Evolved from:
//                 ORBITER MODULE: ShuttlePB
//                  Part of the ORBITER SDK
//          Copyright (C) 2002-2004 Martin Schweiger
//                   All rights reserved
//
// Surveyor.cpp
// Control module for Surveyor vessel class
//
// ==============================================================

#define STRICT
#define ORBITER_MODULE

#include "orbitersdk.h"

// ==============================================================
// Some vessel parameters
// ==============================================================
const double LANDER_EMPTY_MASS = 289.10; //Basic bus plus payload minus AMR minus retro case
const double RETRO_EMPTY_MASS = 64.88;
const double AMR_MASS = 3.82;

const double RETRO_PROP_MASS=560.64;
const double RETRO_THRUST = 39140;
const double RETRO_BURNTIME = 40.5;
const double RETRO_ITOT   = RETRO_THRUST*RETRO_BURNTIME;
const double RETRO_ISP   = RETRO_ITOT/RETRO_PROP_MASS;
const double RETRO_STA   = -0.75;

const double VERNIER_PROP_MASS = 70.98;
const double VERNIER_ISP = 3200;
const double VERNIER_THRUST = 463;
const double VERNIER_RAD = 0.86;
const double VERNIER_STA = -0.5;

const double RCS_PROP_MASS=2;
const double RCS_ISP = 630.0;
const double RCS_THRUST = 0.25;
const double RCS_RAD = 1;
const double RCS_STA = -0.5;
const double RCS_SPACE = 0.1;

const double LEG_RAD = 1.5;
const double LEG_STA =-0.6;


// ==============================================================
// Shuttle-PB class interface
// ==============================================================

class Surveyor: public VESSEL2 {
public:
  Surveyor (OBJHANDLE hVessel, int flightmodel)
    : VESSEL2 (hVessel, flightmodel) {}
  void clbkSetClassCaps (FILEHANDLE cfg);
  void clbkPreStep(double SimT, double SimDT, double MJD);
  int  clbkConsumeBufferedKey(DWORD key, bool down, char *kstate);
  THRUSTER_HANDLE th_vernier[3], th_retro, th_rcs[6], th_group[2];
  double CalcEmptyMass();
  PROPELLANT_HANDLE ph_vernier, ph_rcs, ph_retro;
  void SpawnObject(char* classname, char* ext, VECTOR3 ofs);
  void Jettison();
  int status;

  void SetupMeshes();
  void AddLanderMesh();
  void AddRetroMesh();
  void AddAMRMesh();
};

double Surveyor::CalcEmptyMass() {
  double EmptyMass=0;
  if(GetPropellantMass(ph_retro)>0.999*RETRO_PROP_MASS) {
    EmptyMass+=AMR_MASS;
  }
  if(GetPropellantMass(ph_retro)>1) {
    EmptyMass+=RETRO_EMPTY_MASS;
  }
  EmptyMass+=LANDER_EMPTY_MASS;
  return EmptyMass;
}

// ==============================================================
// Overloaded callback functions
// ==============================================================

// --------------------------------------------------------------
// Set the capabilities of the vessel class
// --------------------------------------------------------------
void Surveyor::clbkSetClassCaps (FILEHANDLE cfg) {

  // physical specs
  SetSize (1.0);
  SetPMI (_V(0.5,0.5,0.5));
  SetCameraOffset (_V(0,0.8,0));
  SetTouchdownPoints( _V( 0,LEG_RAD,LEG_STA), _V( sqrt(3.0)/2*LEG_RAD,-0.5*LEG_RAD,LEG_STA), _V(-sqrt(3.0)/2*LEG_RAD,-0.5*LEG_RAD,LEG_STA));

  status=0;

  // propellant resources
  ph_vernier = CreatePropellantResource(VERNIER_PROP_MASS);
  ph_rcs     = CreatePropellantResource(RCS_PROP_MASS);
  ph_retro   = CreatePropellantResource(RETRO_PROP_MASS);

  th_retro = CreateThruster(_V(0.0,0.0,RETRO_STA), _V(0,0,1), RETRO_THRUST, ph_retro, RETRO_ISP);
  AddExhaust(th_retro, 2, 0.3);

  th_vernier[0] = CreateThruster(_V(         0.0*VERNIER_RAD, 1.0*VERNIER_RAD,VERNIER_STA), _V(0,0,1), VERNIER_THRUST, ph_vernier, VERNIER_ISP);
  th_vernier[1] = CreateThruster(_V( sqrt(3.0)/2*VERNIER_RAD,-0.5*VERNIER_RAD,VERNIER_STA), _V(0,0,1), VERNIER_THRUST, ph_vernier, VERNIER_ISP);
  th_vernier[2] = CreateThruster(_V(-sqrt(3.0)/2*VERNIER_RAD,-0.5*VERNIER_RAD,VERNIER_STA), _V(0,0,1), VERNIER_THRUST, ph_vernier, VERNIER_ISP);
  CreateThrusterGroup(th_vernier, 3, THGROUP_MAIN);
  for(int i=0;i<3;i++) {
    AddExhaust(th_vernier[i], 1, 0.1);
  }

  //Roll (Leg1) jets
  th_rcs[ 0] = CreateThruster (_V(-RCS_SPACE,RCS_RAD,RCS_STA), _V( 1,0,0), RCS_THRUST, ph_rcs, RCS_ISP);
  th_rcs[ 1] = CreateThruster (_V( RCS_SPACE,RCS_RAD,RCS_STA), _V(-1,0,0), RCS_THRUST, ph_rcs, RCS_ISP);
  //Leg2 jets
  th_rcs[ 2] = CreateThruster (_V( sqrt(3.0)/2*RCS_RAD,-0.5*RCS_RAD,RCS_STA-RCS_SPACE), _V(0, 0, 1), RCS_THRUST, ph_rcs, RCS_ISP);
  th_rcs[ 3] = CreateThruster (_V( sqrt(3.0)/2*RCS_RAD,-0.5*RCS_RAD,RCS_STA+RCS_SPACE), _V(0, 0,-1), RCS_THRUST, ph_rcs, RCS_ISP);
  //Leg3 jets
  th_rcs[ 4] = CreateThruster (_V(-sqrt(3.0)/2*RCS_RAD,-0.5*RCS_RAD,RCS_STA-RCS_SPACE), _V(0, 0, 1), RCS_THRUST, ph_rcs, RCS_ISP);
  th_rcs[ 5] = CreateThruster (_V(-sqrt(3.0)/2*RCS_RAD,-0.5*RCS_RAD,RCS_STA+RCS_SPACE), _V(0, 0,-1), RCS_THRUST, ph_rcs, RCS_ISP);

  th_group[0] = th_rcs[3];
  th_group[1] = th_rcs[5];
  CreateThrusterGroup (th_group, 2, THGROUP_ATT_PITCHDOWN);
  th_group[0] = th_rcs[2];
  th_group[1] = th_rcs[4];
  CreateThrusterGroup (th_group, 2, THGROUP_ATT_PITCHUP);
  th_group[0] = th_rcs[0];
  CreateThrusterGroup (th_group, 1, THGROUP_ATT_BANKRIGHT);
  th_group[0] = th_rcs[1];
  CreateThrusterGroup (th_group, 1, THGROUP_ATT_BANKLEFT);
  th_group[0] = th_rcs[3];
  th_group[1] = th_rcs[4];
  CreateThrusterGroup (th_group, 2, THGROUP_ATT_YAWRIGHT);
  th_group[0] = th_rcs[2];
  th_group[1] = th_rcs[5];
  CreateThrusterGroup (th_group, 2, THGROUP_ATT_YAWLEFT);

  for (int i=0;i<6;i++) {
    AddExhaust(th_rcs[i],0.1,0.05);
  }

  // visual specs
  SetupMeshes();
}

void Surveyor::clbkPreStep(double SimT, double SimDT, double MJD) {
  SetEmptyMass(CalcEmptyMass());
  double P,Y,R;
  P=GetThrusterGroupLevel(THGROUP_ATT_PITCHUP)-GetThrusterGroupLevel(THGROUP_ATT_PITCHDOWN);
  Y=GetThrusterGroupLevel(THGROUP_ATT_YAWRIGHT)-GetThrusterGroupLevel(THGROUP_ATT_YAWLEFT);
  R=GetThrusterGroupLevel(THGROUP_ATT_BANKRIGHT)-GetThrusterGroupLevel(THGROUP_ATT_BANKLEFT);
  sprintf(oapiDebugString(),"Pitch %f Yaw %f Roll %f",P,Y,R);

  SetThrusterDir(th_vernier[0],_V(0.087*R,0,1));
  SetThrusterDir(th_vernier[1],_V(0,0,1.0+0.05*P-0.05*Y));
  SetThrusterDir(th_vernier[2],_V(0,0,1.0+0.05*P+0.05*Y));
  if(status == 1 && GetPropellantMass(ph_retro)<1) {
    //Jettison the spent main retro
    Jettison();
  }
  if(status == 0 && GetPropellantMass(ph_retro)<0.999*RETRO_PROP_MASS) {
    //Jettison the AMR if the retro has started burning
    Jettison();
    //Relight the retro if needed
    SetThrusterLevel(th_retro,1);
  }
}

void Surveyor::AddLanderMesh() {
  VECTOR3 ofs = _V(0,0.3,0);
  AddMesh("Surveyor-Lander",&ofs);
}
void Surveyor::AddRetroMesh() {
  VECTOR3 ofs = _V(0,0,-0.5);
  AddMesh("Surveyor-Retro",&ofs);
}
void Surveyor::AddAMRMesh() {
  VECTOR3 ofs = _V(0,0,-0.8);
  AddMesh("Surveyor-AMR",&ofs);
}

void Surveyor::SetupMeshes() {
  ClearMeshes();
  switch(status) {
    case 0:
      AddAMRMesh();
    case 1:
      AddRetroMesh();
    case 2:
      AddLanderMesh();
  }
}

void Surveyor::SpawnObject(char* classname, char* ext, VECTOR3 ofs) {
  VESSELSTATUS vs;
  char name[256];
  GetStatus(vs);
  Local2Rel (ofs, vs.rpos);
  vs.eng_main = vs.eng_hovr = 0.0;
  vs.status = 0;
  strcpy (name, GetName()); strcat (name, ext);
  oapiCreateVessel (name, classname, vs);
}

void Surveyor::Jettison() {
  switch(status) {
    case 0:
      status=1;
      SpawnObject("Surveyor_AMR","-AMR",_V(0,0,-0.8));
      break;
    case 1:
      status=2;
      SpawnObject("Surveyor_Retro","-Retro",_V(0,0,-0.5));
      break;
  }
  SetupMeshes();
}

int Surveyor::clbkConsumeBufferedKey(DWORD key, bool down, char *kstate) {
  if (!down) return 0; // only process keydown events

  if (KEYMOD_SHIFT (kstate)) {

  } else { // unmodified keys
    switch (key) {
      case OAPI_KEY_L:  // Fire Retro
        SetThrusterLevel(th_retro,1);
        return 1;
    }
  }
  return 0;
}

// ==============================================================
// API callback interface
// ==============================================================

// --------------------------------------------------------------
// Vessel initialisation
// --------------------------------------------------------------
DLLCLBK VESSEL *ovcInit (OBJHANDLE hvessel, int flightmodel)
{
  return new Surveyor (hvessel, flightmodel);
}

// --------------------------------------------------------------
// Vessel cleanup
// --------------------------------------------------------------
DLLCLBK void ovcExit (VESSEL *vessel)
{
  if (vessel) delete (Surveyor*)vessel;
}