Beispiel #1
0
void Power::Propeller::ReloadParams(SimpleXMLTransfer* xml)
{
  Gearing::ReloadParams(xml);
  
  SimpleXMLTransfer* prop;
  bool               fExtern = true;
  
  if (xml->indexOfAttribute("filename") >= 0)
  {
    prop = new SimpleXMLTransfer(FileSysTools::getDataPath("models/propeller/" + xml->getString("filename") + ".xml", true));
  }
  else
  {
    prop    = xml;
    fExtern = false;
  }
  
  // Der Sturz wird in jedem Fall aus der Modelldatei gelesen, ansonsten muss man ja eine 
  // Propellerdatei fuer jeden Sturz extra haben.
  CalcDownthrust(xml);
      
  D          = prop->getDouble("D");
  H          = prop->getDouble("H");
  J          = prop->getDouble("J");
  omega_fold = prop->attributeAsDouble("n_fold", -1)*2*M_PI;
  
  std::cout << "      Propeller: D=" << D << " m, H=" << H << " m, J=" << J << " kg m^2";
   
  if (fExtern)
    delete prop;    
}
Beispiel #2
0
void Power::Propeller::CalcDownthrust(SimpleXMLTransfer* xml)
{
  int idx = xml->indexOfChild("pos");
  if (idx < 0)
  {
    dirThrust = CRRCMath::Vector3(1, 0, 0);
    mulForce  = CRRCMath::Vector3(1, 0, 0);
    mulMoment = CRRCMath::Vector3(0, 0, 0);
  }
  else    
  {
    SimpleXMLTransfer* sxtpos     = xml->getChildAt(idx);
    double             downthrust = M_PI * sxtpos->getDouble("downthrust", 0) / 180;      
                       dirThrust  = CRRCMath::Vector3(cos(downthrust), 0, sin(downthrust));
    CRRCMath::Vector3  pos        = CRRCMath::Vector3(sxtpos->getDouble("x", 0),
                                                      0,
                                                      sxtpos->getDouble("z", 0));      
    CRRCMath::Vector3 dirForce   = pos * (1/pos.length());
    
    // Split thrust vector into a part parallel to dirForce and a part parallel to dirMoment:
    //   dirThrust   = a * dirForce   + b * dirMoment
    // After simplifying all this (and using the variable expressions above) the solution boils down to:
    double a = sin(downthrust) * dirForce.r[2] + cos(downthrust) * dirForce.r[0];
    double b = cos(downthrust) * dirForce.r[2] - sin(downthrust) * dirForce.r[0];
    
    mulForce  = dirForce * a;
    mulMoment = CRRCMath::Vector3(0, b * pos.length(), 0);    
  }
  mulForce.print("mulForce=", ", ");
  mulMoment.print("mulMoment=", "\n");
}
Beispiel #3
0
void Power::Propeller::ReloadParams_automagic(SimpleXMLTransfer* xml)
{
  SimpleXMLTransfer* p = xml->getChild("battery.shaft.propeller");
  
  D = p->getDouble("D");
  H = p->getDouble("H");
  J = p->getDouble("J");
  
  double F = xml->getDouble("F");
  double V = xml->getDouble("V");
  

  // Der Sturz wird in jedem Fall aus der Modelldatei gelesen, ansonsten muss man ja eine 
  // Propellerdatei fuer jeden Sturz extra haben.
  CalcDownthrust(p);
  
  {
    // Calculate rotational speed and torque needed:
    //  F = M_PI * 0.25 * D*D * RHO * (V_X + filter.val/2) * filter.val * ETA_PROP;
    //  F = M_PI * 0.25 * D*D * RHO * (V + (Hn-V)/2) * (Hn-V) * ETA_PROP;
    //  F = M_PI * 0.25 * D*D * RHO * (V/2 + Hn/2) * (Hn-V) * ETA_PROP;
    double n = sqrt( (8*F/(M_PI*D*D*RHO*ETA_PROP)) + V*V)/H;    
    double M = F * (V + (V + H*n)/2) / (2*M_PI*n) * i;
    
    // Save these values so the engine can adjust itself to them:
    p->setAttribute("automagic.n_P", doubleToString(n));
    p->setAttribute("automagic.M_P", doubleToString(M));
  }
  
  omega_fold = p->attributeAsDouble("n_fold", -1)*2*M_PI;
}
Beispiel #4
0
/** \brief Initialize the mixer from a config file.
 *
 *  The mixer object will be initialized from the given config file.
 *  This file may contain more than one branch with interface settings,
 *  so the name of the child has to be specified.
 */
