コード例 #1
0
// basically P = Q*w and Q_Engine + (-Q_Rotor) = J * dw/dt, J = Moment
//
void FGTransmission::Calculate(double EnginePower, double ThrusterTorque, double dt) {

  double coupling = 1.0, coupling_sq = 1.0;
  double fw_mult = 1.0;

  double d_omega = 0.0, engine_d_omega = 0.0, thruster_d_omega = 0.0; // relative changes

  double engine_omega = rpm_to_omega(EngineRPM);
  double safe_engine_omega = engine_omega < 1e-1 ? 1e-1 : engine_omega;
  double engine_torque = EnginePower / safe_engine_omega;

  double thruster_omega = rpm_to_omega(ThrusterRPM);
  double safe_thruster_omega = thruster_omega < 1e-1 ? 1e-1 : thruster_omega;

  engine_torque  -= EngineFriction / safe_engine_omega;
  ThrusterTorque += Constrain(0.0, BrakeCtrlNorm, 1.0) * MaxBrakePower / safe_thruster_omega;

  // would the FWU release ?
  engine_d_omega = engine_torque/EngineMoment * dt;
  thruster_d_omega =  - ThrusterTorque/ThrusterMoment * dt;

  if ( thruster_omega+thruster_d_omega > engine_omega+engine_d_omega ) {
    // don't drive the engine
    FreeWheelTransmission = 0.0;
  } else {
    FreeWheelTransmission = 1.0;
  }

  fw_mult = FreeWheelLag.execute(FreeWheelTransmission);
  coupling = fw_mult * Constrain(0.0, ClutchCtrlNorm, 1.0);

  if (coupling < 0.999999) { // are the separate calculations needed ?
    // assume linear transfer 
    engine_d_omega   =
       (engine_torque - ThrusterTorque*coupling)/(ThrusterMoment*coupling + EngineMoment) * dt;
    thruster_d_omega = 
       (engine_torque*coupling - ThrusterTorque)/(ThrusterMoment + EngineMoment*coupling) * dt;

    EngineRPM += omega_to_rpm(engine_d_omega);
    ThrusterRPM += omega_to_rpm(thruster_d_omega);

    // simulate transit to static friction
    coupling_sq = coupling*coupling;
    EngineRPM   = (1.0-coupling_sq) * EngineRPM    + coupling_sq * 0.02 * (49.0*EngineRPM + ThrusterRPM);
    ThrusterRPM = (1.0-coupling_sq) * ThrusterRPM  + coupling_sq * 0.02 * (EngineRPM + 49.0*ThrusterRPM);

    // enforce equal rpm
    if ( fabs(EngineRPM-ThrusterRPM) < 1e-3 ) {
      EngineRPM = ThrusterRPM = 0.5 * (EngineRPM+ThrusterRPM);
    }
  } else {
    d_omega = (engine_torque - ThrusterTorque)/(ThrusterMoment + EngineMoment) * dt;
    EngineRPM = ThrusterRPM += omega_to_rpm(d_omega);
  }

  // nothing will turn backward
  if (EngineRPM < 0.0 ) EngineRPM = 0.0;
  if (ThrusterRPM < 0.0 ) ThrusterRPM = 0.0;

}
コード例 #2
0
ファイル: manips.c プロジェクト: barak/ivtools-cvs
boolean VertexManip::Manipulating (Event& e) {
    Rubberband* r = GetRubberband();

    if (r == nil) {
        return false;
    }

    if (e.eventType == MotionEvent) {
        Constrain(e);
	r->Track(e.x, e.y);

    } else if (e.eventType == DownEvent) {
        Constrain(e);

        if (e.button == LEFTMOUSE) {
            GetGrowingVertices()->AddVertex(e.x, e.y);
	    _origx = e.x;
	    _origy = e.y;

        } else if (e.button == MIDDLEMOUSE) {
            GetGrowingVertices()->AddVertex(e.x, e.y);
            return false;

        } else if (e.button == RIGHTMOUSE) {
            GetGrowingVertices()->RemoveVertex();
	    if (GetGrowingVertices()->Count()==0) return false;
        }
    }
    return true;
}
コード例 #3
0
ファイル: pokef~.c プロジェクト: Cycling74/percolate
void pokef_in3(t_pokef *x, long n)
{
	if (n)
		x->l_chan = Constrain(n,1,4) - 1;
	else
		x->l_chan = 0;
}
コード例 #4
0
ファイル: panner2_6.c プロジェクト: barak/ivtools-cvs
void Slider::Slide (Event& e) {
    IntCoord newleft, newbot, dummy;
    boolean control = e.control;

    Listen(allEvents);
    SlidingRect r(output, canvas, left, bottom, right, top, e.x, e.y);
    CalcLimits(e);
    do {
	switch (e.eventType) {
	    case MotionEvent:
		e.target->GetRelative(e.x, e.y, this);
		Constrain(e);
		r.Track(e.x, e.y);

                if ((syncScroll && !control) || (!syncScroll && control)) {
                    r.Erase();
                    r.GetCurrent(newleft, newbot, dummy, dummy);
                    Move(ViewX(newleft - left), ViewY(newbot - bottom));
                    interactor->Adjust(*shown);
                }

		break;
	    default:
		break;
	}
	Read(e);
    } while (e.eventType != UpEvent);

    r.GetCurrent(newleft, newbot, dummy, dummy);
    Move(ViewX(newleft - left), ViewY(newbot - bottom));
    Listen(input);
}
コード例 #5
0
ファイル: NUSpline.cpp プロジェクト: 2asoft/0ad
void TNSpline::Smooth()
{
	for (int i = 0; i < 3; ++i)
	{
		SNSpline::Smooth();
		Constrain();
	}
}
コード例 #6
0
ファイル: SizerBar.cpp プロジェクト: buranela/OpenHoldemV12
//////////////////
// User let go of mouse: leave size-drag mode
//
void CSizerBar::OnLButtonUp(UINT nFlags, CPoint pt)
{
	if (m_bDragging) {
		pt = Constrain(pt);					 // don't go outside constraints
		pt = Rectify(pt);						 // clip x or y
		CPoint ptDelta = pt-m_ptOriginal; // distance moved
		CancelDrag();							 // cancel drag mode
		NotifyMoved(ptDelta);				 // notify parent
	}
}
コード例 #7
0
ファイル: manips.c プロジェクト: barak/ivtools-cvs
void DragManip::Grasp (Event& e) {
    _grasp_e = e;

    if (!_origPreset) {
        _origx = e.x;
        _origy = e.y;
    }
    Constrain(e);

    if (_r != nil) _r->Track(e.x, e.y);
}
コード例 #8
0
ファイル: SizerBar.cpp プロジェクト: buranela/OpenHoldemV12
//////////////////
// User moved mouse: erase old bar and draw in new position. XOR makes this
// easy. Keep track of previous point.
//
void CSizerBar::OnMouseMove(UINT nFlags, CPoint pt)
{
	if (m_bDragging) {
		DrawBar();				// erase old bar
		pt = Constrain(pt);	// don't go outside constrained rect!
		pt = Rectify(pt);		// clip x or y depending if horizontal or vert
		CPoint ptDelta = pt-m_ptPrevious;
		m_rcBar += ptDelta;	// move bar...
		DrawBar();				// and draw
		m_ptPrevious = pt;	// remember for next mousemove
	}
}
コード例 #9
0
ファイル: 1312.c プロジェクト: tainzhi/acm
void DFS(int x, int y, int n, int m, int *step) {
    matrix[y][x] = '#';
    int nx, ny;
    for (int i = 0; i < 4; ++i) {
        nx = x + move[i][0];
        ny = y + move[i][1];
        if (Constrain(nx, ny, n, m) && matrix[ny][nx] == '.') {
            matrix[ny][nx] = '#';
            ++(*step);
            DFS(nx, ny, n, m, step);
        }
    }
}
コード例 #10
0
ファイル: manips.c プロジェクト: barak/ivtools-cvs
boolean DragManip::Manipulating (Event& e) {
    if (_r == nil) {
        return false;
    }

    if (e.eventType == MotionEvent) {
        Constrain(e);
	_r->Track(e.x, e.y);

    } else if (e.eventType == UpEvent) {
	return false;
    }
    return true;
}
コード例 #11
0
ファイル: composit.cpp プロジェクト: kleopatra999/pgadmin3
bool wxCompositeShape::Recompute()
{
	int noIterations = 0;
	bool changed = TRUE;
	while (changed && (noIterations < 500))
	{
		changed = Constrain();
		noIterations ++;
	}
	/*
	#ifdef wx_x
	  if (changed)
	    cerr << "Warning: constraint algorithm failed after 500 iterations.\n";
	#endif
	*/
	return (!changed);
}
コード例 #12
0
hConstraint Constraint::ConstrainCoincident(hEntity ptA, hEntity ptB) {
    return Constrain(Type::POINTS_COINCIDENT, ptA, ptB,
        Entity::NO_ENTITY, Entity::NO_ENTITY, /*other=*/false, /*other2=*/false);
}
コード例 #13
0
ファイル: FGTurboProp.cpp プロジェクト: DolanP/jsbsim-dll
bool FGTurboProp::Load(FGFDMExec* exec, Element *el)
{
  MaxStartingTime = 999999; //very big timeout -> infinite
  Ielu_max_torque=-1;

// ToDo: Need to make sure units are properly accounted for below.

  if (el->FindElement("milthrust"))
    MilThrust = el->FindElementValueAsNumberConvertTo("milthrust","LBS");
  if (el->FindElement("idlen1"))
    IdleN1 = el->FindElementValueAsNumber("idlen1");
  if (el->FindElement("idlen2"))
    IdleN2 = el->FindElementValueAsNumber("idlen2");
  if (el->FindElement("maxn1"))
    MaxN1 = el->FindElementValueAsNumber("maxn1");
  if (el->FindElement("maxn2"))
    MaxN2 = el->FindElementValueAsNumber("maxn2");
  if (el->FindElement("betarangeend"))
    BetaRangeThrottleEnd = el->FindElementValueAsNumber("betarangeend")/100.0;
  BetaRangeThrottleEnd = Constrain(0.0, BetaRangeThrottleEnd, 0.99999);
  if (el->FindElement("reversemaxpower"))
    ReverseMaxPower = el->FindElementValueAsNumber("reversemaxpower")/100.0;

  if (el->FindElement("maxpower"))
    MaxPower = el->FindElementValueAsNumber("maxpower");
  if (el->FindElement("idlefuelflow")) {
    cerr << el->ReadFrom() << "Note: 'idlefuelflow' is obsolete, "
         << "use the 'CombustionEfficiency_N1' table instead." << endl;
  }
  if (el->FindElement("psfc"))
    PSFC = el->FindElementValueAsNumber("psfc");
  if (el->FindElement("n1idle_max_delay"))
    Idle_Max_Delay = el->FindElementValueAsNumber("n1idle_max_delay");
  if (el->FindElement("maxstartingtime"))
    MaxStartingTime = el->FindElementValueAsNumber("maxstartingtime");
  if (el->FindElement("startern1"))
    StarterN1 = el->FindElementValueAsNumber("startern1");
  if (el->FindElement("ielumaxtorque"))
    Ielu_max_torque = el->FindElementValueAsNumber("ielumaxtorque");
  if (el->FindElement("itt_delay"))
    ITT_Delay = el->FindElementValueAsNumber("itt_delay");

  Element *table_element;
  string name;
  FGPropertyManager* PropertyManager = exec->GetPropertyManager();

  while (true) {
    table_element = el->FindNextElement("table");
    if (!table_element) break;
    name = table_element->GetAttributeValue("name");
    if (name == "EnginePowerVC") {
      EnginePowerVC = new FGTable(PropertyManager, table_element);
    } else if (name == "EnginePowerRPM_N1") {
      EnginePowerRPM_N1 = new FGTable(PropertyManager, table_element);
    } else if (name == "ITT_N1") {
      ITT_N1 = new FGTable(PropertyManager, table_element);
    } else if (name == "CombustionEfficiency_N1") {
      CombustionEfficiency_N1 = new FGTable(PropertyManager, table_element);
    } else {
      cerr << el->ReadFrom() << "Unknown table type: " << name
           << " in turboprop definition." << endl;
    }
  }

  // Pre-calculations and initializations

  delay=1;
  N1_factor = MaxN1 - IdleN1;
  N2_factor = MaxN2 - IdleN2;
  OilTemp_degK = in.TAT_c + 273.0;

  // default table based on '9.333 - (N1)/12.0' approximation
  // gives 430%Fuel at 60%N1
  if (! CombustionEfficiency_N1) {
    CombustionEfficiency_N1 = new FGTable(6);
    *CombustionEfficiency_N1 <<  60.0 << 12.0/52.0;
    *CombustionEfficiency_N1 <<  82.0 << 12.0/30.0;
    *CombustionEfficiency_N1 <<  96.0 << 12.0/16.0;
    *CombustionEfficiency_N1 << 100.0 << 1.0;
    *CombustionEfficiency_N1 << 104.0 << 1.5;
    *CombustionEfficiency_N1 << 110.0 << 6.0;
  }
  

  return true;
}
コード例 #14
0
ファイル: FGAccelerations.cpp プロジェクト: agodemar/jsbsim
void FGAccelerations::CalculateFrictionForces(double dt)
{
  vector<LagrangeMultiplier*>& multipliers = *in.MultipliersList;
  size_t n = multipliers.size();

  vFrictionForces.InitMatrix();
  vFrictionMoments.InitMatrix();

  // If no gears are in contact with the ground then return
  if (!n) return;

  vector<double> a(n*n); // Will contain Jac*M^-1*Jac^T
  vector<double> rhs(n);

  // Assemble the linear system of equations
  for (unsigned int i=0; i < n; i++) {
    FGColumnVector3 U = multipliers[i]->ForceJacobian;
    FGColumnVector3 r = multipliers[i]->LeverArm;
    FGColumnVector3 v1 = U / in.Mass;
    FGColumnVector3 v2 = in.Jinv * (r*U); // Should be J^-T but J is symmetric and so is J^-1

    for (unsigned int j=0; j < i; j++)
      a[i*n+j] = a[j*n+i]; // Takes advantage of the symmetry of Jac^T*M^-1*Jac

    for (unsigned int j=i; j < n; j++) {
      U = multipliers[j]->ForceJacobian;
      r = multipliers[j]->LeverArm;
      a[i*n+j] = DotProduct(U, v1 + v2*r);
    }
  }

  // Assemble the RHS member

  // Translation
  FGColumnVector3 vdot = vUVWdot;
  if (dt > 0.) // Zeroes out the relative movement between the aircraft and the ground
    vdot += (in.vUVW - in.Tec2b * in.TerrainVelocity) / dt;

  // Rotation
  FGColumnVector3 wdot = vPQRdot;
  if (dt > 0.) // Zeroes out the relative movement between the aircraft and the ground
    wdot += (in.vPQR - in.Tec2b * in.TerrainAngularVel) / dt;

  // Prepare the linear system for the Gauss-Seidel algorithm :
  // 1. Compute the right hand side member 'rhs'
  // 2. Divide every line of 'a' and 'rhs' by a[i,i]. This is in order to save
  //    a division computation at each iteration of Gauss-Seidel.
  for (unsigned int i=0; i < n; i++) {
    double d = a[i*n+i];
    FGColumnVector3 U = multipliers[i]->ForceJacobian;
    FGColumnVector3 r = multipliers[i]->LeverArm;

    rhs[i] = -DotProduct(U, vdot + wdot*r)/d;

    for (unsigned int j=0; j < n; j++)
      a[i*n+j] /= d;
  }

  // Resolve the Lagrange multipliers with the projected Gauss-Seidel method
  for (int iter=0; iter < 50; iter++) {
    double norm = 0.;

    for (unsigned int i=0; i < n; i++) {
      double lambda0 = multipliers[i]->value;
      double dlambda = rhs[i];

      for (unsigned int j=0; j < n; j++)
        dlambda -= a[i*n+j]*multipliers[j]->value;

      multipliers[i]->value = Constrain(multipliers[i]->Min, lambda0+dlambda, multipliers[i]->Max);
      dlambda = multipliers[i]->value - lambda0;

      norm += fabs(dlambda);
    }

    if (norm < 1E-5) break;
  }

  // Calculate the total friction forces and moments

  for (unsigned int i=0; i< n; i++) {
    double lambda = multipliers[i]->value;
    FGColumnVector3 U = multipliers[i]->ForceJacobian;
    FGColumnVector3 r = multipliers[i]->LeverArm;

    FGColumnVector3 F = lambda * U;
    vFrictionForces += F;
    vFrictionMoments += r * F;
  }

  FGColumnVector3 accel = vFrictionForces / in.Mass;
  FGColumnVector3 omegadot = in.Jinv * vFrictionMoments;

  vBodyAccel += accel;
  vUVWdot += accel;
  vUVWidot += in.Tb2i * accel;
  vPQRdot += omegadot;
  vPQRidot += omegadot;
}
コード例 #15
0
ファイル: constraint.cpp プロジェクト: astarasikov/solvespace
void Constraint::ConstrainCoincident(hEntity ptA, hEntity ptB) {
    Constrain(POINTS_COINCIDENT, ptA, ptB,
        Entity::NO_ENTITY, Entity::NO_ENTITY, false, false);
}
コード例 #16
0
ファイル: constraint.cpp プロジェクト: astarasikov/solvespace
void Constraint::Constrain(int type, hEntity ptA, hEntity ptB, hEntity entityA){
    Constrain(type, ptA, ptB, entityA, Entity::NO_ENTITY, false, false);
}
コード例 #17
0
hConstraint Constraint::Constrain(Constraint::Type type, hEntity ptA, hEntity ptB, hEntity entityA){
    return Constrain(type, ptA, ptB, entityA, Entity::NO_ENTITY, /*other=*/false, /*other2=*/false);
}
コード例 #18
0
ファイル: FGRotor.cpp プロジェクト: 8W9aG/jsbsim
// 1. read configuration and try to fill holes, ymmv
// 2. calculate derived parameters and transforms
void FGRotor::rotor::configure(int f, const rotor *xmain)
{

  double estimate;
  const bool yell   = true;
  const bool silent = false;

  flags = f;

  estimate = (xmain) ? 2.0 * xmain->Radius * 0.2 : 42.0;
  Radius = 0.5 * cnf_elem("diameter", estimate, "FT", yell);

  estimate = (xmain) ? xmain->BladeNum  : 2.0;
  estimate = Constrain(1.0,estimate,4.0);
  BladeNum = (int) cnf_elem("numblades", estimate, yell);

  estimate = (xmain) ? - xmain->Radius * 1.05 - Radius : - 0.025 * Radius ; 
  RelDistance_xhub = cnf_elem("xhub", estimate, "FT", yell);

  RelShift_yhub = cnf_elem("yhub", 0.0, "FT", silent);
  
  estimate = - 0.1 * Radius - 4.0;
  RelHeight_zhub = cnf_elem("zhub", estimate, "FT", yell);
  
  // make sure that v_tip (omega*r) is below 0.7mach ~ 750ft/s
  estimate = (750.0/Radius)/(2.0*M_PI) * 60.0;  // 7160/Radius
  NominalRPM = cnf_elem("nominalrpm", estimate, yell);

  MinRPM = cnf_elem("minrpm", 1.0, silent);
  MinRPM = Constrain(1.0, MinRPM, NominalRPM-1.0);

  estimate = (xmain) ? 0.12 : 0.07;  // guess solidity
  estimate = estimate * M_PI*Radius/BladeNum;
  BladeChord = cnf_elem("chord", estimate, "FT", yell);

  LiftCurveSlope = cnf_elem("liftcurveslope", 6.0, yell); // "1/RAD"

  estimate = sqr(BladeChord) * sqr(Radius) * 0.57;
  BladeFlappingMoment = cnf_elem("flappingmoment", estimate, "SLUG*FT2", yell);   
  BladeFlappingMoment = Constrain(0.1, BladeFlappingMoment, 1e9);

  BladeTwist = cnf_elem("twist", -0.17, "RAD", yell);

  estimate = sqr(BladeChord) * BladeChord * 15.66; // might be really wrong!
  BladeMassMoment = cnf_elem("massmoment", estimate, yell); // slug-ft
  BladeMassMoment = Constrain(0.1, BladeMassMoment, 1e9);

  TipLossB = cnf_elem("tiplossfactor", 0.98, silent);

  estimate = 1.1 * BladeFlappingMoment * BladeNum;
  PolarMoment = cnf_elem("polarmoment", estimate, "SLUG*FT2", silent);
  PolarMoment = Constrain(0.1, PolarMoment, 1e9);

  InflowLag = cnf_elem("inflowlag", 0.2, silent); // fixme, depends on size

  estimate = (xmain) ? 0.0 : -0.06;  
  ShaftTilt = cnf_elem("shafttilt", estimate, "RAD", silent);

  // ignore differences between teeter/hingeless/fully-articulated constructions
  estimate = 0.05 * Radius;
  HingeOffset = cnf_elem("hingeoffset", estimate, "FT", (xmain) ? silent : yell);

  CantAngleD3 = cnf_elem("cantangle", 0.0, "RAD", silent);  

  // derived parameters

  // precalc often used powers
  R[0]=1.0; R[1]=Radius;   R[2]=R[1]*R[1]; R[3]=R[2]*R[1]; R[4]=R[3]*R[1];
  B[0]=1.0; B[1]=TipLossB; B[2]=B[1]*B[1]; B[3]=B[2]*B[1]; B[4]=B[3]*B[1]; B[5]=B[4]*B[1];

  LockNumberByRho = LiftCurveSlope * BladeChord * R[4] / BladeFlappingMoment;
  solidity = BladeNum * BladeChord / (M_PI * Radius);

  // use simple orientations at the moment
  if (flags & eTail) { // axis parallel to Y_body
    theta_shaft = 0.0; // no tilt
    phi_shaft = 0.5*M_PI;

    // opposite direction if main rotor is spinning CW
    if (xmain && (xmain->flags & eRotCW) ) { 
      phi_shaft = -phi_shaft; 
    }
  } else {  // more or less upright
    theta_shaft = ShaftTilt;
    phi_shaft = 0.0; 
  }

  // setup Shaft-Body transforms, see /SH79/ eqn(17,18)
  double st = sin(theta_shaft);
  double ct = cos(theta_shaft);
  double sp = sin(phi_shaft);
  double cp = cos(phi_shaft);

  ShaftToBody.InitMatrix(    ct, st*sp, st*cp,
                            0.0,    cp,   -sp,
                            -st, ct*sp, ct*cp  );

  BodyToShaft  =  ShaftToBody.Inverse();

  // misc defaults
  nu = 0.001; // help the flow solver by providing some moving molecules
  
  return;
}
コード例 #19
0
ファイル: FGPiston.cpp プロジェクト: matthewzhenggong/jsbsim
FGPiston::FGPiston(FGFDMExec* exec, Element* el, int engine_number, struct Inputs& input)
  : FGEngine(exec, el, engine_number, input),
  R_air(287.3),                  // Gas constant for air J/Kg/K
  rho_fuel(800),                 // estimate
  calorific_value_fuel(47.3e6),  // J/Kg
  Cp_air(1005),                  // Specific heat (constant pressure) J/Kg/K
  Cp_fuel(1700),
  standard_pressure(101320.73)
{
  Element *table_element;
  string token;
  string name="";

  // Defaults and initializations

  Type = etPiston;

  // These items are read from the configuration file
  // Defaults are from a Lycoming O-360, more or less

  Cycles = 4;
  IdleRPM = 600;
  MaxRPM = 2800;
  Displacement = 360;
  SparkFailDrop = 1.0;
  MaxHP = 200;
  MinManifoldPressure_inHg = 6.5;
  MaxManifoldPressure_inHg = 28.5;
  ManifoldPressureLag=1.0;
  ISFC = -1;
  volumetric_efficiency = 0.85;
  Bore = 5.125;
  Stroke = 4.375;
  Cylinders = 4;
  CylinderHeadMass = 2; //kg
  CompressionRatio = 8.5;
  Z_airbox = -999;
  Ram_Air_Factor = 1;
  PeakMeanPistonSpeed_fps = 100;
  FMEPDynamic= 18400;
  FMEPStatic = 46500;
  Cooling_Factor = 0.5144444;
  StaticFriction_HP = 1.5;
  StarterGain = 1.;
  StarterTorque = -1.;
  StarterRPM = -1.;

  // These are internal program variables

  Lookup_Combustion_Efficiency = 0;
  Mixture_Efficiency_Correlation = 0;
  crank_counter = 0;
  Magnetos = 0;
  minMAP = 21950;
  maxMAP = 96250;

  ResetToIC();

  // Supercharging
  BoostSpeeds = 0;  // Default to no supercharging
  BoostSpeed = 0;
  Boosted = false;
  BoostOverride = 0;
  BoostManual = 0;
  bBoostOverride = false;
  bTakeoffBoost = false;
  TakeoffBoost = 0.0;   // Default to no extra takeoff-boost
  int i;
  for (i=0; i<FG_MAX_BOOST_SPEEDS; i++) {
    RatedBoost[i] = 0.0;
    RatedPower[i] = 0.0;
    RatedAltitude[i] = 0.0;
    BoostMul[i] = 1.0;
    RatedMAP[i] = 100000;
    RatedRPM[i] = 2500;
    TakeoffMAP[i] = 100000;
  }
  for (i=0; i<FG_MAX_BOOST_SPEEDS-1; i++) {
    BoostSwitchAltitude[i] = 0.0;
    BoostSwitchPressure[i] = 0.0;
  }

  // Read inputs from engine data file where present.

  if (el->FindElement("minmp")) 
    MinManifoldPressure_inHg = el->FindElementValueAsNumberConvertTo("minmp","INHG");
  if (el->FindElement("maxmp"))
    MaxManifoldPressure_inHg = el->FindElementValueAsNumberConvertTo("maxmp","INHG");
  if (el->FindElement("man-press-lag"))
    ManifoldPressureLag = el->FindElementValueAsNumber("man-press-lag");
  if (el->FindElement("displacement"))
    Displacement = el->FindElementValueAsNumberConvertTo("displacement","IN3");
  if (el->FindElement("maxhp"))
    MaxHP = el->FindElementValueAsNumberConvertTo("maxhp","HP");
  if (el->FindElement("static-friction"))
    StaticFriction_HP = el->FindElementValueAsNumberConvertTo("static-friction","HP");
  if (el->FindElement("sparkfaildrop"))
    SparkFailDrop = Constrain(0, 1 - el->FindElementValueAsNumber("sparkfaildrop"), 1);
  if (el->FindElement("cycles"))
    Cycles = el->FindElementValueAsNumber("cycles");
  if (el->FindElement("idlerpm"))
    IdleRPM = el->FindElementValueAsNumber("idlerpm");
  if (el->FindElement("maxrpm"))
    MaxRPM = el->FindElementValueAsNumber("maxrpm");
  if (el->FindElement("maxthrottle"))
    MaxThrottle = el->FindElementValueAsNumber("maxthrottle");
  if (el->FindElement("minthrottle"))
    MinThrottle = el->FindElementValueAsNumber("minthrottle");
  if (el->FindElement("bsfc"))
    ISFC = el->FindElementValueAsNumberConvertTo("bsfc", "LBS/HP*HR");
  if (el->FindElement("volumetric-efficiency"))
    volumetric_efficiency = el->FindElementValueAsNumber("volumetric-efficiency");
  if (el->FindElement("compression-ratio"))
    CompressionRatio = el->FindElementValueAsNumber("compression-ratio");
  if (el->FindElement("bore"))
    Bore = el->FindElementValueAsNumberConvertTo("bore","IN");
  if (el->FindElement("stroke"))
    Stroke = el->FindElementValueAsNumberConvertTo("stroke","IN");
  if (el->FindElement("cylinders"))
    Cylinders = el->FindElementValueAsNumber("cylinders");
  if (el->FindElement("cylinder-head-mass"))
    CylinderHeadMass = el->FindElementValueAsNumberConvertTo("cylinder-head-mass","KG");
  if (el->FindElement("air-intake-impedance-factor"))
    Z_airbox = el->FindElementValueAsNumber("air-intake-impedance-factor");
  if (el->FindElement("ram-air-factor"))
    Ram_Air_Factor  = el->FindElementValueAsNumber("ram-air-factor");
  if (el->FindElement("cooling-factor"))
    Cooling_Factor  = el->FindElementValueAsNumber("cooling-factor");
  if (el->FindElement("starter-rpm"))
    StarterRPM  = el->FindElementValueAsNumber("starter-rpm");
  if (el->FindElement("starter-torque"))
    StarterTorque  = el->FindElementValueAsNumber("starter-torque");
  if (el->FindElement("dynamic-fmep"))
    FMEPDynamic= el->FindElementValueAsNumberConvertTo("dynamic-fmep","PA");
  if (el->FindElement("static-fmep"))
    FMEPStatic = el->FindElementValueAsNumberConvertTo("static-fmep","PA");
  if (el->FindElement("peak-piston-speed"))
    PeakMeanPistonSpeed_fps  = el->FindElementValueAsNumber("peak-piston-speed");
  if (el->FindElement("numboostspeeds")) { // Turbo- and super-charging parameters
    BoostSpeeds = (int)el->FindElementValueAsNumber("numboostspeeds");
    if (el->FindElement("boostoverride"))
      BoostOverride = (int)el->FindElementValueAsNumber("boostoverride");
    if (el->FindElement("boostmanual"))
      BoostManual = (int)el->FindElementValueAsNumber("boostmanual");
    if (el->FindElement("takeoffboost"))
      TakeoffBoost = el->FindElementValueAsNumberConvertTo("takeoffboost", "PSI");
    if (el->FindElement("ratedboost1"))
      RatedBoost[0] = el->FindElementValueAsNumberConvertTo("ratedboost1", "PSI");
    if (el->FindElement("ratedboost2"))
      RatedBoost[1] = el->FindElementValueAsNumberConvertTo("ratedboost2", "PSI");
    if (el->FindElement("ratedboost3"))
      RatedBoost[2] = el->FindElementValueAsNumberConvertTo("ratedboost3", "PSI");
    if (el->FindElement("ratedpower1"))
      RatedPower[0] = el->FindElementValueAsNumberConvertTo("ratedpower1", "HP");
    if (el->FindElement("ratedpower2"))
      RatedPower[1] = el->FindElementValueAsNumberConvertTo("ratedpower2", "HP");
    if (el->FindElement("ratedpower3"))
      RatedPower[2] = el->FindElementValueAsNumberConvertTo("ratedpower3", "HP");
    if (el->FindElement("ratedrpm1"))
      RatedRPM[0] = el->FindElementValueAsNumber("ratedrpm1");
    if (el->FindElement("ratedrpm2"))
      RatedRPM[1] = el->FindElementValueAsNumber("ratedrpm2");
    if (el->FindElement("ratedrpm3"))
      RatedRPM[2] = el->FindElementValueAsNumber("ratedrpm3");
    if (el->FindElement("ratedaltitude1"))
      RatedAltitude[0] = el->FindElementValueAsNumberConvertTo("ratedaltitude1", "FT");
    if (el->FindElement("ratedaltitude2"))
      RatedAltitude[1] = el->FindElementValueAsNumberConvertTo("ratedaltitude2", "FT");
    if (el->FindElement("ratedaltitude3"))
      RatedAltitude[2] = el->FindElementValueAsNumberConvertTo("ratedaltitude3", "FT");
  }

  while((table_element = el->FindNextElement("table")) != 0) {
    name = table_element->GetAttributeValue("name");
    try {
      if (name == "COMBUSTION") {
        Lookup_Combustion_Efficiency = new FGTable(PropertyManager, table_element);
      } else if (name == "MIXTURE") {
        Mixture_Efficiency_Correlation = new FGTable(PropertyManager, table_element);
      } else {
        cerr << "Unknown table type: " << name << " in piston engine definition." << endl;
      }
    } catch (std::string str) {
      throw("Error loading piston engine table:" + name + ". " + str);
    }
  }


  volumetric_efficiency_reduced = volumetric_efficiency;

  if(StarterRPM < 0.) StarterRPM = 2*IdleRPM;
  if(StarterTorque < 0)
    StarterTorque = (MaxHP)*0.4; //just a wag.

  displacement_SI = Displacement * in3tom3;
  RatedMeanPistonSpeed_fps =  ( MaxRPM * Stroke) / (360); // AKA 2 * (RPM/60) * ( Stroke / 12) or 2NS

  // Create IFSC to match the engine if not provided
  if (ISFC < 0) {
      double pmep = 29.92 - MaxManifoldPressure_inHg;
      pmep *= inhgtopa  * volumetric_efficiency;
      double fmep = (FMEPDynamic * RatedMeanPistonSpeed_fps * fttom + FMEPStatic);
      double hp_loss = ((pmep + fmep) * displacement_SI * MaxRPM)/(Cycles*22371);
      ISFC = ( 1.1*Displacement * MaxRPM * volumetric_efficiency *(MaxManifoldPressure_inHg / 29.92) ) / (9411 * (MaxHP+hp_loss-StaticFriction_HP));
// cout <<"FMEP: "<< fmep <<" PMEP: "<< pmep << " hp_loss: " <<hp_loss <<endl;
  }
  if ( MaxManifoldPressure_inHg > 29.9 ) {   // Don't allow boosting with a bogus number
      MaxManifoldPressure_inHg = 29.9;
  }
  minMAP = MinManifoldPressure_inHg * inhgtopa;  // inHg to Pa
  maxMAP = MaxManifoldPressure_inHg * inhgtopa;

// For throttle
/*
 * Pm = ( Ze / ( Ze + Zi + Zt ) ) * Pa
 * Where:
 * Pm = Manifold Pressure
 * Pa = Ambient Pressre
 * Ze = engine impedance, Ze is effectively 1 / Mean Piston Speed
 * Zi = airbox impedance
 * Zt = throttle impedance
 *
 * For the calculation below throttle is fully open or Zt = 0
 *
 *
 *
 */
  if(Z_airbox < 0.0){
    double Ze=PeakMeanPistonSpeed_fps/RatedMeanPistonSpeed_fps; // engine impedence
    Z_airbox = (standard_pressure *Ze / maxMAP) - Ze; // impedence of airbox
  }
  // Constant for Throttle impedence
  Z_throttle=(PeakMeanPistonSpeed_fps/((IdleRPM * Stroke) / 360))*(standard_pressure/minMAP - 1) - Z_airbox; 
  //  Z_throttle=(MaxRPM/IdleRPM )*(standard_pressure/minMAP+2); // Constant for Throttle impedence

// Default tables if not provided in the configuration file
  if(Lookup_Combustion_Efficiency == 0) {
    // First column is thi, second is neta (combustion efficiency)
    Lookup_Combustion_Efficiency = new FGTable(12);
    *Lookup_Combustion_Efficiency << 0.00 << 0.980;
    *Lookup_Combustion_Efficiency << 0.90 << 0.980;
    *Lookup_Combustion_Efficiency << 1.00 << 0.970;
    *Lookup_Combustion_Efficiency << 1.05 << 0.950;
    *Lookup_Combustion_Efficiency << 1.10 << 0.900;
    *Lookup_Combustion_Efficiency << 1.15 << 0.850;
    *Lookup_Combustion_Efficiency << 1.20 << 0.790;
    *Lookup_Combustion_Efficiency << 1.30 << 0.700;
    *Lookup_Combustion_Efficiency << 1.40 << 0.630;
    *Lookup_Combustion_Efficiency << 1.50 << 0.570;
    *Lookup_Combustion_Efficiency << 1.60 << 0.525;
    *Lookup_Combustion_Efficiency << 2.00 << 0.345;
  }

    // First column is Fuel/Air Ratio, second is neta (mixture efficiency)
  if( Mixture_Efficiency_Correlation == 0) {
    Mixture_Efficiency_Correlation = new FGTable(15);
    *Mixture_Efficiency_Correlation << 0.05000 << 0.00000;
    *Mixture_Efficiency_Correlation << 0.05137 << 0.00862;
    *Mixture_Efficiency_Correlation << 0.05179 << 0.21552;
    *Mixture_Efficiency_Correlation << 0.05430 << 0.48276;
    *Mixture_Efficiency_Correlation << 0.05842 << 0.70690;
    *Mixture_Efficiency_Correlation << 0.06312 << 0.83621;
    *Mixture_Efficiency_Correlation << 0.06942 << 0.93103;
    *Mixture_Efficiency_Correlation << 0.07786 << 1.00000;
    *Mixture_Efficiency_Correlation << 0.08845 << 1.00000;
    *Mixture_Efficiency_Correlation << 0.09270 << 0.98276;
    *Mixture_Efficiency_Correlation << 0.10120 << 0.93103;
    *Mixture_Efficiency_Correlation << 0.11455 << 0.72414;
    *Mixture_Efficiency_Correlation << 0.12158 << 0.45690;
    *Mixture_Efficiency_Correlation << 0.12435 << 0.23276;
    *Mixture_Efficiency_Correlation << 0.12500 << 0.00000;
  }

  string property_name, base_property_name;
  base_property_name = CreateIndexedPropertyName("propulsion/engine", EngineNumber);
  property_name = base_property_name + "/power-hp";
  PropertyManager->Tie(property_name, &HP);
  property_name = base_property_name + "/bsfc-lbs_hphr";
  PropertyManager->Tie(property_name, &ISFC);
  property_name = base_property_name + "/starter-norm";
  PropertyManager->Tie(property_name, &StarterGain);
  property_name = base_property_name + "/volumetric-efficiency";
  PropertyManager->Tie(property_name, &volumetric_efficiency);
  property_name = base_property_name + "/map-pa";
  PropertyManager->Tie(property_name, &MAP);
  property_name = base_property_name + "/map-inhg";
  PropertyManager->Tie(property_name, &ManifoldPressure_inHg);
  property_name = base_property_name + "/air-intake-impedance-factor";
  PropertyManager->Tie(property_name, &Z_airbox);
  property_name = base_property_name + "/ram-air-factor";
  PropertyManager->Tie(property_name, &Ram_Air_Factor);
  property_name = base_property_name + "/cooling-factor";
  PropertyManager->Tie(property_name, &Cooling_Factor);
  property_name = base_property_name + "/boost-speed";
  PropertyManager->Tie(property_name, &BoostSpeed);
  property_name = base_property_name + "/cht-degF";
  PropertyManager->Tie(property_name, this, &FGPiston::getCylinderHeadTemp_degF);
  property_name = base_property_name + "/oil-temperature-degF";
  PropertyManager->Tie(property_name, this, &FGPiston::getOilTemp_degF);
  property_name = base_property_name + "/oil-pressure-psi";
  PropertyManager->Tie(property_name, this, &FGPiston::getOilPressure_psi);
  property_name = base_property_name + "/egt-degF";
  PropertyManager->Tie(property_name, this, &FGPiston::getExhaustGasTemp_degF);

  // Set up and sanity-check the turbo/supercharging configuration based on the input values.
  if (TakeoffBoost > RatedBoost[0]) bTakeoffBoost = true;
  for (i=0; i<BoostSpeeds; ++i) {
    bool bad = false;
    if (RatedBoost[i] <= 0.0) bad = true;
    if (RatedPower[i] <= 0.0) bad = true;
    if (RatedAltitude[i] < 0.0) bad = true;  // 0.0 is deliberately allowed - this corresponds to unregulated supercharging.
    if (i > 0 && RatedAltitude[i] < RatedAltitude[i - 1]) bad = true;
    if (bad) {
      // We can't recover from the above - don't use this supercharger speed.
      BoostSpeeds--;
      // TODO - put out a massive error message!
      break;
    }
    // Now sanity-check stuff that is recoverable.
    if (i < BoostSpeeds - 1) {
      if (BoostSwitchAltitude[i] < RatedAltitude[i]) {
        // TODO - put out an error message
        // But we can also make a reasonable estimate, as below.
        BoostSwitchAltitude[i] = RatedAltitude[i] + 1000;
      }
      BoostSwitchPressure[i] = GetStdPressure100K(BoostSwitchAltitude[i]) * psftopa;
      //cout << "BoostSwitchAlt = " << BoostSwitchAltitude[i] << ", pressure = " << BoostSwitchPressure[i] << '\n';
      // Assume there is some hysteresis on the supercharger gear switch, and guess the value for now
      BoostSwitchHysteresis = 1000;
    }
    // Now work out the supercharger pressure multiplier of this speed from the rated boost and altitude.
    RatedMAP[i] = standard_pressure + RatedBoost[i] * 6895;  // psi*6895 = Pa.
    // Sometimes a separate BCV setting for takeoff or extra power is fitted.
    if (TakeoffBoost > RatedBoost[0]) {
      // Assume that the effect on the BCV is the same whichever speed is in use.
      TakeoffMAP[i] = RatedMAP[i] + ((TakeoffBoost - RatedBoost[0]) * 6895);
      bTakeoffBoost = true;
    } else {
      TakeoffMAP[i] = RatedMAP[i];
      bTakeoffBoost = false;
    }
    BoostMul[i] = RatedMAP[i] / (GetStdPressure100K(RatedAltitude[i]) * psftopa);

  }

  if (BoostSpeeds > 0) {
    Boosted = true;
    BoostSpeed = 0;
  }
  bBoostOverride = (BoostOverride == 1 ? true : false);
  bBoostManual   = (BoostManual   == 1 ? true : false);
  Debug(0); // Call Debug() routine from constructor if needed
}
コード例 #20
0
ファイル: Constrain.c プロジェクト: MARFMS/chiquitico
main(int argc, char *argv[])
{
   InitializeConstrainer(argc,argv);
   Constrain();
   exit(0);
}