Пример #1
0
void Robots::AddRobot(std::string robotfilename)
{
  Robot* robot = new Robot();

  // 
  robot->fi = new ModRobotInterface();
  robot->fi->loadAirplane(robotfilename.c_str(), (FDMEnviroment*)0, (SimpleXMLTransfer*)0);  
  if (robot->fi->robot)
  {    
    SimpleXMLTransfer* header = robot->fi->robot->GetHeader();
    
    std::string filename = FileSysTools::getDataPath(header->getString("airplane.file"));
    
    SimpleXMLTransfer* xml = new SimpleXMLTransfer(filename);
    XMLModelFile::SetGraphics(xml, header->getInt("airplane.graphics"));
    SimpleXMLTransfer* graphics = XMLModelFile::getGraphics(xml);
    
    // 
    robot->vis_id = Video::new_visualization("objects/" + graphics->attribute("model"),
                                             "textures",
                                             CRRCMath::Vector3(), // todo
                                             xml);
  
    list.push_back(robot);
  }
}
Пример #2
0
void T_AxisMapper::init(SimpleXMLTransfer* cfgfile, std::string childname)
{
#if DEBUG_TX_INTERFACE > 0
  printf("T_AxisMapper::init(cfg, child)\n");
  printf(" <-- %s\n", childname.c_str());
#endif
  SimpleXMLTransfer* inter;
  SimpleXMLTransfer* bindings;
  SimpleXMLTransfer* group;
  SimpleXMLTransfer* item;
  
  child_in_cfg = childname;

  // try to load config
  try
  {
    inter = cfgfile->getChild(childname, true);
    bindings  = inter->getChild("bindings", true);
    group     = bindings->getChild("axes", true);
  
    for (int i = T_AxisMapper::AILERON; i <= T_AxisMapper::PITCH; i++)
    {
      int default_axis = -1;
      float default_polarity = 1.0;

      // special handling for some default values
      if (i == T_AxisMapper::AILERON)
      {
        default_axis = 0;
      }
      else if (i == T_AxisMapper::ELEVATOR)
      {
        default_axis = 1;
        if (iface->inputMethod() != T_TX_Interface::eIM_joystick)
        {
          default_polarity = -1.0;
        }
      }
      
      item = group->getChild(Global::inputDev->AxisStringsXML[i], true);
      c_func[i] = item->attributeAsInt("axis", default_axis);
      c_inv[i]  = item->attributeAsDouble("polarity", default_polarity);
    }

    std::string radio = 
      strU(bindings->attribute("radio_type", RadioTypeStrings[CUSTOM]));

    for (int n=0; n < NR_OF_RADIO_TYPES; n++)
    {
      if (radio.compare(strU(RadioTypeStrings[n])) == 0)
      {
        setRadioType(n);
      }
    }
  }
  catch (XMLException e)
  {
    fprintf(stderr, "*** T_AxisMapper: XMLException: %s\n", e.what());
  }
}
Пример #3
0
void T_AxisMapper::putBackIntoCfg(SimpleXMLTransfer* cfgfile)
{
#if DEBUG_TX_INTERFACE > 0
  printf("T_AxisMapper::putBackIntoCfg(SimpleXMLTransfer* config)\n");
  printf(" --> %s\n", child_in_cfg.c_str());
#endif
  SimpleXMLTransfer* item;
  SimpleXMLTransfer* group;
  SimpleXMLTransfer* item2;

  try
  {
    item = cfgfile->getChild(child_in_cfg);
    group = item->getChild("bindings.axes");

    for (int i = T_AxisMapper::AILERON; i <= T_AxisMapper::PITCH; i++)
    {
      item2 = group->getChild(Global::inputDev->AxisStringsXML[i], true);
      item2->setAttributeOverwrite("axis", c_func[i]);
      item2->setAttributeOverwrite("polarity", doubleToString(c_inv[i]));
    }
  
    item2 = item->getChild("bindings");
    item2->setAttributeOverwrite("radio_type", RadioTypeStrings[radio_type]);
  }
  catch (XMLException e)
  {
    fprintf(stderr, "*** T_AxisMapper: XMLException: %s\n", e.what());
  }
}
Пример #4
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;    
}
Пример #5
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");
}
Пример #6
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;
}
Пример #7
0
/** \brief Add animations to a model
 *
 *  This method reads animation description tags from a model file
 *  and tries to add the corresponding animations to the 3D model.
 *
 *  \todo Right now there's only one type of animation: movable control
 *  surfaces. Therefore this method receives a pointer to the control
 *  input class. If animations are added that need a different kind of
 *  input for their update() method, we need to decide how to pass all
 *  this stuff to initAnimations().
 *
 *  \param  model_file    XML model description file
 *  \param  model         scenegraph of the 3D model
 */
