Surveyor Source Code

From OrbiterWiki
Jump to navigation Jump to search

This is the source code for the module Surveyor, by Kwan3217. It is based on the module for the Shuttle-PB. It is created in Vessel Tutorial 2.

// ==============================================================
//                 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;
}