Esempio n. 1
0
FGThruster::FGThruster(FGFDMExec *FDMExec, Element *el, int num ): FGForce(FDMExec)
{
  Element* thruster_element = el->GetParent();
  Element* element;
  FGColumnVector3 location, orientation, pointing;

  Type = ttDirect;
  SetTransformType(FGForce::tCustom);

  Name = el->GetAttributeValue("name");

  GearRatio = 1.0;
  ReverserAngle = 0.0;
  Thrust = 0.0;
  EngineNum = num;
  PropertyManager = FDMExec->GetPropertyManager();

// Determine the initial location and orientation of this thruster and load the
// thruster with this information.

  element = thruster_element->FindElement("location");
  if (element)  location = element->FindElementTripletConvertTo("IN");
  else          cerr << fgred << "      No thruster location found." << reset << endl;

  SetLocation(location);

  string property_name, base_property_name;
  base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNum);

  element = thruster_element->FindElement("pointing");
  if (element)  {

    // This defines a fixed nozzle that has no public interface property to gimbal or reverse it.
    pointing = element->FindElementTripletConvertTo("RAD"); // The specification of RAD here is superfluous,
                                                            // and simply precludes a conversion.
    mT.InitMatrix();
    mT(1,1) = pointing(1);
    mT(2,1) = pointing(2);
    mT(3,1) = pointing(3);

  } else {

  element = thruster_element->FindElement("orient");
  if (element)  orientation = element->FindElementTripletConvertTo("RAD");

  SetAnglesToBody(orientation);
  property_name = base_property_name + "/pitch-angle-rad";
  PropertyManager->Tie( property_name.c_str(), (FGForce *)this, &FGForce::GetPitch, &FGForce::SetPitch);
  property_name = base_property_name + "/yaw-angle-rad";
  PropertyManager->Tie( property_name.c_str(), (FGForce *)this, &FGForce::GetYaw, &FGForce::SetYaw);

  if (el->GetName() == "direct") // this is a direct thruster. At this time
                                 // only a direct thruster can be reversed.
  {
    property_name = base_property_name + "/reverser-angle-rad";
    PropertyManager->Tie( property_name.c_str(), (FGThruster *)this, &FGThruster::GetReverserAngle,
                                                          &FGThruster::SetReverserAngle);
  }

  }


  Debug(0);
}
Esempio n. 2
0
FGRotor::FGRotor(FGFDMExec *exec, Element* rotor_element, int num)
                    : FGThruster(exec, rotor_element, num)
{

  FGColumnVector3 location, orientation;
  Element *thruster_element;

  PropertyManager = fdmex->GetPropertyManager();
  dt = fdmex->GetDeltaT();

  /* apply defaults */

  rho = 0.002356; // just a sane value
  
  RPM = 0.0;
  Sense = 1.0;
  tailRotorPresent = false;
  
  effective_tail_col = 0.001; // just a sane value 

  prop_inflow_ratio_lambda =  0.0;
  prop_advance_ratio_mu = 0.0; 
  prop_inflow_ratio_induced_nu = 0.0;
  prop_mr_torque = 0.0;
  prop_thrust_coefficient = 0.0;
  prop_coning_angle = 0.0;

  prop_theta_downwash = prop_phi_downwash = 0.0;

  hover_threshold = 0.0;
  hover_scale = 0.0;

  mr.zero();
  tr.zero();

  // debug stuff
  prop_DumpFlag = 0;

  /* configure */

  Type = ttRotor;
  SetTransformType(FGForce::tCustom);

  // get data from parent and 'mount' the rotor system

  thruster_element = rotor_element->GetParent()->FindElement("sense");
  if (thruster_element) {
    Sense = thruster_element->GetDataAsNumber() >= 0.0 ? 1.0: -1.0;
  }

  thruster_element = rotor_element->GetParent()->FindElement("location");
  if (thruster_element)  location = thruster_element->FindElementTripletConvertTo("IN");
  else          cerr << "No thruster location found." << endl;

  thruster_element = rotor_element->GetParent()->FindElement("orient");
  if (thruster_element)  orientation = thruster_element->FindElementTripletConvertTo("RAD");
  else          cerr << "No thruster orientation found." << endl;

  SetLocation(location);
  SetAnglesToBody(orientation);

  // get main rotor parameters 
  mr.parent = rotor_element;

  int flags = eMain;

  string a_val="";
  a_val = rotor_element->GetAttributeValue("variant");
  if ( a_val == "coaxial" ) {
    flags += eCoaxial;
    cerr << "# found 'coaxial' variant" << endl;
  }  

  if (Sense<0.0) {
    flags += eRotCW;
  }
    
  mr.configure(flags);

  mr.rk.init(0,dt,6);

  // get tail rotor parameters
  tr.parent=rotor_element->FindElement("tailrotor");
  if (tr.parent) {
    tailRotorPresent = true;
  } else {
    tailRotorPresent = false;
    cerr << "# No tailrotor found, assuming a single rotor." << endl;
  }

  if (tailRotorPresent) {
    int flags = eTail;
    if (Sense<0.0) {
      flags += eRotCW;
    }
    tr.configure(flags, &mr);
    tr.rk.init(0,dt,6);
    tr.RpmRatio = tr.NominalRPM/mr.NominalRPM; // 'connect'
  }

  /* remaining parameters */

  // ground effect  
  double c_ground_effect = 0.0;  // uh1 ~ 0.28 , larger values increase the effect
  ground_effect_exp = 0.0;  
  ground_effect_shift = 0.0;

  if (rotor_element->FindElement("cgroundeffect"))
    c_ground_effect = rotor_element->FindElementValueAsNumber("cgroundeffect");

  if (rotor_element->FindElement("groundeffectshift"))
    ground_effect_shift = rotor_element->FindElementValueAsNumberConvertTo("groundeffectshift","FT");

  // prepare calculations, see /TA77/
  if (c_ground_effect > 1e-5) {
    ground_effect_exp = 1.0 / ( 2.0*mr.Radius * c_ground_effect );
  } else {
    ground_effect_exp = 0.0; // disable
  }

  // smooth out jumps in hagl reported, otherwise the ground effect
  // calculation would cause jumps too. 1Hz seems sufficient.
  damp_hagl = Filter(1.0,dt);


  // misc, experimental
  if (rotor_element->FindElement("hoverthreshold"))
    hover_threshold = rotor_element->FindElementValueAsNumberConvertTo("hoverthreshold", "FT/SEC");

  if (rotor_element->FindElement("hoverscale"))
    hover_scale = rotor_element->FindElementValueAsNumber("hoverscale");

  // enable import-export
  bind();

  // unused right now
  prop_rotorbrake->setDoubleValue(0.0);
  prop_freewheel_factor->setDoubleValue(1.0);  

  Debug(0);

}  // Constructor