void initAnimations(SimpleXMLTransfer *model_file, ssgEntity* model)
{
  SimpleXMLTransfer *animations = model_file->getChild("animations", true);
  int num_anims = animations->getChildCount();
  std::cout << "initAnimations: found " << num_anims << " children" << std::endl;
  
  for (int i = 0; i < num_anims; i++)
  {
    SimpleXMLTransfer *animation = animations->getChildAt(i);
    createAnimation(animation, model);
  }
}
Пример #8
0
void T_TX_InterfaceSerPIC::putBackIntoCfg (SimpleXMLTransfer *config)/*{{{*/
{
#if DEBUG_TX_INTERFACE > 0
  std::cout << "T_TX_InterfaceSerPIC::putBackIntoCfg(SimpleXMLTransfer *config)" << std::endl;
#endif

  // Store the port settings
  T_TX_InterfaceSerial::putBackIntoCfg(config);

  // Store additional settings
  SimpleXMLTransfer *port = config->getChild(getXmlChildName() + ".port", true);
  port->setAttributeOverwrite ("sync", ucSyncByte);
  port->setAttributeOverwrite ("button_channel", iSPIC_ButtonChannel);
}
Пример #9
0
void T_Calibration::putBackIntoCfg(SimpleXMLTransfer* cfgfile)
{
#if DEBUG_TX_INTERFACE > 0
  printf("T_Calibration::putBackIntoCfg(cfg)\n");
  printf(" --> %s\n", child_in_cfg.c_str());
#endif
  int size;
  SimpleXMLTransfer* item;
  SimpleXMLTransfer* group;
  SimpleXMLTransfer* item2;

  item = cfgfile->getChild(child_in_cfg);
  group = item->getChild("calibration");
  group->setAttributeOverwrite("version", "2");

  // clean list
  size = group->getChildCount();
  for (int n = 0; n < size; n++)
  {
    item2 = group->getChildAt(0);
    group->removeChildAt(0);
    delete item2;
  }
  // create new list
  for (int n = 0; n < TX_MAXAXIS; n++)
  {
    item2 = new SimpleXMLTransfer();
    item2->setName("axis");
    item2->addAttribute("val_min", doubleToString(val_min[n]));
    item2->addAttribute("val_mid", doubleToString(val_mid[n]));
    item2->addAttribute("val_max", doubleToString(val_max[n]));
    group->addChild(item2);
  }
}
Пример #10
0
Power::Shaft::Shaft(SimpleXMLTransfer* xml)
{    
  for (int n=0; n<xml->getChildCount(); n++)
  {
    SimpleXMLTransfer* it = xml->getChildAt(n);
    Gearing*           s  = (Gearing*)0;
    if (it->getName().compare("engine") == 0)
      s = new Engine_DCM();
    else if (it->getName().compare("propeller") == 0)
      s = new Propeller();
    else if (it->getName().compare("simplethrust") == 0)
      s = new SimpleThrust();
    if (s != (Gearing*)0)
      gear.push_back(s);
  }
}
Пример #11
0
CRRCAirplaneV2::CRRCAirplaneV2(SimpleXMLTransfer* xml)
{
  printf("CRRCAirplaneV2(xml)\n");

  // initialize the airplane's sound
  initSound(xml);    

  // initialize the visual representation
  // first collect all relevant information from the model file
  std::string s;      
  s = XMLModelFile::getGraphics(xml)->getString("model");
        
  // Offset of center of gravity
  CRRCMath::Vector3  pCG;         
  pCG = CRRCMath::Vector3(0, 0, 0);
  if (xml->indexOfChild("CG") >= 0)
  {
    SimpleXMLTransfer* i;
    i = xml->getChild("CG");
    pCG.r[0] = i->attributeAsDouble("x", 0);
    pCG.r[1] = i->attributeAsDouble("y", 0);
    pCG.r[2] = i->attributeAsDouble("z", 0);
    
    if (i->attributeAsInt("units") == 1)
      pCG *= M_TO_FT;
  }
  // plib automatically loads the texture file, but it does not know which directory to use.
  // where is the object file?
  std::string    of  = FileSysTools::getDataPath("objects/" + s);
  // compile and set relative texture path
  std::string    tp  = of.substr(0, of.length()-s.length()-1-7) + "textures";    

  lVisID = Video::new_visualization(of, tp, pCG, xml);
  
  if (lVisID == INVALID_AIRPLANE_VISUALIZATION)
  {
    std::string msg = "Unable to open airplane model file \"";
    msg += s;
    msg += "\"\nspecified in \"";
    msg += xml->getSourceDescr();
    msg += "\"";
    throw std::runtime_error(msg);
  }

}
Пример #12
0
/**
 * Load the airplane specified in configfile. Throw a
 * std::runtime_error on failure.
 */
