示例#1
0
//------------------------------------------------------------------------------
// getRCS() -- Get the RCS
//------------------------------------------------------------------------------
LCreal SigAzEl::getRCS(const Emission* const em)
{
   LCreal rcs = 0.0;
   if (em != 0 && tbl != 0) {

      // angle of arrival (radians)
      LCreal iv1 = em->getAzimuthAoi();
      LCreal iv2 = em->getElevationAoi();

      // If the table's independent variable's order is swapped: (El, Az)
      if (isOrderSwapped()) {
         iv1 = em->getElevationAoi();
         iv2 = em->getAzimuthAoi();
      }

      // If the table's independent variables are in degrees ..
      if (isInDegrees()) {
         iv1 *= static_cast<LCreal>(Basic::Angle::R2DCC);
         iv2 *= static_cast<LCreal>(Basic::Angle::R2DCC);
      }

      rcs = tbl->lfi(iv1,iv2);

      // If the dependent data is in decibels ...
      if (isDecibel()) {
         rcs = lcPow(LCreal(10.0f), LCreal(rcs/10.0f));
      }
   }
   return rcs;
}
示例#2
0
double Func5::f(const double iv1, const double iv2, const double iv3, const double iv4, const double iv5, FStorage* const s) const
{
   double value = 0;

   // No derived class handled this ...

   const Table5* p = (const Table5*) getTable();
   if (p != 0) {
      // But we do have an optional table that'll handle it.
      value = p->lfi(LCreal(iv1), LCreal(iv2), LCreal(iv3), LCreal(iv4), LCreal(iv5) ,s);
   }

   return value;
}
示例#3
0
//------------------------------------------------------------------------------
// Constructor(s)
//------------------------------------------------------------------------------
Gun::Gun()
{
   STANDARD_CONSTRUCTOR()

   bullet = nullptr;

   armed = false;
   fire = false;
   unlimited = false;

   burstFrameTimer = 0;
   burstFrameTime = 1.0f/LCreal(DEFAULT_BURST_RATE);
   rcount = 0.0;

   shortBurstTimer = 0.0;
   shortBurstTime  = 0.5;

   rounds = 0;
   initRounds = DEFAULT_NUM_ROUNDS;

   rpm = DEFAULT_ROUNDS_PER_MINUTE;

   setPosition(0.0, 0.0, 0.0);
   setAngles(0.0, 0.0, 0.0);
   // Note: rotation matrix (mm) was initialized by setAngles()

}
示例#4
0
void TacanRadio::initData()
{
    setMaxDetectRange(120.0);

    setNumberOfChannels(126);

    rangeIsValid = false;
    bearingIsValid = false;
    range = 0;
    grdrange = 0;
    bearing = 0;
    destLatitude = 0;
    destLongitude = 0;
    currentMagVar = 0;
    band = TCN_X_BAND;

    // Set frequencies
    {
        unsigned short chan = 1;

        // channels [ 1 .. 16 ]
        while (chan <= 16) {
            setChannelFrequency(chan++, 0.0f);
        }

        // channels [ 17 .. 59 ]
        while (chan < 59) {
            setChannelFrequency(chan, (LCreal(chan) * 0.1f + 106.3f));
            chan++;
        }

        // channels [ 60 .. 69 ]
        while (chan <= 69) {
            setChannelFrequency(chan++, 0.0f);
        }

        // channels [ 70 .. 126 ]
        while (chan <= 126) {
            setChannelFrequency(chan, (LCreal(chan) * 0.1f + 107.3f) );
            chan++;
        }
    }
}
示例#5
0
//------------------------------------------------------------------------------
// Check to see if two positions are over the horizon from each other.
// return TRUE if they are both within horizon distance, FALSE if they 
// are over the horizon. 
//------------------------------------------------------------------------------
bool TdbIr::horizonCheck(const osg::Vec3& position1, const osg::Vec3& position2)
{

   bool aboveHorizon = true; 

   //LET .FIRST.NODE.DISTANCE.TO.HORIZON
   //         = SQRT.F(MAX.F (2.0 * EARTH.RADIUS * .FIRST.NODE.POSITION(3), 1.0) )

   LCreal distance1 = lcSqrt( LCreal(2.0f * Basic::Nav::ERADM * -position1.z()) ); 
   if (distance1 < 1.0f) distance1 = 1.0f; 


   //      LET .SECOND.NODE.DISTANCE.TO.HORIZON
   //         = SQRT.F(MAX.F (2.0 * EARTH.RADIUS * .SECOND.NODE.POSITION(3), 1.0) )

   LCreal distance2 = lcSqrt( LCreal(2.0f * Basic::Nav::ERADM * -position2.z()) ); 
   if (distance2 < 1.0f) distance2 = 1.0f;

   //LET .RELATIVE.POSITION(*)
   //   = UT.LINEAR.COMBINATION.OF.VECTORS.F(1.0, .FIRST.NODE.POSITION(*),
   //                                        -1.0, .SECOND.NODE.POSITION(*))
   // LET .RELATIVE.POSITION(3) = 0.0

   // LET .GROUND.TRACK.RANGE = UT.NORM.F(.RELATIVE.POSITION(*))

   osg::Vec3 groundVec = position1 - position2;  

   LCreal gndRng = lcSqrt ((groundVec.x() * groundVec.x()) 
                     + (groundVec.y() * groundVec.y())); 

   //IF .GROUND.TRACK.RANGE < .FIRST.NODE.DISTANCE.TO.HORIZON
   //                        + .SECOND.NODE.DISTANCE.TO.HORIZON

   if (gndRng >= distance1 + distance2)
      aboveHorizon = false; 

    return aboveHorizon; 
}
示例#6
0
// getValue() -- get an object containing the real value to send
// or null(0) if the value hasn't changed.
Object* Component::SendData::getValue(const float value)
{
    Float* num = dynamic_cast<Float*>(past);
    if (num == 0) {
        if (past != 0) past->unref();
        past = new Float(value);
        return past;
    }
    if (*num != LCreal(value)) {
        *num = value;
        return num;
    }
    else return 0;
}
示例#7
0
//------------------------------------------------------------------------------
// onRfEmissionReturnEventAntenna() -- process Returned RF Emission Events
//------------------------------------------------------------------------------
bool Antenna::onRfEmissionReturnEventAntenna(Emission* const em)
{
    bool used = false;
    // Pass all returned emissions to our sensor
    RfSystem* sys1 = getSystem();
    if (sys1 != 0) {
        sys1->ref();

        // Compute antenna effective area
        double aea = getEffectiveArea(em->getGain(), em->getWavelength());
        // Same antenna -- polarization match -- polarization gain is 1.0
        // So just use Antenna effective area
        sys1->rfReceivedEmission(em, this, LCreal(aea));
        used = true;

        sys1->unref();
    }
    return used;
}
示例#8
0
//------------------------------------------------------------------------------
// irRequestSignature() -- Send an IR query packet at all active players to request an IR signature
//------------------------------------------------------------------------------
void IrSeeker::irRequestSignature(IrQueryMsg* const irQuery)
{
   // Need something to store the required data for the IR signatures and someone to send to

   Tdb* tdb0 = getCurrentTDB();
   Player* ownship = getOwnship();
   if (irQuery == 0 || tdb0 == 0 || ownship == 0) {
      // Clean up and leave
      if (tdb0 != 0) tdb0->unref();
      return;
   }

   // ---
   // Compute gimbal boresight data for our targets
   // ---

   // FAB - cannot use ownHdgOnly
   unsigned int ntgts = tdb0->computeBoresightData();
   if (ntgts > MAX_PLAYERS) ntgts = MAX_PLAYERS;

   // ---
   // If we have targets
   // ---
   const osg::Vec3d* losG = tdb0->getGimbalLosVectors();
   if (ntgts > 0 && losG != 0) {

      // Fetch the required data arrays from the TargetDataBlock
      const double* ranges = tdb0->getTargetRanges();
      const double* rngRates = tdb0->getTargetRangeRates();
      const double* anglesOffBoresight = tdb0->getBoresightErrorAngles();
      const osg::Vec3d* losO2T = tdb0->getLosVectors();
      const osg::Vec3d* losT2O = tdb0->getTargetLosVectors();
      Player** targets = tdb0->getTargets();
      LCreal maximumRange = irQuery->getMaxRangeNM()*Basic::Distance::NM2M;

      // ---
      // Send query packets to the targets
      // ---
      for (unsigned int i = 0; i < ntgts; i++) {

         // filter on sensor max range 
         // can't filter on sensor range in processPlayers - different sensors can have different max range
         if (maximumRange > 0.0 && ranges[i] > maximumRange)
            continue;

         // Get a free query packet
         lcLock(freeQueryLock);
         IrQueryMsg* query = freeQueryStack.pop();
         lcUnlock(freeQueryLock);

         if (query == 0) { 
            query = new IrQueryMsg();
            //if (ownship->getID() != 1) {
            //    static tcnt = 0;
            //    tcnt++;

            //if (isMessageEnabled(MSG_INFO)) {
            //    std::cout << "new IrQueryMsg(" << this << "): " << tcnt << ", inused: " << inUseEmQueue.entries() << ", em = " << em << std::endl;
            //}

            //}
         }

         // Send the IR query message to the other player
         if (query != 0) {

            // a) Copy the template query msg
            *query = *irQuery;

            // b) Set target unique data
            query->setGimbal(this);
            query->setOwnship(ownship);

            query->setRange( LCreal(ranges[i]) );
            query->setLosVec( losO2T[i] );
            query->setTgtLosVec( losT2O[i] );
            query->setRangeRate( LCreal(rngRates[i]) );
            query->setTarget(targets[i]);
            query->setAngleOffBoresight( LCreal(anglesOffBoresight[i]) );

            query->setGimbalAzimuth( LCreal(getAzimuth()) );
            query->setGimbalElevation( LCreal(getElevation()) );

            // c) Send the query to the target
            targets[i]->event(IR_QUERY, query);

            // d) Dispose of the query
            if (query->getRefCount() <= 1) {
               // Recycle the query packet
               query->clear();
               lcLock(freeQueryLock);
               if (freeQueryStack.isNotFull()) {
                  freeQueryStack.push(query);
               }
               else {
                  query->unref();
               }
               lcUnlock(freeQueryLock);
            }
            else {
               // Store for future reference
               lcLock(inUseQueryLock);
               if (inUseQueryQueue.isNotFull()) {
                  inUseQueryQueue.put(query);
               }
               else {
                  // Just forget it
                  query->unref();
               }
               lcUnlock(inUseQueryLock);
            }
         }
         else {
            // When we couldn't get a free query packet
            if (isMessageEnabled(MSG_WARNING)) {
               std::cerr << "Iw Seeker: OUT OF Query messages!" << std::endl;
            }
         }
      }
   }

   // Unref() the TDB
   tdb0->unref();
}
示例#9
0
//------------------------------------------------------------------------------
// burstFrame() -- generate a small burst of bullets (usually every 1/10 seconds)
//------------------------------------------------------------------------------
void Gun::burstFrame()
{
   // Compute the number of rounds this burst
   int ibullets = static_cast<int>(rcount + 0.5f);

   // Do we have any bullets to fire ...
   if (ibullets > 0){

      // Decrease the number of rounds remaining
      if ( !isUnlimited() ) {
         if (ibullets > rounds) {
            ibullets = rounds;
            rcount = LCreal(ibullets);
         }
         rounds -= ibullets;
      }


      // Update the rounds fired count
      rcount -= ibullets;

      // Log this event
      Player* ownship = static_cast<Player*>( findContainerByType(typeid(Player)) );

      if (ownship != 0) {
         BEGIN_RECORD_DATA_SAMPLE( getSimulation()->getDataRecorder(), REID_GUN_FIRED )
            SAMPLE_1_OBJECT( ownship )
            SAMPLE_1_VALUE( rcount )
         END_RECORD_DATA_SAMPLE()
      }

      // TabLogger is deprecated
      if (ownship != nullptr && getAnyEventLogger() != nullptr) {
         TabLogger::TabLogEvent* evt = new TabLogger::LogGunActivity(1, ownship, ibullets); // type 1 == gun fired
         getAnyEventLogger()->log(evt);
         evt->unref();
      }

      // When we have a bullet model ... we're going to create a bullet (weapon)
      // player to flyout the rounds.
      Bullet* wpn = getBulletType();
      Simulation* sim = static_cast<Simulation*>( findContainerByType(typeid(Simulation)) );
      if (wpn != nullptr && ownship != nullptr && sim != nullptr) {

         // Compute the bullet burst's initial position and velocity
         osg::Vec3 ipos = computeInitBulletPosition();
         osg::Vec3 ivel = computeInitBulletVelocity();

         // Get the bullet player being used to fly-out the bullets
         Bullet* flyout = static_cast<Bullet*>( wpn->getFlyoutWeapon() );
         if (flyout == nullptr) {
            // If we don't have the flyout bullet (i.e., weapon and player) ... create it
            wpn->setLaunchVehicle(ownship);
            flyout = static_cast<Bullet*>( wpn->release() );
         }

            // The flyout bullet (player) will handle this burst of bullets.
         if (flyout != nullptr) {
            flyout->burstOfBullets(&ipos, &ivel, ibullets, getRoundsPerMinute(), sim->getNewWeaponEventID() );
         }

         // Cleanup
         if (flyout != nullptr) { flyout->unref(); flyout = nullptr; }

      }
   }
   else rcount = 0;
示例#10
0
//------------------------------------------------------------------------------
// getRayAzimuth() -- 
//------------------------------------------------------------------------------
LCreal Rwr::getRayAzimuth(const int idx) const
{
    LCreal az = getDegreesPerRay() * LCreal(idx);
    return lcAepcDeg(az);
}
示例#11
0
//------------------------------------------------------------------------------
// onRfEmissionEventAntenna() -- process events for RF Emission not sent by us.
//
// 1) Build a list of emission packets from the queue and compute the
//    Line-Of-Sight (LOS) vectors back to the transmitter.
//
// 2) Transform LOS vectors to antenna coordinates
//
// 3) Compute antenna gains in the direction of the transmitter
//
// 4) Compute Antenna Effective Gains
//
// 5) Compute Antenna Effective Area and Polarization Gains
//
// 6) Compute total receiving antenaa gain and send the emission to our sensor
//------------------------------------------------------------------------------
bool Antenna::onRfEmissionEvent(Emission* const em)
{
   // Is this emission from a player of interest?
   if (fromPlayerOfInterest(em)) {

      Player* ownship = getOwnship();
      RfSystem* sys1 = getSystem();
      if (ownship != 0 && sys1 != 0) {
         sys1->ref();

         // Line-Of-Sight (LOS) vectors back to the transmitter.
         osg::Vec3d xlos = em->getTgtLosVec();
         osg::Vec4d los0( xlos.x(), xlos.y(), xlos.z(), 0.0);

         // 2) Transform local NED LOS vectors to antenna coordinates
         osg::Matrixd mm = getRotMat();
         mm *= ownship->getRotMat();
         osg::Vec4d losA = mm * los0;

         // ---
         // Compute antenna gains in the direction of the transmitter
         // ---
         double rGainDb = 0.0f;
         if (gainPattern != 0) {

            Basic::Func1* gainFunc1 = dynamic_cast<Basic::Func1*>(gainPattern);
            Basic::Func2* gainFunc2 = dynamic_cast<Basic::Func2*>(gainPattern);
            if (gainFunc2 != 0) {
               // ---
               // 3-a) Antenna pattern: 2D table (az & el off antenna boresight)
               // ---

               // Get component arrays and ground range squared
               double xa =  losA.x();
               double ya =  losA.y();
               double za = -losA.z();
               double ra2 = xa*xa + ya*ya;

               // Compute range along antenna x-y plane
               double ra = sqrt(ra2);

               // Compute azimuth off boresight
               double aazr = atan2(ya,xa);

               // Compute elevation off boresight
               double aelr = atan2(za,ra);

               // Lookup gain in 2D table and convert from dB
               if (gainPatternDeg)
                  rGainDb = gainFunc2->f( aazr * Basic::Angle::R2DCC, aelr * Basic::Angle::R2DCC );
               else
                  rGainDb = gainFunc2->f( aazr, aelr );

            }

            else if (gainFunc1 != 0) {
               // ---
                  // 3-b) Antenna Pattern: 1D table (off antenna boresight only
                  // ---

                  // Compute angle off antenna boresight
                  double aar = acos(losA.x());

                  // Lookup gain in 1D table and convert from dB
                  if (gainPatternDeg)
                     rGainDb = gainFunc1->f( aar * Basic::Angle::R2DCC );
                  else
                     rGainDb = gainFunc1->f(aar);

            }
         }

         // Compute off-boresight gain
         double rGain = pow(10.0,rGainDb/10.0);

         // Compute Antenna Effective Gain
         double aeGain = rGain * getGain();
         double lambda = em->getWavelength();
         double aea = getEffectiveArea(aeGain, lambda);

         double pGain = getPolarizationGain(em->getPolarization());
         double raGain = aea * pGain;

         sys1->rfReceivedEmission(em, this, LCreal(raGain));

         sys1->unref();
      }

   }

   return BaseClass::onRfEmissionEvent(em);
}
示例#12
0
//------------------------------------------------------------------------------
// rfTransmit() -- Transmit a RF emission packet at all active players.
//------------------------------------------------------------------------------
void Antenna::rfTransmit(Emission* const xmit)
{
   // Need something to transmit and someone to send to
   Tdb* tdb = getCurrentTDB();
   Player* ownship = getOwnship();
   if (xmit == 0 || tdb == 0 || ownship == 0) {
      // Clean up and leave
      if (tdb != 0) tdb->unref();
      return;
   }

   // ---
   // Compute gimbal boresight data for our targets
   // ---
   unsigned int ntgts = tdb->computeBoresightData();
   if (ntgts > MAX_PLAYERS) ntgts = MAX_PLAYERS;

   // ---
   // If we have targets
   // ---
   const osg::Vec3d* losG = tdb->getGimbalLosVectors();
   if (ntgts > 0 && losG != 0) {

      // ---
      // Lookup gain from antenna gain pattern, compute antenna
      // effective gain and effective radiated power.    
      // ---
      bool haveGainTgt = false;
      double gainTgt[MAX_PLAYERS];
      if (gainPattern != 0) {
         Basic::Func1* gainFunc1 = dynamic_cast<Basic::Func1*>(gainPattern);
         Basic::Func2* gainFunc2 = dynamic_cast<Basic::Func2*>(gainPattern);
         if (gainFunc2 != 0) {
            // ---
            // Antenna pattern: 2D table (az & el off antenna boresight)
            // ---

            // Compute azimuth off boresight (radians)
            const double* aazr = tdb->getBoresightAzimuthErrors();

            // Compute elevation off boresight (radians)
            const double* aelr = tdb->getBoresightElevationErrors();

            // Lookup gain in 2D table and convert from dB
            double gainTgt0[MAX_PLAYERS];
            if (gainPatternDeg) {
               for (unsigned int i1 = 0; i1 < ntgts; i1++) {
                  gainTgt0[i1] = gainFunc2->f( (aazr[i1] * Basic::Angle::R2DCC), (aelr[i1] * Basic::Angle::R2DCC) )/10.0;
               }
            }
            else {
               for (unsigned int i1 = 0; i1 < ntgts; i1++) {
                  gainTgt0[i1] = gainFunc2->f( aazr[i1], aelr[i1] )/10.0f;
               }
            }
            pow10Array(gainTgt0, gainTgt, ntgts);
            haveGainTgt = true;
         }
         else if (gainFunc1 != 0) {
            // ---
            // Antenna Pattern: 1D table (off antenna boresight only
            // ---

            // Compute angles off antenna boresight (radians)
            const double* aar = tdb->getBoresightErrorAngles();

            // Lookup gain in 1D table and convert from dB
            double gainTgt0[MAX_PLAYERS];
            if (gainPatternDeg) {
               for (unsigned int i2 = 0; i2 < ntgts; i2++) {
                  gainTgt0[i2] = gainFunc1->f( aar[i2]*Basic::Angle::R2DCC )/10.0;
               }
            }
            else {
               for (unsigned int i2 = 0; i2 < ntgts; i2++) {
                  gainTgt0[i2] = gainFunc1->f( aar[i2] )/10.0f;
               }
            }
            pow10Array(gainTgt0, gainTgt, ntgts);
            haveGainTgt = true;
         }
      }
      if (!haveGainTgt) {
         // ---
         // No antenna pattern table
         // ---
         for (unsigned int i = 0; i < ntgts; i++) {
            gainTgt[i] = 1.0f;
         }
      }

      // Compute antenna effective gain
      double aeGain[MAX_PLAYERS];
      multArrayConst(gainTgt, getGain(), aeGain, ntgts);

      // Compute Effective Radiated Power (watts) (Equation 2-1)
      double erp[MAX_PLAYERS];
      multArrayConst(aeGain, xmit->getPower(), erp, ntgts);

      // Fetch the required data arrays from the TargetDataBlock
      const double* ranges = tdb->getTargetRanges();
      const double* rngRates = tdb->getTargetRangeRates();
      const osg::Vec3d* losO2T = tdb->getLosVectors();
      const osg::Vec3d* losT2O = tdb->getTargetLosVectors();
      Player** targets = tdb->getTargets();

      // ---
      // Send emission packets to the targets
      // ---
      for (unsigned int i = 0; i < ntgts; i++) {

         // Only of power exceeds an optional threshold
         if (erp[i] > threshold) {

            // Get a free emission packet
            Emission* em(0);
            if (recycle) {
               lcLock(freeEmLock);
               em = freeEmStack.pop();
               lcUnlock(freeEmLock);
            }

            bool cloned = false;
            if (em == 0) {
               // Otherwise, clone a new one 
               em = xmit->clone();
               cloned = true;
            }

            // Send the emission to the other player
            if (em != 0) {

               // a) Copy the template emission
               if (!cloned) *em = *xmit;

               // b) Set target unique data
               em->setGimbal(this);
               em->setOwnship(ownship);

               em->setRange( LCreal(ranges[i]) );
               em->setLosVec(losO2T[i]);
               em->setTgtLosVec(losT2O[i]);
               em->setRangeRate( LCreal(rngRates[i]) );
               em->setTarget(targets[i]);

               em->setGimbalAzimuth( LCreal(getAzimuth()) );
               em->setGimbalElevation( LCreal(getElevation()) );
               em->setPower( LCreal(erp[i]) );
               em->setGain( LCreal(aeGain[i]) );
               em->setPolarization(getPolarization());
               em->setLocalPlayersOnly( isLocalPlayersOfInterestOnly() );

               // c) Send the emission to the target
               targets[i]->event(RF_EMISSION, em);

               // d) Recycle the emission
               bool recycled = false;
               if (recycle) {
                  lcLock(inUseEmLock);
                  if (inUseEmQueue.isNotFull()) {
                     // Store for future reference
                     inUseEmQueue.put(em);
                     recycled = true;
                  }
                  lcUnlock(inUseEmLock);
               }

               // or just forget it
               else {
                  em->unref();
              }

            }
            else {
               // When we couldn't get a free emission packet
               if (isMessageEnabled(MSG_ERROR)) {
                  std::cerr << "Antenna: OUT OF EMISSIONS!" << std::endl;
               }
            }
         }

      }
   }

   // Unref() the TDB
   tdb->unref();
}