//------------------------------------------------------------------------------ // updateData() - //------------------------------------------------------------------------------ void Adi::updateData(const LCreal dt) { // update our base class first BaseClass::updateData(dt); // drive our adi toward the actual pitch, from our current pitch, no faster // than our MAX_RATE (this allows for greater fidelity, simulates an analog adi) LCreal delta = 0; delta = alim (lcAepcDeg(pitch - curTheta), maxRate * dt); curTheta = lcAepcDeg(curTheta + delta); // now do the same thing for roll delta = alim (lcAepcRad(roll - curPhi), maxRate * dt); curPhi = lcAepcRad(curPhi + delta); // get our table, and do the linear interpolation ourself setInstVal(curTheta); scaledPitch = getInstValue(); }
//------------------------------------------------------------------------------ // Handle input devices //------------------------------------------------------------------------------ void IoHandler::inputDevices(const LCreal dt) { BaseClass::inputDevices(dt); // --- // get the Input data buffer // --- const Basic::IoData* const inData = getInputData(); // --- // get the Station, Simulation and our ownship player // --- SimStation* const sta = static_cast<SimStation*>( findContainerByType(typeid(SimStation)) ); Simulation::Simulation* sim = 0; Simulation::AirVehicle* av = 0; if (sta != 0) { sim = sta->getSimulation(); av = dynamic_cast<Simulation::AirVehicle*>(sta->getOwnship()); } // --- // If we have everything we need .... // --- if (av != 0 && sim != 0 && inData != 0) { // find the (optional) autopilot Simulation::Autopilot* ap = 0; { Basic::Pair* p = av->getPilotByType( typeid( Simulation::Autopilot) ); if (p != 0) ap = static_cast<Simulation::Autopilot*>( p->object() ); } // ------------------------------------------------------------ // Simulation Control Inputs // ------------------------------------------------------------ { bool enabled = false; inData->getDiscreteInput(CTL_ENABLE_SW, &enabled); { // Toggle simulation freeze bool sw = false; inData->getDiscreteInput(FREEZE_SW, &sw); bool frzSw = sw && enabled; if (frzSw && !frzSw1) { Basic::Boolean newFrz( !sim->isFrozen() ); sim->event(FREEZE_EVENT, &newFrz); } frzSw1 = frzSw; } { // Send a reset pulse to the station bool sw = false; inData->getDiscreteInput(RESET_SW, &sw); bool rstSw = sw && enabled; if (rstSw && !rstSw1) { sta->event(RESET_EVENT); } rstSw1 = rstSw; } { // Send a weapons reload pulse to the station bool sw = false; inData->getDiscreteInput(RELOAD_SW, &sw); bool wpnReloadSw = sw && enabled; if (wpnReloadSw && !wpnReloadSw1) { sta->event(WPN_RELOAD); } wpnReloadSw1 = wpnReloadSw; } } // ------------------------------------------------------------ // Flight Control Inputs // ------------------------------------------------------------ { // Process Roll Input LCreal ai = 0; inData->getAnalogInput(ROLL_AI, &ai); LCreal aiLim = alim(ai, 1.0f); if (ap != 0) ap->setControlStickRollInput(aiLim); else av->setControlStickRollInput(aiLim); } { // Process Pitch Input LCreal ai = 0; inData->getAnalogInput(PITCH_AI, &ai); LCreal aiLim = alim(ai, 1.0f); if (ap != 0) ap->setControlStickPitchInput(aiLim); else av->setControlStickPitchInput(aiLim); } { // Process Rudder Input LCreal ai = 0; inData->getAnalogInput(RUDDER_AI, &ai); LCreal aiLim = alim(ai, 1.0f); av->setRudderPedalInput(aiLim); } { // Process Throttle Input LCreal value = 0; inData->getAnalogInput(THROTTLE_AI, &value); if (value < 0.0f) value = 0.0f; else if (value > 2.0f) value = 2.0f; if (ap != 0) ap->setThrottles(&value,1); else av->setThrottles(&value,1); } { // Weapons Release bool sw = false; inData->getDiscreteInput(PICKLE_SW, &sw); if (sw != wpnRelSw1) { Basic::Boolean sw(sw); av->event(WPN_REL_EVENT, &sw); } wpnRelSw1 = sw; } { // Trigger switch bool sw = false; inData->getDiscreteInput(TRIGGER_SW2, &sw); if (sw != trgSw1) { Basic::Boolean sw(sw); av->event(TRIGGER_SW_EVENT, &sw); } trgSw1 = sw; } { // Target Step (reject) bool sw = false; inData->getDiscreteInput(TMS_RIGHT_SW, &sw); if (sw && !tgtStepSw1) { av->event(TGT_STEP_EVENT); } tgtStepSw1 = sw; } { // Target Designate bool sw = false; inData->getDiscreteInput(TMS_UP_SW, &sw); if (sw && !tgtDesSw1) { av->event(TGT_DESIGNATE); } tgtDesSw1 = sw; } { // Return-To-Search bool sw = false; inData->getDiscreteInput(TMS_DOWN_SW, &sw); if (sw && !rtn2SrchSw1) { av->event(SENSOR_RTS); } rtn2SrchSw1 = sw; } { // Autopilot disengage bool autopilotSw = false; inData->getDiscreteInput(PADDLE_SW, &autopilotSw); if (autopilotSw && !autopilotSw1) { Simulation::Autopilot* ap = dynamic_cast<Simulation::Autopilot*>(av->getPilot()); if (ap != 0) { ap->setHeadingHoldMode(false); ap->setAltitudeHoldMode(false); ap->setVelocityHoldMode(false); ap->setLoiterMode(false); ap->setNavMode(false); } } autopilotSw1 = autopilotSw; } { // Speedbrake switch bool sbExtSw = false; bool sbRetSw = false; inData->getDiscreteInput(SB_EXT_SW, &sbExtSw); inData->getDiscreteInput(SB_RET_SW, &sbRetSw); LCreal sb = 0.0; if(sbExtSw) sb = -1.0f; if(sbRetSw) sb = 1.0f; av->setSpeedBrakesSwitch(sb); } { // Steerpoint increment bool incStptSw = false; inData->getDiscreteInput(DMS_UP_SW, &incStptSw); if(incStptSw && !incStptSw1) { // find our route and increment the steerpoint Simulation::Navigation* myNav = av->getNavigation(); if (myNav != 0) { myNav->ref(); Simulation::Route* myRoute = myNav->getPriRoute(); if (myRoute != 0) { myRoute->ref(); myRoute->incStpt(); myRoute->unref(); } } } incStptSw1 = incStptSw; } { // Steerpoint decrement bool decStptSw = false; inData->getDiscreteInput(DMS_DOWN_SW, &decStptSw); if (decStptSw && !decStptSw1) { // find our route and increment the steerpoint Simulation::Navigation* myNav = av->getNavigation(); if (myNav != 0) { myNav->ref(); Simulation::Route* myRoute = myNav->getPriRoute(); if (myRoute != 0) { myRoute->ref(); myRoute->decStpt(); myRoute->unref(); } } } decStptSw1 = decStptSw; } } }
//------------------------------------------------------------------------------ // updateData() -- update non time-critical stuff here //------------------------------------------------------------------------------ void TestElectronic::updateData(const LCreal dt) { BaseClass::updateData(dt); updateTestValues(dt); // current heading / current heading bug { // max rate here is 120 degs / second LCreal delta = alim(lcAepcDeg(heading - curHdg), 120 * dt); curHdg = lcAepcDeg(curHdg + delta); // now figure our heading bug delta = alim(lcAepcDeg(headingBug - curBug), 120 * dt); curBug = lcAepcDeg(curBug + delta); if (navMode == ARC_MODE) { // we either move it to the left or right, depending on how far // off our slew is. LCreal diff = lcAepcDeg(curHdg - curBug); LCreal moveX = -1.8f; if (diff >= -36 && diff < 36) { if (diff > 0) moveX = 1.53f; else moveX = -1.8f; } int tempCurBug = static_cast<int>(curBug); if (tempCurBug < 0) tempCurBug += 360; // heading bug readout value and x position. send("bugro", UPDATE_VALUE, tempCurBug, hdgBugROSD); send("headingbugro", UPDATE_VALUE, moveX, hdgBugROMoveXSD); // heading bug actual position send("headingbug", UPDATE_VALUE6, heading - curBug, headingBugSD); } } // distance data / DME { // are we a distance type or DME type? bool distType = true; // initial type is DME bool distVis = true; // initial visibility is true LCreal curDist = alim(dist, 999.9f); // current distance to DME if (navSource == PRIMARY) { // valid DME makes our label visible distVis = dmeValid; if (navType == INAV) distType = false; } else if (navSource == SECONDARY) { // valid DME makes our label visible distVis = secDmeValid; if (secNavType == INAV) distType = false; else distVis = true; } send("distlabel", SELECT, distType, distTypeSD); send("distval", SET_VISIBILITY, distVis, distVisSD); send("distval", UPDATE_VALUE, curDist, curDistSD); } // course data { // which course pointer are we using? send("whichcourseptr", SELECT, navSource, whichCrsPtrSD); int curIntCourse = 0; LCreal tempCDI = 0; LCreal tempCourse = 0; // primary nav course if (navSource == PRIMARY) { curIntCourse = nint(course); tempCDI = cdi; tempCourse = course; } // secondary nav course else { curIntCourse = nint(secCourse); tempCDI = secCdi; tempCourse = secCourse; } if (curIntCourse < 0) curIntCourse += 360; // send the course readout send("course", UPDATE_VALUE, curIntCourse, courseSD); // here is the course deviation LCreal delta = alim (lcAepcDeg(tempCDI - curCdi), 4 * dt); curCdi = alim (curCdi + delta, 2.0); // now find our inches to translate the cdi LCreal cdiInch = curCdi * 0.43f; // now figure our course slew delta = alim(lcAepcDeg(tempCourse - curCourse), 120 * dt); curCourse = (lcAepcDeg(curCourse + delta)); // ok, do our color determination for the course pointer - primary first if (navSource == PRIMARY) { // dealing with our primary course pointer here bool vis = true; if (navMode == MAP_MODE || navMode == DECLUTTER) vis = false; send("primarycoursepointer", SET_VISIBILITY, vis, primaryCrsVisSD); // course pointer deviation and rotation send("primarycoursedev", UPDATE_VALUE, cdiInch, priCourseDevSD); send("primarycoursepointer", UPDATE_VALUE6, heading - curCourse, crsPntrSD); // course pointer color Basic::String* string = new Basic::String("white"); if (navType == VORTAC) { if ((vhfReceive && !(vhfDIC || vhfLGS)) || (vhfLocValid && vhfLGS)) string->setStr("green"); else string->setStr("yellow"); } else { if (dmeValid) string->setStr("green"); else string->setStr("yellow"); } send("primarycoursepointer", SET_COLOR, string->getString(), priCrsPtrColorSD); // get rid of our string string->unref(); } else { // secondary course pointer bool vis = true; if (secNavMode == MAP_MODE || secNavMode == DECLUTTER) vis = false; send("secondarycoursepointer", SET_VISIBILITY, vis, secondaryCrsVisSD); // course pointer deviation and rotation send("secondarycoursedev", UPDATE_VALUE, cdiInch, secCourseDevSD); send("secondarycoursepointer", UPDATE_VALUE2, curCourse - heading, secCrsPntrSD); // course pointer color Basic::String* string = new Basic::String("white"); if (secNavType == VORTAC) { if ((secVhfReceive && !(secVhfDIC || secVhfLGS)) || (secVhfLocValid && secVhfLGS)) string->setStr("green"); else string->setStr("yellow"); } else { if (secDmeValid) string->setStr("green"); else string->setStr("yellow"); } send("secondarycoursepointer", SET_COLOR, string->getString(), secCrsPtrColorSD); // get rid of our string string->unref(); } } // our data readouts (TTG, Gs, etc...) { // which readout are we using send("whichlabel", SELECT, readoutMode, roLabelSD); // send which readout we are going to use send("whichreadout", SELECT, readoutMode, roWhichSD); // first readout, which is our time to go if (readoutMode == ND_TTG) { LCreal curTTG = timeToGo / 60; send("ttg", UPDATE_VALUE, curTTG, ttgSD); } // ground speed, drift angle, drift angle side. else if (readoutMode == ND_GSP) { // ground speed send("groundspeed", UPDATE_VALUE, groundSpeed, groundSpeedSD); // drift angle send("driftangle", UPDATE_VALUE, abs(driftAngle), driftAngleSD); if (driftAngle < 0) send("driftangleside", SELECT, true, driftAngSideSD); else send("driftangleside", SELECT, false, driftAngSideSD); } // true air speed else if (readoutMode == ND_TAS) { int curTAS = nintd(trueAirSpeed * Basic::LinearVelocity::FPS2KTSCC); send("trueairspeed", UPDATE_VALUE, curTAS, trueAirSpeedSD); } // elapsed time else if (readoutMode == ND_ET) { int hour = static_cast<int>(elapsedTime / 3600); bool isMin = false; // default to show hours if (hour < 1) { isMin = true; // show in minutes send("elapsedtimemin", UPDATE_VALUE, elapsedTime, elapsedTimeSD); } else send("elapsedtimehour", UPDATE_VALUE, elapsedTime, elapsedTimeHRSD); // send which readout send("whichelapsedtimero", SELECT, isMin, whichETSD); } // wind speed, direction, and drift angle (again) else if (readoutMode == ND_WIND) { // wind direction send("winddirection", UPDATE_VALUE, windDir, windDirectionSD); // wind speed send("windspeed", UPDATE_VALUE, windSpeed, windSpeedSD); // wind drift angle (same as drift angle for test purposes) send("driftanglewind", UPDATE_VALUE, abs(driftAngle), driftAngleWindSD); bool left = false; // false is right side, true is left // drift angle side if (driftAngle < 0) left = true; send("driftanglewindside", SELECT, left, whichSideDAWindSD); } } // bearing readouts { // determine the source of our bearing int brgSrc = 1; // default to INAV if (navSource == PRIMARY) { if (navType == VORTAC) brgSrc = 2; // primary vortac else if (navType == TACAN) brgSrc = 3; // primary tacan send("bearingro", UPDATE_VALUE, bearing, brgROSD); } else { if (secNavType == VORTAC) brgSrc = 4; // secondary vortac else brgSrc = 5; // secondary tacan send("bearingro", UPDATE_VALUE, secBearing, secBrgROSD); } send("bearingsource", SELECT, brgSrc, brgSourceSD); } // glide slope { LCreal gsDev = static_cast<LCreal>(alim (gsDots, 2.1f) * 0.35f); send("glideslopedev", UPDATE_VALUE2, gsDev, glideSlopeSD); } // compass { // let's do decentered for both, and hsi mode will just set displacement to 0 send("compass", UPDATE_VALUE6, false, centeredSD); // send our compass heading send("compass", UPDATE_VALUE, curHdg, compassHdgSD); } // primary and secondary readout indicators (with asterisk) { // first of all, which position is the asterisk going in (primary or secondary?) send("whichnavsource", SELECT, navSource, whichNavSrcSD); // primary nav source selection int primaryPos = 1; // 1 is INAV if (navType == VORTAC) { // pilot if (loc == PILOT) { if (vhfLGS) primaryPos = 2; else primaryPos = 3; } // copilot else { if (vhfLGS) primaryPos = 4; else primaryPos = 5; } } else if (navType == TACAN) primaryPos = 6; send("whichprimaryreadout", SELECT, primaryPos, primaryPosSD); // now do our secondary source selections int secondaryPos = 1; if (secNavType == VORTAC) { // pilot if (loc == PILOT) { if (secVhfLGS) secondaryPos = 2; else secondaryPos = 3; } // copilot else { if (secVhfLGS) secondaryPos = 4; else secondaryPos = 5; } } else if (secNavType == TACAN) secondaryPos = 6; send("whichsecondaryreadout", SELECT, secondaryPos, secondaryPosSD); } // TO / FROM arrow - HSI mode only { LCreal toFrom = 0; if (navSource == PRIMARY) toFrom = 1 - lcAbs(lcAepcDeg(bearing - course)) / 90; else toFrom = 1 - lcAbs(lcAepcDeg(secBearing - secCourse)) / 90; LCreal delta = alim(toFrom - curToFrom, dt); curToFrom = alim(curToFrom + delta, 0.65f); // if we are positive, we are to, negative, from bool whichToFrom = (curToFrom > 0); send("toorfrom", SELECT, whichToFrom, toOrFromSD); // now send down where to translate send("tofrom", UPDATE_VALUE2, curToFrom, toFromSD); } }