//------------------------------------------------------------------------------ // transmit() -- send radar emissions //------------------------------------------------------------------------------ void Radar::transmit(const LCreal dt) { BaseClass::transmit(dt); // Transmitting, scanning and have an antenna? if ( !areEmissionsDisabled() && isTransmitting() ) { // Send the emission to the other player Emission* em = new Emission(); em->setFrequency(getFrequency()); em->setBandwidth(getBandwidth()); const LCreal prf1 = getPRF(); em->setPRF(prf1); int pulses = static_cast<int>(prf1 * dt + 0.5); if (pulses == 0) pulses = 1; // at least one em->setPulses(pulses); const LCreal p = getPeakPower(); em->setPower(p); em->setMaxRangeNM(getRange()); em->setPulseWidth(getPulseWidth()); em->setTransmitLoss(getRfTransmitLoss()); em->setReturnRequest( isReceiverEnabled() ); em->setTransmitter(this); getAntenna()->rfTransmit(em); em->unref(); } }
//------------------------------------------------------------------------------ // transmitDataMessage() -- send a data message emission; // returns true if the data emission was sent. //------------------------------------------------------------------------------ bool CommRadio::transmitDataMessage(base::Object* const msg) { bool sent = false; // Transmitting, scanning and have an antenna? if(getOwnship() == nullptr) { if (isMessageEnabled(MSG_DEBUG)) { std::cout << "CommRadio ownship == nullptr!" << std::endl; } return sent; } if (msg != nullptr && isTransmitterEnabled() && getAntenna() != nullptr) { // Send the emission to the other player Emission* em = new Emission(); em->setDataMessage(msg); em->setFrequency(getFrequency()); em->setBandwidth(getBandwidth()); em->setPower(getPeakPower()); em->setTransmitLoss(getRfTransmitLoss()); em->setMaxRangeNM(getMaxDetectRange()); em->setTransmitter(this); em->setReturnRequest(false); getAntenna()->rfTransmit(em); em->unref(); sent = true; } return sent; }
//------------------------------------------------------------------------------ // clearQueues() -- clear out all queues //------------------------------------------------------------------------------ void Antenna::clearQueues() { lcLock(freeEmLock); Emission* em = freeEmStack.pop(); while (em != 0) { em->unref(); em = freeEmStack.pop(); } lcUnlock(freeEmLock); lcLock(inUseEmLock); em = inUseEmQueue.get(); while (em != 0) { em->unref(); em = inUseEmQueue.get(); } lcUnlock(inUseEmLock); }
//------------------------------------------------------------------------------ // process() -- process the reports //------------------------------------------------------------------------------ void Rwr::process(const LCreal dt) { BaseClass::process(dt); // --- // Process Emissions into tracks // --- for (Emission* em = rptQueue.get(); em != 0; em = rptQueue.get()) { // finished em->unref(); // this undoes the ref() added in Rwr::receive() } }
//------------------------------------------------------------------------------ // killedNotification() -- We were just killed by player 'p' //------------------------------------------------------------------------------ bool Rwr::killedNotification(Player* const p) { // --- // Clear out the queues // --- for (Emission* em = rptQueue.get(); em != 0; em = rptQueue.get()) { em->unref(); } // --- // Make sure our base class knows we're dead. // --- BaseClass::killedNotification(p); return true; }
//------------------------------------------------------------------------------ // receive() -- process received emissions //------------------------------------------------------------------------------ void Radio::receive(const double dt) { BaseClass::receive(dt); // Receiver losses double noise = getRfRecvNoise(); // --- // Process Emissions // --- Emission* em = nullptr; double signal = 0; // Get an emission from the queue base::lock(packetLock); if (np > 0) { np--; // Decrement 'np', now the array index em = packets[np]; signal = signals[np]; } base::unlock(packetLock); while (em != nullptr) { // Signal/Noise (Equation 2-9) double sn = signal / noise; double snDbl = 10.0 * std::log10(sn); // Is S/N above receiver threshold? if ( snDbl >= getRfThreshold() ) { // Report this valid emission to the radio model ... receivedEmissionReport(em); } em->unref(); em = nullptr; // Get another emission from the queue base::lock(packetLock); if (np > 0) { np--; em = packets[np]; signal = signals[np]; } base::unlock(packetLock); } }
//------------------------------------------------------------------------------ // clearTracksAndQueues() -- clear out tracks and queues //------------------------------------------------------------------------------ void Radar::clearTracksAndQueues() { // Clear reports lcLock(myLock); for (unsigned int i = 0; i < numReports && i < MAX_REPORTS; i++) { if (reports[i] != nullptr) { reports[i]->unref(); reports[i] = nullptr; } } numReports = 0; lcUnlock(myLock); // --- // Clear out the queues // --- lcLock(myLock); for (Emission* em = rptQueue.get(); em != nullptr; em = rptQueue.get()) { em->unref(); } while (rptSnQueue.isNotEmpty()) { rptSnQueue.get(); } lcUnlock(myLock); }
//------------------------------------------------------------------------------ // process() -- Process phase //------------------------------------------------------------------------------ void Antenna::process(const LCreal dt) { BaseClass::process(dt); // --- // Recycle emissions ... // Update emission queues: from 'in-use' to 'free' // --- if (recycle) { unsigned int n = inUseEmQueue.entries(); for (unsigned int i = 0; i < n; i++) { lcLock(inUseEmLock); Emission* em = inUseEmQueue.get(); lcUnlock(inUseEmLock); if (em != 0 && em->getRefCount() > 1) { // Others are still referencing the emission, put back on in-use queue lcLock(inUseEmLock); inUseEmQueue.put(em); lcUnlock(inUseEmLock); } else if (em != 0 && em->getRefCount() <= 1) { // No one else is referencing the emission, push to the free stack em->clear(); lcLock(freeEmLock); if (freeEmStack.isNotFull()) freeEmStack.push(em); else em->unref(); lcUnlock(freeEmLock); } } } }
//------------------------------------------------------------------------------ // process() -- process the TWS reports //------------------------------------------------------------------------------ void Radar::process(const LCreal dt) { BaseClass::process(dt); // Find the track manager TrackManager* tm = getTrackManager(); if (tm == nullptr) { // No track manager! Then just flush the input queue. lcLock(myLock); for (Emission* em = rptQueue.get(); em != nullptr; em = rptQueue.get()) { em->unref(); rptSnQueue.get(); } lcUnlock(myLock); } // --- // When end of scan, send all unsent reports to the track manager // --- if (endOfScanFlg) { endOfScanFlg = false; lcLock(myLock); for (unsigned int i = 0; i < numReports && i < MAX_REPORTS; i++) { if (tm != nullptr) { tm->newReport(reports[i], rptMaxSn[i]); } reports[i]->unref(); reports[i] = nullptr; rptMaxSn[i] = 0; } numReports = 0; lcUnlock(myLock); } // --- // Process our returned emissions into reports for the track manager // 1) Match each emission with existing reports // 2) On emission/report matches, if the S/N value of the new emission // is greater than the report, use the new emission // 3) Create new reports for unmatched emissions // --- lcLock(myLock); while (rptQueue.isNotEmpty()) { // Get the emission Emission* em = rptQueue.get(); LCreal snDbl = rptSnQueue.get(); if (em != nullptr) { // --- // 1) Match the emission with existing reports // --- int matched = -1; for (unsigned int i = 0; i < numReports && matched < 0; i++) { // Compare targets if ( em->getTarget() == reports[i]->getTarget() ) { // We have a match!!! matched = i; } } // --- // 2) On emission/report match // --- if (matched >= 0) { if (snDbl > rptMaxSn[matched]) { // When the S/N value of the new emission is greater than the report, // we use the new emission reports[matched]->unref(); em->ref(); reports[matched] = em; rptMaxSn[matched] = snDbl; } } // --- // 3) Create a new report entry for the unmatched emission // --- if (matched < 0 && numReports < MAX_REPORTS) { em->ref(); reports[numReports] = em; rptMaxSn[numReports] = snDbl; numReports++; } // finished em->unref(); } } lcUnlock(myLock); }
//------------------------------------------------------------------------------ // receive() -- process received emissions //------------------------------------------------------------------------------ void Radar::receive(const LCreal dt) { BaseClass::receive(dt); // Can't do anything without an antenna if (getAntenna() == nullptr) return; // Clear the next sweep csweep = computeSweepIndex( static_cast<LCreal>(Basic::Angle::R2DCC * getAntenna()->getAzimuth()) ); clearSweep(csweep); // Compute noise level // CGB moved here from RfSystem // Basically, we're simulation Hannen's S/I equation from page 356 of his notes. // Where I is N + J. J is noise from jamming. // Receiver Loss affects the total I, so we have to wait until this point to account for it. const LCreal interference = (getRfRecvNoise() + jamSignal) * getRfReceiveLoss(); const LCreal noise = getRfRecvNoise() * getRfReceiveLoss(); currentJamSignal = jamSignal * getRfReceiveLoss(); int countNumJammedEm = 0; // --- // Process Returned Emissions // --- Emission* em = nullptr; LCreal signal = 0; // Get an emission from the queue lcLock(packetLock); if (np > 0) { np--; // Decrement 'np', now the array index em = packets[np]; signal = signals[np]; } lcUnlock(packetLock); while (em != nullptr) { // exclude noise jammers (accounted for already in RfSystem::rfReceivedEmission) if (em->getTransmitter() == this || (em->isECM() && !em->isECMType(Emission::ECM_NOISE)) ) { // compute the return trip loss ... // Compute signal received LCreal rcs = em->getRCS(); // Signal Equation (Equation 2-7) LCreal rl = em->getRangeLoss(); signal *= (rcs * rl); // Integration gain signal *= rfIGain; // Range attenuation: we don't want the strong signal from short range targets LCreal maxRng = getRange() * Basic::Distance::NM2M; //LCreal maxRng4 = (maxRng*maxRng*maxRng*maxRng); //LCreal rng = (em->getRange()); const LCreal s1 = 1.0; //if (rng > 0) { // LCreal rng4 = (rng*rng*rng*rng); // s1 = (rng4/maxRng4); // if (s1 > 1.0f) s1 = 1.0f; //} signal *= s1; if (signal > 0.0) { // Signal/Noise (Equation 2-9) const LCreal signalToInterferenceRatio = signal / interference; const LCreal signalToInterferenceRatioDbl = 10.0f * lcLog10(signalToInterferenceRatio); const LCreal signalToNoiseRatio = signal / noise; const LCreal signalToNoiseRatioDbl = 10.0f * lcLog10(signalToNoiseRatio); //std::cout << "Radar::receive(" << em->getTarget() << "): "; //std::cout << " pwr=" << em->getPower(); //std::cout << " gain=" << em->getGain(); //std::cout << " rl=" << rl; //std::cout << " rcs=" << rcs; //std::cout << " signal=" << signal; //std::cout << " recvN=" << getRfRecvNoise(); //std::cout << " signalToInterferenceRatio=" << signalToInterferenceRatio; //std::cout << " signalToInterferenceRatioDbl=" << signalToInterferenceRatioDbl; //std::cout << " thrs=" << getRfThreshold(); //std::cout << std::endl; // Is S/N above receiver threshold and within 125% of max range? // CGB, if "signal <= 0.0", then "signalToInterferenceRatioDbl" is probably invalid // we should probably do something smart with "signalToInterferenceRatioDbl" above as well. lcLock(myLock); if (signalToInterferenceRatioDbl >= getRfThreshold() && em->getRange() <= (maxRng*1.25) && rptQueue.isNotFull()) { // send the report to the track manager em->ref(); rptQueue.put(em); rptSnQueue.put(signalToInterferenceRatioDbl); //std::cout << " (" << em->getRange() << ", " << signalToInterferenceRatioDbl << ", " << signalToInterferenceRatio << ", " << signalToInterferenceRatioDbl << ")"; // Save signal for real-beam display int iaz = csweep; int irng = computeRangeIndex( em->getRange() ); sweeps[iaz][irng] += (signalToInterferenceRatioDbl/100.0f); vclos[iaz][irng] = em->getRangeRate(); } else if (signalToInterferenceRatioDbl < getRfThreshold() && signalToNoiseRatioDbl >= getRfThreshold()) { countNumJammedEm++; } lcUnlock(myLock); } } em->unref(); // this unref() undoes the ref() done by RfSystem::rfReceivedEmission em = nullptr; //if (np >= 0 && np < MAX_EMISSIONS) { // packets[np] = 0; // signals[np] = 0; //} // Get another emission from the queue lcLock(packetLock); if (np > 0) { np--; em = packets[np]; signal = signals[np]; } lcUnlock(packetLock); } //std::cout << std::endl; numberOfJammedEmissions = countNumJammedEm; // Set interference signal back to zero jamSignal = 0; }
//------------------------------------------------------------------------------ // receive() -- process received emissions //------------------------------------------------------------------------------ void Rwr::receive(const LCreal dt) { BaseClass::receive(dt); // clear the back buffer clearRays(0); // Receiver losses #if 0 LCreal noise = getRfRecvNoise(); #else LCreal noise = getRfRecvNoise() * getRfReceiveLoss(); #endif // Process received emissions TrackManager* tm = getTrackManager(); Emission* em = 0; LCreal signal = 0; // Get an emission from the queue lcLock(packetLock); if (np > 0) { np--; // Decrement 'np', now the array index em = packets[np]; signal = signals[np]; } lcUnlock(packetLock); while (em != 0) { //std::cout << "Rwr::receive(" << em->getOwnship() << "): "; //std::cout << " pwr=" << em->getPower(); //std::cout << " gain=" << em->getGain(); //std::cout << " rl=" << rl; //std::cout << " pulses=" << pulses; //std::cout << " losses=" << losses; //std::cout << " signal=" << signal; //std::cout << " recvN=" << getRfRecvNoise(); //std::cout << " sn=" << sn; //std::cout << " snDbl=" << snDbl; //std::cout << " thrs=" << getRfThreshold(); //std::cout << std::endl; // CGB, if "signal <= 0.0", then "snDbl" is probably invalid if (signal > 0.0 && dt != 0.0) { // Signal over noise (equation 3-5) LCreal sn = signal / noise; LCreal snDbl = 10.0f * lcLog10(sn); // Is S/N above receiver threshold ## dpg -- for now, don't include ECM emissions if (snDbl > getRfThreshold() && !em->isECM() && rptQueue.isNotFull()) { // Send report to the track manager if (tm != 0) { tm->newReport(em, snDbl); } // Get Angle Of Arrival LCreal aoa= em->getAzimuthAoi(); // Store received power for real-beam display LCreal sigDbl = 10.0f * lcLog10(signal); LCreal signal10 = (sigDbl + 50.0f)/50.f; int idx = getRayIndex( static_cast<LCreal>(Basic::Angle::R2DCC * aoa) ); rays[0][idx] = lim01(rays[0][idx] + signal10); //if (idx == 0 && getOwnship()->getID() == 1011) { // std::cout << "sig = " << signal10 << std::endl; //} // Send to the track list processor em->ref(); // ref() for track list processing rptQueue.put(em); } } // finished em->unref(); // this unref() undoes the ref() done by RfSystem::rfReceivedEmission em = 0; // Get another emission from the queue lcLock(packetLock); if (np > 0) { np--; em = packets[np]; signal = signals[np]; } lcUnlock(packetLock); } // Transfer the rays xferRays(); }
//------------------------------------------------------------------------------ // shutdownNotification() //------------------------------------------------------------------------------ bool Rwr::shutdownNotification() { // Clear out the queues for (Emission* em = rptQueue.get(); em != 0; em = rptQueue.get()) { em->unref(); } return BaseClass::shutdownNotification(); }
//------------------------------------------------------------------------------ // deleteData() -- delete member data //------------------------------------------------------------------------------ void Rwr::deleteData() { // Clear out the queues for (Emission* em = rptQueue.get(); em != 0; em = rptQueue.get()) { em->unref(); } }