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); }
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