void Aircraft::load(SimpleXMLTransfer *configfile, FDMEnviroment* fdmEnvironment)
{
  cleanup();
  fdmInterface = new ModFDMInterface();

  std::string filename = configfile->getString("airplane.file", "models/allegro.xml");
  filename = air_to_xml_file_load(filename);

  try
  {
    SimpleXMLTransfer* xml = new SimpleXMLTransfer(filename);

    SimpleXMLTransfer* ap = configfile->getChild("airplane");

    // Here we copy graphics and config preferences from crrcsim's config file
    // into the in-memory-copy of the airplane. This is because an airplane file 
    // should not be altered by user preferences.
    XMLModelFile::SetGraphics(xml, ap->attributeAsInt("graphics", 0));
    XMLModelFile::SetConfig  (xml, ap->attributeAsInt("config",   0));

    fdmInterface->loadAirplane(xml, fdmEnvironment, configfile);
    if (configfile->getInt("video.enabled", 1))
    {
      model_ = new CRRCAirplaneLaRCSimSSG(xml, scene);
    }

    getFDM()->registerAnimations(getModel()->getAnimations());

    delete xml;
  }
  catch (XMLException e)
  {
    std::string msg = "Error opening airplane specification file: ";
    msg += filename;
    msg += ": ";
    msg += e.what();

    throw std::runtime_error(msg);    
  }  
  if (getFDM() == NULL)
  {
    throw std::runtime_error("Unable to load airplane specification file.");
  }
}
Пример #13
0
/**
 *  Initialize the interface.
 *
 *  The base class handles all hardware initialization for us, so we only
 *  have to set up the correct control line states to power the interface.
 */
int T_TX_InterfaceSerPIC::init (SimpleXMLTransfer *config)
{
#if DEBUG_TX_INTERFACE > 0
  std::cout << "T_TX_InterfaceSerPIC::init ()\n";
#endif
  int ret = T_TX_InterfaceSerial::init (config);

  if (ret == 0)
  {
    // initialized successfully, now turn on the power supply for the
    // interface hardware (careful, could throw an exception)
    try
    {
      setRts (true);
      setDtr (false);
    }
    catch (CharDevice::ConfigureDeviceException e)
    {
      setErrMsg ("Setting Rts/Dtr states failed.");
      cerr << "Serial interface initialization: " << getErrMsg () << endl;
      ret = 1;
    }

    int default_sync_byte = DEFAULT_SYNC_BYTE_19200;
    int default_button_channel = DEFAULT_BUTTON_CHANNEL_19200;
    if (T_TX_InterfaceSerial::getBaudRate() == 9600)
    {
      default_sync_byte = DEFAULT_SYNC_BYTE_9600;
      default_button_channel = DEFAULT_BUTTON_CHANNEL_9600;
    }
    // read sync and button byte settings from config file
    SimpleXMLTransfer *port = config->getChild(getXmlChildName() + ".port", true);
    ucSyncByte              = port->attributeAsInt("sync", default_sync_byte);
    iSPIC_ButtonChannel     = port->attributeAsInt("button_channel", default_button_channel);
#if DEBUG_TX_INTERFACE > 0
    std::cout << "  Configured sync byte: 0x" << std::hex << int(ucSyncByte) << std::dec;
    std::cout << ", " << std::string((iSPIC_ButtonChannel == 0) ? "no" : "has") << " button channel";
    std::cout << std::endl;
#endif
  }

  return ret;
}
Пример #14
0
void T_Calibration::init(SimpleXMLTransfer* cfgfile,
                         std::string childname)
{
#if DEBUG_TX_INTERFACE > 0
  printf("T_Calibration::init(cfg, child)\n");
  printf(" <-- %s\n", childname.c_str());
#endif
  int size;
  SimpleXMLTransfer* item;
  SimpleXMLTransfer* group;
  SimpleXMLTransfer* item2;
  
  child_in_cfg = childname;

  // try to load config
  printf("Loading calibration settings from %s:\n", childname.c_str());
  try
  {
    item = cfgfile->getChild(childname, true);
    group = item->getChild("calibration", true);
    int nVer = group->getInt("version", 1);
  
    size  = group->getChildCount();
    if (size > TX_MAXAXIS)
      size = TX_MAXAXIS;
    for (int n = 0; n < size; n++)
    {
      item2 = group->getChildAt(n);
      switch (nVer)
      {
        case 1:
          {
            float scale = item2->getDouble("scale", 1.0);
            float off = item2->getDouble("offset", 0.0);
            // old:   out = scale * in + offset
            val_min[n] = (-0.5 - off) / scale;
            val_max[n] = ( 0.5 - off) / scale;
            val_mid[n] = 0.5 * (val_min[n] + val_max[n]);
            printf("  (1)");
          }
          break;
          
        case 2:      
          val_min[n] = item2->getDouble("val_min", -1.0);
          val_mid[n] = item2->getDouble("val_mid",  0.0);
          val_max[n] = item2->getDouble("val_max",  1.0);
          printf("  (2)");
          break;
      }
      printf(" axis=%i val_min=%f val_mid=%f val_max=%f\n", n, val_min[n], val_mid[n], val_max[n]);
    }
  }
  catch (XMLException e)
  {
    fprintf(stderr, "*** T_Calibration::init(): %s\n", e.what());
  }
}
Пример #15
0
void Power::Shaft::ReloadParams(SimpleXMLTransfer* xml)
{
  int      nChildCnt = 0;
  double   J_ges;
  
  fBrake = (xml->attributeAsInt("brake", 1) != 0);
  J_ges = xml->attributeAsDouble("J", 0);
  std::cout << "  Shaft: J=" << J_ges << " kg m^2\n";
      
  for (int n=0; n<xml->getChildCount(); n++)
  {
    SimpleXMLTransfer* it = xml->getChildAt(n);
    if (it->getName().compare("engine")       == 0 ||
        it->getName().compare("propeller")    == 0 ||
        it->getName().compare("simplethrust") == 0
        )
    {
      gear[nChildCnt]->ReloadParams(it);
      J_ges += gear[nChildCnt++]->getJ();
    }
  }
  
  J_inv = 1/J_ges;
}
Пример #16
0
/**
 *  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();
}
Пример #17
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;
}
Пример #18
0
/** \brief Transfers all settings back to the config file.
 *
 *  The mixer settings will be stored in the same branch of the config
 *  file that they were read from on initialization.
 *
 *  \param config Pointer to the config file's SimpleXMLTransfer.
 */
