Example #1
0
//------------------------------------------------------------------------------
// 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();
}
Example #2
0
  //------------------------------------------------------------------------------
  // 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);
    }
}