int T_TX_Mixer::init(SimpleXMLTransfer* cfg, std::string child)
{
#if DEBUG_TX_INTERFACE > 0
  printf("T_TX_Mixer::init(cfg, child)\n");
  printf(" <-- %s\n", child.c_str());
#endif

  SimpleXMLTransfer* mixer;
  SimpleXMLTransfer* item;
  SimpleXMLTransfer* inter;

  // store the child's name for writing back the settings
  child_in_cfg = child;

  printf("Loading mixer settings from %s:\n", child.c_str());
  try
  {
    inter = cfg->getChild(child, true);
    mixer = inter->getChild("mixer", true);

    enabled = mixer->attributeAsInt("enabled", 1);
    dr_enabled = mixer->attributeAsInt("dr_enabled", 0);
 
    for (int i = T_AxisMapper::AILERON; i <= T_AxisMapper::PITCH; i++)
    { 
      item = mixer->getChild(Global::inputDev->AxisStringsXML[i], true);

      trim_val[i]   = item->getDouble("trim",   0.0);
      nrate_val[i]  = item->getDouble("nrate",  1.0);
      srate_val[i]  = item->getDouble("srate",  1.0);
      exp_val[i]    = item->getDouble("exp",    0.0);

      mtravel_val[i] = item->getDouble("mtravel", -0.5);
      ptravel_val[i] = item->getDouble("ptravel", 0.5);
    }
      
    for (int i = 0; i < T_TX_Mixer::NUM_MIXERS; i++)
    { 
      item = mixer->getChild(Global::inputDev->MixerStringsXML[i], true);
      mixer_enabled[i] = item->attributeAsInt("enabled", 0);
      mixer_src[i]     = item->getDouble("src", T_AxisMapper::NOTHING);
      mixer_dst[i]     = item->getDouble("dst", T_AxisMapper::NOTHING);
      mixer_val[i]     = item->getDouble("val", 0.0);
    }
  }
  catch (XMLException e)
  {
    errMsg = e.what();
    return 1;
  }

  return 0;
}
void CRRCAirplaneLaRCSim::initSound(SimpleXMLTransfer* xml)
{
  SimpleXMLTransfer* cfg = XMLModelFile::getConfig(xml);
  SimpleXMLTransfer* sndcfg = cfg->getChild("sound", true);
  int children = sndcfg->getChildCount();
  int units = sndcfg->getInt("units", 0);
  
  for (int i = 0; i < children; i++)
  {
    SimpleXMLTransfer *child = sndcfg->getChildAt(i);
    std::string name = child->getName();
    
    if (name.compare("sample") == 0)
    {
      T_AirplaneSound *sample;

      // assemble relative path
      std::string soundfile;
      soundfile           = child->attribute("filename");

      // other sound attributes
      int sound_type      = child->getInt("type", SOUND_TYPE_GLIDER);
      double dPitchFactor = child->getDouble("pitchfactor", 0.002);
      double dMaxVolume   = child->getDouble("maxvolume", 1.0);
  
      if (dMaxVolume < 0.0)
      {
        dMaxVolume = 0.0;
      }
      else if (dMaxVolume > 1.0)
      {
        dMaxVolume = 1.0;
      }

  //~ if (cfg->indexOfChild("power") < 0)
    //~ max_thrust = 0;
  //~ else
    //~ max_thrust = 1;
  
      if (soundfile != "")
      {
        // Get full path (considering search paths). 
        soundfile = FileSysTools::getDataPath("sounds/" + soundfile);
      }
      
      // File ok? Use default otherwise.
      if (!FileSysTools::fileExists(soundfile))
        soundfile = FileSysTools::getDataPath("sounds/fan.wav");
    
      std::cout << "soundfile: " << soundfile << "\n";
      //~ std::cout << "max_thrust: " << max_thrust << "\n";
      std::cout << "soundserver: " << Global::soundserver << "\n";
  
      // Only make noise if a sound file is available
      if (soundfile != "" && Global::soundserver != (CRRCAudioServer*)0)
      {        
        std::cout << "Using airplane sound " << soundfile << ", type " << sound_type << ", max vol " << dMaxVolume << std::endl;
        
        if (sound_type == SOUND_TYPE_GLIDER)
        {
          T_GliderSound *glidersound;
          float flMinRelV, flMaxRelV, flMaxDist;
          flMinRelV = (float)child->getDouble("v_min", 1.5);
          flMaxRelV = (float)child->getDouble("v_max", 4.0);
          flMaxDist = (float)child->getDouble("dist_max", 300);
          
          if (units == 1)
          {
            // convert from metric units to ft.
            flMaxDist *= M_TO_FT;
          }
          
          glidersound = new T_GliderSound(soundfile.c_str(), Global::soundserver->getAudioSpec());
          glidersound->setMinRelVelocity(flMinRelV);
          glidersound->setMaxRelVelocity(flMaxRelV);
          glidersound->setMaxDistanceFeet(flMaxDist);
          sample = glidersound;
        }
        else
        {
          sample = new T_EngineSound(soundfile.c_str(), Global::soundserver->getAudioSpec());
        }
                
        sample->setType(sound_type);
        sample->setPitchFactor(dPitchFactor);
        sample->setMaxVolume(dMaxVolume);
        sample->setChannel(Global::soundserver->playSample((T_SoundSample*)sample));
        sound.push_back(sample);
      }
    }
  }
}
/**
 *  Create a CRRCControlSurfaceAnimation object
 *
 *  Initialize the animation from an 
 *  <animation type="ControlSurface"> tag
 */