void T_TX_Mixer::putBackIntoCfg(SimpleXMLTransfer* config)
{
#if DEBUG_TX_INTERFACE > 0
  printf("T_TX_Mixer::putBackIntoCfg(SimpleXMLTransfer* config)\n");
  printf(" --> %s\n", child_in_cfg.c_str());
#endif

  SimpleXMLTransfer* inter = config->getChild(child_in_cfg);
  SimpleXMLTransfer* mixer = inter->getChild("mixer");
  SimpleXMLTransfer* item;

  mixer->setAttributeOverwrite("enabled", enabled);
  mixer->setAttributeOverwrite("dr_enabled", dr_enabled);

  item = mixer->getChild(Global::inputDev->AxisStringsXML[T_AxisMapper::AILERON], true);
  item->setAttributeOverwrite("trim",  doubleToString(trim_val[T_AxisMapper::AILERON]));
  item->setAttributeOverwrite("nrate", doubleToString(nrate_val[T_AxisMapper::AILERON]));
  item->setAttributeOverwrite("srate", doubleToString(srate_val[T_AxisMapper::AILERON]));
  item->setAttributeOverwrite("exp",   doubleToString(exp_val[T_AxisMapper::AILERON]));

  item = mixer->getChild(Global::inputDev->AxisStringsXML[T_AxisMapper::ELEVATOR], true);
  item->setAttributeOverwrite("trim",  doubleToString(trim_val[T_AxisMapper::ELEVATOR]));
  item->setAttributeOverwrite("nrate", doubleToString(nrate_val[T_AxisMapper::ELEVATOR]));
  item->setAttributeOverwrite("srate", doubleToString(srate_val[T_AxisMapper::ELEVATOR]));
  item->setAttributeOverwrite("exp",   doubleToString(exp_val[T_AxisMapper::ELEVATOR]));

  item = mixer->getChild(Global::inputDev->AxisStringsXML[T_AxisMapper::RUDDER], true);
  item->setAttributeOverwrite("trim",  doubleToString(trim_val[T_AxisMapper::RUDDER]));
  item->setAttributeOverwrite("nrate", doubleToString(nrate_val[T_AxisMapper::RUDDER]));
  item->setAttributeOverwrite("srate", doubleToString(srate_val[T_AxisMapper::RUDDER]));
  item->setAttributeOverwrite("exp",   doubleToString(exp_val[T_AxisMapper::RUDDER]));

  item = mixer->getChild(Global::inputDev->AxisStringsXML[T_AxisMapper::FLAP], true);
  item->setAttributeOverwrite("trim",    doubleToString(trim_val[T_AxisMapper::FLAP]));
  item->setAttributeOverwrite("mtravel", doubleToString(mtravel_val[T_AxisMapper::FLAP]));
  item->setAttributeOverwrite("ptravel", doubleToString(ptravel_val[T_AxisMapper::FLAP]));
  
  for (int i = 0; i < T_TX_Mixer::NUM_MIXERS; i++)
  {
    item = mixer->getChild(Global::inputDev->MixerStringsXML[i], true);
    item->setAttributeOverwrite("enabled", mixer_enabled[i]);
    item->setAttributeOverwrite("src", mixer_src[i]);
    item->setAttributeOverwrite("dst", mixer_dst[i]);
    item->setAttributeOverwrite("val", doubleToString(mixer_val[i]));
  }
}
Пример #19
0
/** \brief Add animations to a model
 *
 *  This method reads animation description tags from a model file
 *  and tries to add the corresponding animations to the 3D model.
 *
 *  \todo Right now there's only one type of animation: movable control
 *  surfaces. Therefore this method receives a pointer to the control
 *  input class. If animations are added that need a different kind of
 *  input for their update() method, we need to decide how to pass all
 *  this stuff to initAnimations().
 *
 *  \param  model_file    XML model description file
 *  \param  model         scenegraph of the 3D model
 *  \param  fInputs       pointer to the control input class
 *  \param  anim_list     list of all created CRRCAnimation objects
 */
