//------------------------------------------------------------------------------ // 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; }
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; }
//------------------------------------------------------------------------------ // 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() }
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++; } } }
//------------------------------------------------------------------------------ // 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; }
// 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; }
//------------------------------------------------------------------------------ // 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; }
//------------------------------------------------------------------------------ // 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(); }
//------------------------------------------------------------------------------ // 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;
//------------------------------------------------------------------------------ // getRayAzimuth() -- //------------------------------------------------------------------------------ LCreal Rwr::getRayAzimuth(const int idx) const { LCreal az = getDegreesPerRay() * LCreal(idx); return lcAepcDeg(az); }
//------------------------------------------------------------------------------ // 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); }
//------------------------------------------------------------------------------ // 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(); }