CRRCControlSurfaceAnimation::CRRCControlSurfaceAnimation(SimpleXMLTransfer *xml)
 : CRRCAnimation(new ssgTransform()), fallback_data(0.0f),
   eventAdapter(this, &CRRCControlSurfaceAnimation::axisValueCallback, Event::Input),
    aileron(0.0f), elevator(0.0f), rudder(0.0f), throttle(0.0f),
    spoiler(0.0f), flap(0.0f), retract(0.0f), pitch(0.0f)
{
  bool failed = false;
  
  // evaluate <object> tag
  SimpleXMLTransfer *map = xml->getChild("object", true);
  symbolic_name = map->getString("name", "no_name_set");
  max_angle = (float)(map->getDouble("max_angle", 0.0) * SG_RADIANS_TO_DEGREES);
  abs_max_angle = (float)fabs((double)max_angle);

  // find hinges and evaluate all <control> tags
  int num_controls = 0;
  int num_hinges = 0;
  for (int i = 0; i < xml->getChildCount(); i++)
  {
    SimpleXMLTransfer *child = xml->getChildAt(i);
    if (child->getName() == "hinge")
    {
      // found a <hinge> child
      sgVec3 pos;
      pos[SG_X] = (float)(-1 * child->getDouble("y", 0.0));
      pos[SG_Y] = (float)(-1 * child->getDouble("x", 0.0));
      pos[SG_Z] = (float)(-1 * child->getDouble("z", 0.0));
      if (num_hinges == 0)
      {
        sgCopyVec3(hinge_1, pos);
      }
      else if (num_hinges == 1)
      {
        sgCopyVec3(hinge_2, pos);
      }
      num_hinges++;
    }
    else if (child->getName() == "control")
    {
      // found a <control> child
      // The "*2" factor for each gain value scales the control input
      // values from -0.5...+0.5 to -1.0...+1.0. This saves one
      // float multiplication per mapping in the runtime update() routine.
      std::string mapping = child->getString("mapping", "NOTHING");
      float gain = (float)child->getDouble("gain", 1.0);
      if (mapping == "ELEVATOR")
      {
        datasource.push_back(&elevator);
        source_gain.push_back(gain * 2);
        num_controls++;
      }
      else if (mapping == "AILERON")
      {
        datasource.push_back(&aileron);
        source_gain.push_back(gain * 2);
        num_controls++;
      }
      else if (mapping == "THROTTLE")
      {
        datasource.push_back(&throttle);
        source_gain.push_back(gain * 2);
        num_controls++;
      }
      else if (mapping == "RUDDER")
      {
        datasource.push_back(&rudder);
        source_gain.push_back(gain * 2);
        num_controls++;
      }
      else if (mapping == "FLAP")
      {
        datasource.push_back(&flap);
        source_gain.push_back(gain * 2);
        num_controls++;
      }
      else if (mapping == "SPOILER")
      {
        datasource.push_back(&spoiler);
        source_gain.push_back(gain * 2);
        num_controls++;
      }
      else if (mapping == "RETRACT")
      {
        datasource.push_back(&retract);
        source_gain.push_back(gain * 2);
        num_controls++;
      }
      else if (mapping == "PITCH")
      {
        datasource.push_back(&pitch);
        source_gain.push_back(gain * 2);
        num_controls++;
      }
      else
      {
        std::cerr << "ControlSurfaceAnimation: ignoring <control> tag without mapping." << std::endl;
      }
      
    }
  }

  if (num_controls < 1)
  {
    std::cerr << "ControlSurfaceAnimation: found animation without proper <control> tag. Animation disabled." << std::endl;
    failed = true;
  }

  if (num_hinges < 2)
  {
    std::cerr << "ControlSurfaceAnimation: Must specify exactly two hinges!" << std::endl;
    failed = true;
  }
  else
  {
    if (num_hinges > 2)
    {
      std::cerr << "ControlSurfaceAnimation: Must specify exactly two hinges!" << std::endl;
      std::cerr << "ControlSurfaceAnimation: Ignoring excessive hinge tag(s)." << std::endl;
    }
    sgSubVec3(axis, hinge_2, hinge_1);
    if (sgLengthVec3(axis) < 0.001)
    {
      std::cerr << "ControlSurfaceAnimation: Insufficient spacing between hinges!" << std::endl;
      failed = true;
    }
  }

  if (failed)
  {
    std::cerr << "ControlSurfaceAnimation: Animation setup failed." << std::endl;
    // set to some non-critical defaults
    datasource.resize(1);
    datasource[0] = &fallback_data;
    source_gain.resize(1);
    source_gain[0] = 1.0;
    sgSetVec3(hinge_1, 0.0f, 0.0f, 0.0f);
    sgSetVec3(hinge_2, 1.0f, 0.0f, 0.0f);
    sgSubVec3(axis, hinge_2, hinge_1);
  }
  
  sgMakeIdentMat4(move_to_origin);
  move_to_origin[3][0] = -hinge_1[0];
  move_to_origin[3][1] = -hinge_1[1];
  move_to_origin[3][2] = -hinge_1[2];

  sgMakeTransMat4(move_back, hinge_1);

  realInit();
}
void CRRC_AirplaneSim_MCopter01::LoadFromXML(SimpleXMLTransfer* xml, int nVerbosity)
{
  if (xml->getString("type").compare("mcopter01") != 0 ||
      xml->getInt("version") != 1)
  {
    throw XMLException("file is not for mcopter01");
  }    
    
  SimpleXMLTransfer* i;
  SimpleXMLTransfer* cfg = XMLModelFile::getConfig(xml);  
  
  {
    double to_slug;
    double to_slug_ft_ft;
    
    i = cfg->getChild("mass_inertia");
    switch (i->getInt("units"))
    {
     case 0:    
      to_slug       = 1;
      to_slug_ft_ft = 1;
      break;
     case 1:
      to_slug       = KG_TO_SLUG;
      to_slug_ft_ft = KG_M_M_TO_SLUG_FT_FT;
      break;
     default:
      {
        throw std::runtime_error("Unknown units in mass_inertia");
      }
      break;
    }
    Mass  = i->getDouble("Mass") * to_slug;
    I_xx  = i->getDouble("I_xx") * to_slug_ft_ft;
    I_yy  = i->getDouble("I_yy") * to_slug_ft_ft;
    I_zz  = i->getDouble("I_zz") * to_slug_ft_ft;
    I_xz  = i->getDouble("I_xz") * to_slug_ft_ft;
  }
    
  {
    speed_damp       = cfg->getDouble("aero.speed.damp");
    roll_damp1       = cfg->getDouble("aero.roll.damp1", 0);
    yaw_damp1        = cfg->getDouble("aero.yaw.damp1",  0);    
    roll_damp2       = cfg->getDouble("aero.roll.damp2", 0);    
    yaw_damp2        = cfg->getDouble("aero.yaw.damp2",  0);    
        
    yaw_dist         = cfg->getDouble("aero.yaw.dist", 0);    
    roll_dist        = cfg->getDouble("aero.roll.dist", 0);
    pitch_dist       = cfg->getDouble("aero.pitch.dist", roll_dist);
    
    // The ground effect parameters should be quite independent of the helicopter
    // parameters...shouldn't they? However, they can be adjusted.
    dGEDistMul  = xml->getDouble("GroundEffect.dist.mul",  1.5);

    {
      double tau  = xml->getDouble("Disturbance.tau_filter", 0.2);
      dist_t_init = xml->getDouble("Disturbance.time",       0.2);

      filt_rnd_yaw.SetTau(tau);
      filt_rnd_roll.SetTau(tau);
      filt_rnd_pitch.SetTau(tau);
    }
  }  
  
  wheels.init(xml, 0);
  dRotorRadius = wheels.getWingspan()*0.5;
  dRotorZ      = wheels.getZHigh();

  wheels.init(xml, 0);
  dRotorRadius = wheels.getWingspan()*0.5;
  dRotorZ      = wheels.getZHigh();

  props.clear();
  i = cfg->getChild("aero.props");
  for (int n=0; n<i->getChildCount(); n++)
    props.push_back(Propdata(i->getChildAt(n)));

  if (power.size() == 0)
  {    
    for (unsigned int n=0; n<props.size(); n++)
      power.push_back(new Power::Power(cfg, nVerbosity));
    dURef = 0.7 * cfg->getDouble("power.battery.U_0");
  }
  else
  {
    for (unsigned int n=0; n<power.size(); n++)
      power[n]->ReloadParams(cfg, nVerbosity);
  }
  
  controllers.clear();  
  Controller::LoadList(cfg->getChild("controllers"), controllers);  
}
Beispiel #8
0
/**
 * Create a HardPointRotation
 *
 * \param xml <animation> part of the model file that contains the
 *            description of the animation
 */