void initAnimations(SimpleXMLTransfer *model_file, ssgEntity* model, 
                    TSimInputs *fInput, std::vector<CRRCAnimation*>& anim_list)
{
  SimpleXMLTransfer *animations = model_file->getChild("animations", true);
  int num_anims = animations->getChildCount();
  fprintf(stdout, "initAnimations: found %d children\n", num_anims);
  
  for (int i = 0; i < num_anims; i++)
  {
    SimpleXMLTransfer *animation = animations->getChildAt(i);
    ssgEntity *node;
    
    if (animation->getName() != "animation")
    {
      fprintf(stderr, "initAnimations: invalid child <%s>\n", animation->getName().c_str());
    }
    else
    {
      std::string node_name = animation->getString("object.name", "default");
      std::string type      = animation->getString("type", "default");

      node = SSGUtil::findNamedNode(model, node_name.c_str());
      if (node != NULL)
      {
        CRRCAnimation *anim = NULL;
        printf("initAnimations: found animation node %s, type %s\n", 
                node_name.c_str(), type.c_str());
        
        if (type == "ControlSurface")
        {
          anim = new CRRCControlSurfaceAnimation(animation, fInput);
        }
        else
        {
          fprintf(stderr, "initAnimations: unknown animation type '%s'\n", type.c_str());
        }
        
        if (anim != NULL)
        {
          if (anim->getBranch() == NULL)
          {
            fprintf(stderr, "initAnimations: defunct animation class (animation branch is <NULL>)\n");
            exit(0);
          }
          else
          {
            SSGUtil::spliceBranch(anim->getBranch(), node);
            anim->init();
            anim->setName("Animation");
            anim->getBranch()->setUserData(anim);
            anim->getBranch()->setTravCallback(SSG_CALLBACK_PRETRAV, animation_callback);
            anim_list.push_back(anim);
          }
        }
        
      }
      else
      {
        fprintf(stderr, "initAnimations: node '%s' not found in 3D model\n", node_name.c_str());
      }
    }
  }
}
Пример #20
0
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);  
}
Пример #21
0
/** \brief The constructor.
 *
 *  Loads an airplane model from an xml description. The 3D model
 *  will be added to the specified scenegraph.
 *
 *  \param  xml   XML model description file
 *  \param  graph Pointer to the scenegraph which shall render the model
 */
