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); } }
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()); } }
/** \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); } }
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); } } } }
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); }
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 }
/** * 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; } }
/** \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()); } } } }