HardPointRotation::HardPointRotation(SimpleXMLTransfer *xml, TSimInputs const& in)
{
  bool failed = false;
  
  // evaluate <object> tag
  SimpleXMLTransfer *map = xml->getChild("object", true);
  symbolic_name = map->getString("name", "no_name_set");
  max_angle_rad = (float)map->getDouble("max_angle", 0.0);
  abs_max_angle_rad = (float)fabs((double)max_angle_rad);

  // find hinges and evaluate all <control> tags
  int num_controls = 0;
  int num_hinges = 0;
  for (int i = 0; i < xml->getChildCount(); i++)
  {
    SimpleXMLTransfer *child = xml->getChildAt(i);
    if (child->getName() == "hinge")
    {
      // found a <hinge> child
      CRRCMath::Vector3 pos;
      pos.r[0] = (float)(child->getDouble("x", 0.0));
      pos.r[1] = (float)(child->getDouble("y", 0.0));
      pos.r[2] = (float)(child->getDouble("z", 0.0));
      if (num_hinges < 2)
      {
        hinge[num_hinges] = pos;
      }
      num_hinges++;
    }
    else if (child->getName() == "control")
    {
      // found a <control> child
      // The "*2" factor for each gain value scales the control input
      // values from -0.5...+0.5 to -1.0...+1.0. This saves one
      // float multiplication per mapping in the runtime update() routine.
      // NB: unsigned control (throttle, spoiler, retract) are not scaled,
      //     since control input is already in range 0.0...+1.0
      std::string mapping = child->getString("mapping", "NOTHING");
      float gain = (float)child->getDouble("gain", 1.0);
      std::cout << "  mapped to " << mapping << " with gain " << gain;
      std::cout << " and max_angle_rad " << max_angle_rad << std::endl;
      if (mapping == "ELEVATOR")
      {
        datasource.push_back(&in.elevator);
        source_gain.push_back(gain * 2);
        num_controls++;
      }
      else if (mapping == "AILERON")
      {
        datasource.push_back(&in.aileron);
        source_gain.push_back(gain * 2);
        num_controls++;
      }
      else if (mapping == "THROTTLE")
      {
        datasource.push_back(&in.throttle);
        source_gain.push_back(gain);
        num_controls++;
      }
      else if (mapping == "RUDDER")
      {
        datasource.push_back(&in.rudder);
        source_gain.push_back(gain * 2);
        num_controls++;
      }
      else if (mapping == "FLAP")
      {
        datasource.push_back(&in.flap);
        source_gain.push_back(gain * 2);
        num_controls++;
      }
      else if (mapping == "SPOILER")
      {
        datasource.push_back(&in.spoiler);
        source_gain.push_back(gain);
        num_controls++;
      }
      else if (mapping == "RETRACT")
      {
        datasource.push_back(&in.retract);
        source_gain.push_back(gain);
        num_controls++;
      }
      else if (mapping == "PITCH")
      {
        datasource.push_back(&in.pitch);
        source_gain.push_back(gain * 2);
        num_controls++;
      }
      else
      {
        fprintf(stderr, "HardPointRotation: ignoring <control> tag without mapping.\n");
      }
      
    }
  }

  if (num_controls < 1)
  {
    fprintf(stderr, "HardPointRotation: found animation without proper <control> tag. Animation disabled.\n");
    failed = true;
  }

  if (num_hinges < 2)
  {
    fprintf(stderr, "HardPointRotation: Must specify exactly two hinges!\n");
    failed = true;
  }
  else
  {
    if (num_hinges > 2)
    {
      fprintf(stderr, "HardPointRotation: Must specify exactly two hinges!\n");
      fprintf(stderr, "HardPointRotation: Ignoring excessive hinge tag(s).\n");
    }
    axis = hinge[1] - hinge[0];
    if (axis.length() < 0.001)
    {
      fprintf(stderr, "HardPointRotation: Insufficient spacing between hinges!\n");
      failed = true;
    }
  }

  if (failed)
  {
    fprintf(stderr, "HardPointRotation: Animation setup failed.\n");
    // set to some non-critical defaults
    datasource.resize(1);
    datasource[0] = &fallback_data;
    source_gain.resize(1);
    source_gain[0] = 1.0;
    hinge[0] = CRRCMath::Vector3(0.0, 0.0, 0.0);
    hinge[1] = CRRCMath::Vector3(1.0, 0.0, 0.0);
    axis = hinge[1] - hinge[0];
  }
  else
  {
    std::cerr << "HardPointRotation: set up animated hardpoint ";
    std::cerr << symbolic_name << std::endl;
  }
  
  move_orig.makeTranslation(hinge[0] * -1);
  move_back.makeTranslation(hinge[0]);

  //~ realInit();

}