CRRCAirplaneLaRCSimSSG::CRRCAirplaneLaRCSimSSG(SimpleXMLTransfer* xml, ssgBranch *graph)
  : CRRCAirplaneLaRCSim(xml), initial_trans(NULL), 
    model_trans(NULL), model(NULL),
    shadow(NULL), shadow_trans(NULL)
{
  printf("CRRCAirplaneLaRCSimSSG(xml, branch)\n");
  
  std::string s;      
  s = XMLModelFile::getGraphics(xml)->getString("model");
        
  // plib automatically loads the texture file, but it does not know which directory to use.
  {
    // where is the object file?
    std::string    of  = FileSysTools::getDataPath("objects/" + s);
    // compile and set relative texture path
    std::string    tp  = of.substr(0, of.length()-s.length()-1-7) + "textures";    
    ssgTexturePath(tp.c_str());
    // load model
    model = ssgLoad(of.c_str());
  }

  if (model != NULL)
  {
    // Offset of center of gravity
    CRRCMath::Vector3  pCG;         
    pCG = CRRCMath::Vector3(0, 0, 0);
    if (xml->indexOfChild("CG") >= 0)
    {
      SimpleXMLTransfer* i;
      i = xml->getChild("CG");
      pCG.r[0] = i->attributeAsDouble("x", 0);
      pCG.r[1] = i->attributeAsDouble("y", 0);
      pCG.r[2] = i->attributeAsDouble("z", 0);
      
      if (i->attributeAsInt("units") == 1)
        pCG *= M_TO_FT;
    }
    
    // transform model from SSG coordinates to CRRCsim coordinates
    initial_trans = new ssgTransform();
    model_trans = new ssgTransform();
    graph->addKid(model_trans);
    model_trans->addKid(initial_trans);
    initial_trans->addKid(model);
    
    sgMat4 it = {  {1.0,  0.0,  0.0,  0},
                   {0.0,  0.0, -1.0,  0},
                   {0.0,  1.0,  0.0,  0},
                   {pCG.r[1],  pCG.r[2],  -pCG.r[0],  1.0} };
    
    initial_trans->setTransform(it);

    // add a simple shadow
    shadow = (ssgEntity*)initial_trans->clone(SSG_CLONE_RECURSIVE | SSG_CLONE_GEOMETRY | SSG_CLONE_STATE);
    makeShadow(shadow);
    shadow_trans = new ssgTransform();
    graph->addKid(shadow_trans);
    shadow_trans->addKid(shadow);
    
    // add animations ("real" model only, without shadow)
    initAnimations(xml, model, &Global::inputs, animations);
  }
  else
  {
    std::string msg = "Unable to open airplane model file \"";
    msg += s;
    msg += "\"\nspecified in \"";
    msg += xml->getSourceDescr();
    msg += "\"";

    throw std::runtime_error(msg);
  }

}
Пример #22
0
ModelBasedScenery::ModelBasedScenery(SimpleXMLTransfer *xml, int sky_variant)
    : Scenery(xml, sky_variant), location(Scenery::MODEL_BASED)
{
  ssgEntity *model = NULL;
  SimpleXMLTransfer *scene = xml->getChild("scene", true);
  getHeight_mode = scene->attributeAsInt("getHeight_mode", DEFAULT_HEIGHT_MODE);
  //std::cout << "----getHeight_mode : " <<  getHeight_mode <<std::endl;
  SceneGraph = new ssgRoot();

  // Create an "invisible" state. This state actually makes a node
  // visible in a predefined way. This is used to visualize invisible
  // objects (e.g. collision boxes).
  invisible_state = new ssgSimpleState();
  invisible_state->disable(GL_COLOR_MATERIAL);
  invisible_state->disable(GL_TEXTURE_2D);
  invisible_state->enable(GL_LIGHTING);
  invisible_state->enable(GL_BLEND);
  //invisible_state->setShadeModel(GL_SMOOTH);
  //invisible_state->setShininess(0.0f);
  invisible_state->setMaterial(GL_EMISSION, 0.0, 0.0, 0.0, 0.0);
  invisible_state->setMaterial(GL_AMBIENT, 1.0, 0.0, 0.0, 0.5);
  invisible_state->setMaterial(GL_DIFFUSE, 1.0, 0.0, 0.0, 0.5);
  invisible_state->setMaterial(GL_SPECULAR, 1.0, 0.0, 0.0, 0.5);

  // transform everything from SSG coordinates to CRRCsim coordinates
  initial_trans = new ssgTransform();
  SceneGraph->addKid(initial_trans);
//10.76
  sgMat4 it = {  {1,  0.0,  0.0,   0},
    {0.0,  0.0, -1,   0},
    {0.0,  1,  0.0,   0},
    {0.0,  0.0,  0.0, 1.0}
  };

  initial_trans->setTransform(it);

  // find all "objects" defined in the file
  int num_children = scene->getChildCount();

  for (int cur_child = 0; cur_child < num_children; cur_child++)
  {
    SimpleXMLTransfer *kid = scene->getChildAt(cur_child);
    // only use "object" tags
    if (kid->getName() == "object")
    {
      std::string filename = kid->attribute("filename", "not_specified");
      bool is_terrain = (kid->attributeAsInt("terrain", 1) != 0);
      bool is_visible = (kid->attributeAsInt("visible", 1) != 0);

      // PLIB automatically loads the texture file,
      // but it does not know which directory to use.
      // Where is the object file?
      std::string    of  = FileSysTools::getDataPath("objects/" + filename, TRUE);
      // compile and set relative texture path
      std::string    tp  = of.substr(0, of.length()-filename.length()-1-7) + "textures";
      ssgTexturePath(tp.c_str());

      // load model
      std::cout << "Loading 3D object \"" << of.c_str() << "\"";
      if (is_terrain)
      {
        std::cout << " (part of terrain)";
      }
      if (!is_visible)
      {
        std::cout << " (invisible)";
      }
      std::cout << std::endl;
      model = ssgLoad(of.c_str());
      if (model != NULL)
      {
        if (!is_visible)
        {
          setToInvisibleState(model);
        }
        
        // The model may contain internal node attributes (e.g. for
        // integrated collision boxes). Parse these attributes now.
        evaluateNodeAttributes(model);
        
        
        // now parse the instances and place the model in the SceneGraph
        for (int cur_instance = 0; cur_instance < kid->getChildCount(); cur_instance++)
        {
          SimpleXMLTransfer *instance = kid->getChildAt(cur_instance);
          if (instance->getName() == "instance")
          {
            sgCoord coord;
            
            // try north/east/height first, then fallback to x/y/z
            try
            {
              coord.xyz[SG_X] = instance->attributeAsDouble("east");
            }
            catch (XMLException &e)
            {
              coord.xyz[SG_X] = instance->attributeAsDouble("y", 0.0);
            }
            try
            {
              coord.xyz[SG_Y] = instance->attributeAsDouble("north");
            }
            catch (XMLException &e)
            {
              coord.xyz[SG_Y] = instance->attributeAsDouble("x", 0.0);
            }
            try
            {
              coord.xyz[SG_Z] = instance->attributeAsDouble("height");
            }
            catch (XMLException &e)
            {
              coord.xyz[SG_Z] = instance->attributeAsDouble("z", 0.0);
            }
            coord.hpr[0] = 180 - instance->attributeAsDouble("h", 0.0);
            coord.hpr[1] = -instance->attributeAsDouble("p", 0.0);
            coord.hpr[2] = -instance->attributeAsDouble("r", 0.0);

            std::cout << std::setprecision(1);
            std::cout << "  Placing instance at " << coord.xyz[SG_X] << ";" << coord.xyz[SG_Y] << ";" << coord.xyz[SG_Z];
            std::cout << ", orientation " << (180-coord.hpr[0]) << ";" << -coord.hpr[1] << ";" << -coord.hpr[2] << std::endl;
            std::cout << std::setprecision(6);
            ssgTransform *trans = new ssgTransform();
            trans->setTransform(&coord);
            
            // In PLIB::SSG, intersection testing is done by a tree-walking
            // function. This can be influenced by the tree traversal mask
            // bits. The HOT and LOS flags are cleared for objects that are
            // not part of the terrain, so that the height-of-terrain and
            // line-of-sight algorithms ignore this branch of the tree.
            if (!is_terrain)
            {
              trans->clrTraversalMaskBits(SSGTRAV_HOT | SSGTRAV_LOS);
            }
            // Objects are made invisible by clearing the CULL traversal flag.
            // This means that ssgCullAndDraw will ignore this branch.
            if (!is_visible)
            {
              trans->clrTraversalMaskBits(SSGTRAV_CULL);
            }
            initial_trans->addKid(trans);
            trans->addKid(model);
          }
        }
      }
    }
  }
  
  // create actual terrain height model
  if (getHeight_mode == 1)
  {
    heightdata = new HD_TabulatedTerrain(SceneGraph);
  }
  else if (getHeight_mode == 2)
  {
    heightdata = new HD_TilingTerrain(SceneGraph);
  }
  else
  {
    heightdata = new HD_SsgLOSTerrain(SceneGraph);
  }

  //wind
  SimpleXMLTransfer *wind = xml->getChild("wind", true);
  std::string wind_filename = wind->attribute("filename","");
#if WINDDATA3D == 1
  wind_data = 0;//default : no wind_data
  std::string wind_position_unit = wind->attribute("unit","");
  try {
    flDefaultWindDirection = wind->attributeAsInt("direction");
    ImposeWindDirection = true;
    }
  catch (XMLException)
    {
    // if not attribut "direction", normal mode
    }
  
  if (wind_position_unit.compare("m")==0)
  {
    wind_position_coef = FT_TO_M;
  }
  else
  {
    wind_position_coef = 1;
  }
  std::cout << "wind file name :  " << wind_filename.c_str()<< std::endl;
  if (wind_filename.length() > 0)
  {
    wind_filename = FileSysTools::getDataPath(wind_filename);  
    std::cout << "init wind ---------";
    int n = init_wind_data((wind_filename.c_str()));
    std::cout << n << "  points processed" << std::endl;
  }
#else
  if (wind_filename.length() > 0)
  {
    new CGUIMsgBox("Insufficient configuration to read windfields.");
  }
#endif
}
Пример #23
0
/**
 * Initialize a WheelSystem from an XML file.
 *
 * \param ModelFile   pointer to file class
 * \param def_span    default span if no hardpoints are found to calculate it
 */
void WheelSystem::init(SimpleXMLTransfer *ModelFile, SCALAR  def_span)
{
  Wheel              wheel(this);
  SimpleXMLTransfer  *e, *i;
  unsigned int       uSize;
  double             x, y, z;
  double             dist;
  double             to_ft;
  double             to_lbf_per_ft;
  double             to_lbf_s_per_ft;
  double             to_lbf;
  CRRCMath::Vector3  pCG;
   
  /**
   * Tracks wingspan [m]
   */
  double span = 0;
  span_ft = 0.0;
  
  
  //
  pCG = CRRCMath::Vector3(0, 0, 0);
  if (ModelFile->indexOfChild("CG") >= 0)
  {
    i = ModelFile->getChild("CG");
    pCG.r[0] = i->attributeAsDouble("x", 0);
    pCG.r[1] = i->attributeAsDouble("y", 0);
    pCG.r[2] = i->attributeAsDouble("z", 0);
    
    if (i->attributeAsInt("units") == 1)
      pCG *= M_TO_FT;
  }
  
  // let's assume that there is nothing below/above the CG:
  dZLow    = 0;
  dZHigh   = 0;
  
  // let's assume that there is nothing distant from the CG:
  dMaxSize = 0;
  
  wheels.clear();
  
  i = ModelFile->getChild("wheels");
  switch (i->getInt("units"))
  {
   case 0:    
    to_ft           = 1;
    to_lbf_per_ft   = 1;
    to_lbf_s_per_ft = 1;
    to_lbf          = 1;
    break;
   case 1:
    to_ft           = M_TO_FT;
    to_lbf_per_ft   = FT_TO_M / LBF_TO_N;
    to_lbf_s_per_ft = FT_TO_M / LBF_TO_N;
    to_lbf          = N_TO_LBF;
    break;
   default:
    {
      throw std::runtime_error("Unknown units in wheels");
    }
    break;
  }        
  uSize = i->getChildCount();
  for (unsigned int n=0; n<uSize; n++)
  {
    // we assign the child number as a unique ID for
    // debugging
    wheel.nID = n;
    
    e = i->getChildAt(n);
    
    x = e->getDouble("pos.x") * to_ft - pCG.r[0];
    y = e->getDouble("pos.y") * to_ft - pCG.r[1];
    z = e->getDouble("pos.z") * to_ft - pCG.r[2];
    wheel.v_P = CRRCMath::Vector3(x, y, z);
    
    // let's see if this wheel is coupled to an animation
    wheel.anim_name = e->getString("pos.animation", "");
    if (wheel.anim_name != "")
    {
      std::cout << "WheelSystem::init: hardpoint is coupled to anim ";
      std::cout << wheel.anim_name << std::endl;
    }
    wheel.hpt = NULL;
    if (ModelFile->indexOfChild("animations") >= 0)
    {
      SimpleXMLTransfer *a = ModelFile->getChild("animations");
      unsigned int numAnims = a->getChildCount();
      for (unsigned int animIndex = 0; animIndex < numAnims; animIndex++)
      {
        SimpleXMLTransfer *an = a->getChildAt(animIndex);
        if (an->getString("object.name", "") == wheel.anim_name)
        {
          printf("Found %s animation for wheel %s\n",
                  an->getString("type", "<unknown>").c_str(),
                  wheel.anim_name.c_str());
          wheel.hpt = new HardPointRotation(an, wheel_inputs);
          break;
        }
      }
    }

    wheel.spring_constant    = e->getDouble("spring.constant") * to_lbf_per_ft;
    wheel.spring_damping     = e->getDouble("spring.damping")  * to_lbf_s_per_ft;
    wheel.max_force          = e->getDouble("spring.max_force", 9999) * to_lbf;
    wheel.percent_brake      = e->getDouble("percent_brake");
    wheel.caster_angle_rad   = e->getDouble("caster_angle_rad");

    if (e->indexOfChild("steering") >= 0)
    {
      std::string s = e->getString("steering.mapping", "NOTHING");
      wheel.steering_max_angle = e->getDouble("steering.max_angle", 1.0);
      wheel.steering_mapping   = XMLModelFile::GetSteering(s);
    }
    else
    {
      wheel.steering_mapping   = TSimInputs::smNOTHING;
      wheel.steering_max_angle = 0;
    }
    wheels.push_back(wheel);
    
    // track wingspan
    if (span < y)
      span = y;
    // lowest point?
    if (dZLow < z)
      dZLow = z;
    // highest point?
    if (dZHigh > z)
      dZHigh = z;
    // far away (Z distance is assumed to be low)?
    dist = x*x + y*y;
    if (dist > dMaxSize)
      dMaxSize = dist;
  }
  dMaxSize = sqrt(dMaxSize);
  span_ft  = 2 * span;

  // just in case: if there were no hardpoints, use the reference span
  if (span_ft == 0.0)
  {
    span_ft = def_span;
  }
}
Пример #24
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);
      }
    }
  }
}
Пример #25
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();

}