From bc26cbc7061270522cc0d7263d2abc410a35a712 Mon Sep 17 00:00:00 2001 From: Kevin D Date: Wed, 6 May 2026 17:16:57 -0700 Subject: [PATCH] rfsensor parameterization --- @rfSensor/RSS.m | 2 +- @rfSensor/initialize.m | 12 +++++++++--- @rfSensor/pathLoss.m | 2 +- @rfSensor/plotParameters.m | 2 +- @rfSensor/plotPerformance.m | 2 +- @rfSensor/rfSensor.m | 4 +++- @rfSensor/transmitterGain.m | 4 +--- @sensingObjective/plot.m | 2 +- test/test_rfSensor.m | 28 +++++++++++++++++++--------- 9 files changed, 37 insertions(+), 21 deletions(-) diff --git a/@rfSensor/RSS.m b/@rfSensor/RSS.m index c512a56..ef05692 100644 --- a/@rfSensor/RSS.m +++ b/@rfSensor/RSS.m @@ -10,6 +10,6 @@ function value = RSS(obj, d, t, a) end assert(size(d, 1) == size(t, 1), "Mismatch in number of distances (%d) and tilts (%d) provided", size(d, 1), size(t, 1)); - % RSS (dBm) = TX Power (dBm) + TX Antenna Gain (dB) + RX Antenna Gain (dBi) - Path Loss (dB) + % RSS (dBm) = TX Power (dBm) + TX Antenna Gain (dBi) + RX Antenna Gain (dBi) - Path Loss (dB) value = obj.P_TX_dBm + obj.transmitterGain(t, a) + obj.G_RX_dBi - obj.pathLoss(d); end \ No newline at end of file diff --git a/@rfSensor/initialize.m b/@rfSensor/initialize.m index 14db6f3..156d4f1 100644 --- a/@rfSensor/initialize.m +++ b/@rfSensor/initialize.m @@ -1,26 +1,32 @@ -function obj = initialize(obj, txPower, bandwidth, centerFreq, rxGain_dBi, tilt, azimuth) +function obj = initialize(obj, txPower, bandwidth, centerFreq, rxGain_dBi, beamwidthExponent, tilt, azimuth, lossExponent) arguments (Input) obj (1, 1) {mustBeA(obj, "rfSensor")} txPower (1, 1) double; bandwidth (1, 1) double; centerFreq (1, 1) double; rxGain_dBi (1, 1) double; + beamwidthExponent (1, 1) double; tilt (1, 1) double = 0; azimuth (1, 1) double = 0; + lossExponent (1, 1) double = NaN; end arguments (Output) obj (1, 1) {mustBeA(obj, "rfSensor")} end - % Provided values + %% Provided values obj.P_TX = txPower; % Transmit power (W) obj.BW = bandwidth; % Bandwidth (Hz) obj.f_c = centerFreq; % Center frequency (Hz) obj.G_RX_dBi = rxGain_dBi; % Receiving Antenna Gain (dBi) + obj.beamwidthExponent = beamwidthExponent; % Defines how focused the antenna beam is + obj.lossExponent = lossExponent; + + % Define initial antenna pointing obj.tilt = tilt; obj.azimuth = azimuth; - % Computed values + %% Computed values obj.P_TX_dBm = 10*log10(obj.P_TX/1e-3); % Transmit power in dBm obj.N = obj.k_B * obj.T_0 * obj.BW; % Thermal noise end \ No newline at end of file diff --git a/@rfSensor/pathLoss.m b/@rfSensor/pathLoss.m index c638699..9970f00 100644 --- a/@rfSensor/pathLoss.m +++ b/@rfSensor/pathLoss.m @@ -8,6 +8,6 @@ function L_FSPL_dB = pathLoss(obj, d) end % Free Space Path Loss (dB); d clamped away from zero (log undefined at d=0) - L_FSPL_dB = 20*log10(max(d, eps)) + 20*log10(obj.f_c) + 20*log10((4*pi)/obj.c); + L_FSPL_dB = obj.lossExponent * 10 * log10(max(d, eps)) + 20 * log10(obj.f_c) + 20 * log10((4*pi)/obj.c); end diff --git a/@rfSensor/plotParameters.m b/@rfSensor/plotParameters.m index 002aab9..5f24a6e 100644 --- a/@rfSensor/plotParameters.m +++ b/@rfSensor/plotParameters.m @@ -40,7 +40,7 @@ function f = plotParameters(obj) end colormap(turbo); - colorbar; + c = colorbar; c.Label.String = "Received Signal Strength (dB)"; daspect([1 1 0.2]); xlabel('X (log_{10} units)'); ylabel('Y (log_{10} units)'); zlabel('log_{10} Altitude (m)'); set(gca, 'ZDir', 'reverse'); diff --git a/@rfSensor/plotPerformance.m b/@rfSensor/plotPerformance.m index df9dfe9..f36dcc1 100644 --- a/@rfSensor/plotPerformance.m +++ b/@rfSensor/plotPerformance.m @@ -52,7 +52,7 @@ function f = plotPerformance(obj, altitude, otherSensorsPos, otherSensors) colorbar; xlabel("X (m)"); ylabel("Y (m)"); title("Linearly Normalized SNR (dB)"); subtitle("No interfering sources"); - addSensorOverlay(gca, sensorXY, sensorTilts, sensorAzimuths, tailScale); + addSensorOverlay(gca, sensorXY(1, 1:2), sensorTilts(1, 1), sensorAzimuths(1, 1), tailScale); nexttile; imagesc(distances, distances, SINR); diff --git a/@rfSensor/rfSensor.m b/@rfSensor/rfSensor.m index 66ce3b2..0cc33ef 100644 --- a/@rfSensor/rfSensor.m +++ b/@rfSensor/rfSensor.m @@ -4,6 +4,7 @@ classdef rfSensor c = 3e8; % Speed of light (m/s) k_B = 1.38e-23 % Boltzmann constant (W/Hz/K) for thermal noise model T_0 = 300; % Ambient temperature (Kelvin) for thermal noise model + lossExponent = NaN; % Path loss exponent (2 for free space, up to 6 for the lossiest environments) % Sensor parameters P_TX = NaN; % Transmit power (Watts) BW = NaN; % Bandwidth (Hz) @@ -11,6 +12,7 @@ classdef rfSensor G_RX_dBi = NaN; % Receiver antenna gain tilt = NaN; % Antenna boresight tilt (deg): 0=nadir, 90=horizon azimuth = NaN; % Antenna boresight azimuth (deg): 0=+y, 90=+x, 180=-y, 270=-x + beamwidthExponent = NaN; % Antenna beamwidth exponent for cosine radiation pattern, larger exponent -> narrower beam % Values computed at initialization P_TX_dBm = NaN; % Transmit power (dBm) N = NaN; % Thermal noise @@ -19,7 +21,7 @@ classdef rfSensor end methods (Access = public) - [obj] = initialize(obj, txPower, bandwidth, centerFreq, rxGain, tilt, azimuth); % initialize sensor, define parameters + [obj] = initialize(obj, txPower, bandwidth, centerFreq, rxGain, beamwidthExponent, tilt, azimuth); % initialize sensor, define parameters [SINR, SNR, obj, otherSensors] = sensorPerformance(obj, agentPos, targetPos, otherSensorsPos, otherSensors); % determine sensor performance for a given single sensor and target geometry [d, t, a] = computePointToPoints(obj, agentPos, targetPos); [value] = halfAngle(obj); % tilt angle (deg) at which sensor performance is halved diff --git a/@rfSensor/transmitterGain.m b/@rfSensor/transmitterGain.m index 06e0d68..6317608 100644 --- a/@rfSensor/transmitterGain.m +++ b/@rfSensor/transmitterGain.m @@ -11,8 +11,6 @@ function value = transmitterGain(obj, t, a) error("t and a must be the same size"); end - n = 6; % beamwidth exponent (higher = narrower beam) - % Angular offset from boresight via spherical law of cosines % Convention: t=0° nadir, t=90° horizon; a=0° +y, a=90° +x cos_theta = sind(obj.tilt) .* sind(t) .* cosd(a - obj.azimuth) + ... @@ -21,5 +19,5 @@ function value = transmitterGain(obj, t, a) theta = acosd(cos_theta); % Cardioid family: peak at boresight (theta=0), null opposite (theta=180°) - value = 10 .* n .* log10((1 + cosd(theta)) ./ 2); + value = 10 .* obj.beamwidthExponent .* log10((1 + cosd(theta)) ./ 2); end diff --git a/@sensingObjective/plot.m b/@sensingObjective/plot.m index d7bc074..ee5ed39 100644 --- a/@sensingObjective/plot.m +++ b/@sensingObjective/plot.m @@ -20,7 +20,7 @@ function f = plot(obj, ind, f) hold(f.CurrentAxes, "off"); else hold(f.Children(1).Children(ind(1)), "on"); - o = surf(f.Children(1).Children(ind(1)), obj.X, obj.Y, zeros(size(obj.X)), obj.values ./ max(obj.values, [], "all"), "EdgeColor", "none"); + o = surf(f.Children(1).Children(ind(1)), obj.X, obj.Y, zeros(size(obj.X)), obj.values ./ sum(obj.values, "all"), "EdgeColor", "none"); o.HitTest = "off"; o.PickableParts = "none"; hold(f.Children(1).Children(ind(1)), "off"); diff --git a/test/test_rfSensor.m b/test/test_rfSensor.m index 6323aa3..cad8b2e 100644 --- a/test/test_rfSensor.m +++ b/test/test_rfSensor.m @@ -18,8 +18,10 @@ classdef test_rfSensor < matlab.unittest.TestCase BW = 20e6; % Bandwidth (Hz) f_c = 2e9; % Center frequency (Hz) G_RX_dBi = 3; % Receiving Antenna Gain (dBi) + beamwidthExponent = 6; + lossExponent = 2; - tc.testClass = tc.testClass.initialize(P_TX, BW, f_c, G_RX_dBi, 0, 0); + tc.testClass = tc.testClass.initialize(P_TX, BW, f_c, G_RX_dBi, beamwidthExponent, 0, 0, lossExponent); tc.testClass.plotParameters(); end @@ -29,8 +31,10 @@ classdef test_rfSensor < matlab.unittest.TestCase BW = 20e6; % Bandwidth (Hz) f_c = 2e9; % Center frequency (Hz) G_RX_dBi = 3; % Receiving Antenna Gain (dBi) + beamwidthExponent = 6; + lossExponent = 2; - tc.testClass = tc.testClass.initialize(P_TX, BW, f_c, G_RX_dBi, 30, 135); + tc.testClass = tc.testClass.initialize(P_TX, BW, f_c, G_RX_dBi, beamwidthExponent, 30, 135, lossExponent); altitude = 30; @@ -50,8 +54,10 @@ classdef test_rfSensor < matlab.unittest.TestCase BW = 20e6; % Bandwidth (Hz) f_c = 2e9; % Center frequency (Hz) G_RX_dBi = 3; % Receiving Antenna Gain (dBi) + beamwidthExponent = 6; + lossExponent = 2; - tc.testClass = tc.testClass.initialize(P_TX, BW, f_c, G_RX_dBi, 0, 0); + tc.testClass = tc.testClass.initialize(P_TX, BW, f_c, G_RX_dBi, beamwidthExponent, 0, 0, lossExponent); altitude = 30; otherSensorsPos = [6, -4, -1]; % relative to main sensor @@ -67,8 +73,10 @@ classdef test_rfSensor < matlab.unittest.TestCase BW = 20e6; % Bandwidth (Hz) f_c = 2e9; % Center frequency (Hz) G_RX_dBi = 3; % Receiving Antenna Gain (dBi) + beamwidthExponent = 6; + lossExponent = 2; - tc.testClass = tc.testClass.initialize(P_TX, BW, f_c, G_RX_dBi, 0, 0); + tc.testClass = tc.testClass.initialize(P_TX, BW, f_c, G_RX_dBi, beamwidthExponent, 0, 0, lossExponent); altitude = 30; otherSensorsPos = [6, -4, -1; -2, 6, 0]; % relative to main sensor @@ -77,8 +85,8 @@ classdef test_rfSensor < matlab.unittest.TestCase otherSensors{2} = rfSensor; % Must use same center frequency and bandwidth for interference sources - otherSensors{1} = otherSensors{1}.initialize(10 * P_TX, BW, f_c, G_RX_dBi, 0, 0); - otherSensors{2} = otherSensors{2}.initialize(10 * P_TX, BW, f_c, G_RX_dBi, 0, 0); + otherSensors{1} = otherSensors{1}.initialize(10 * P_TX, BW, f_c, G_RX_dBi, beamwidthExponent, 0, 0, lossExponent); + otherSensors{2} = otherSensors{2}.initialize(10 * P_TX, BW, f_c, G_RX_dBi, beamwidthExponent, 0, 0, lossExponent); tc.testClass.plotPerformance(altitude, otherSensorsPos, otherSensors); end @@ -88,13 +96,15 @@ classdef test_rfSensor < matlab.unittest.TestCase f_c = 2e9; G_RX_dBi = 3; altitude = 30; + beamwidthExponent = [6, 4, 10]; + lossExponent = 2; sensor1 = rfSensor; - sensor1 = sensor1.initialize(P_TX, BW, f_c, G_RX_dBi, 15, 45); + sensor1 = sensor1.initialize(P_TX, BW, f_c, G_RX_dBi, beamwidthExponent(1), 15, 45, lossExponent); sensor2 = rfSensor; - sensor2 = sensor2.initialize(P_TX, BW, f_c, G_RX_dBi, 10, 150); + sensor2 = sensor2.initialize(P_TX, BW, f_c, G_RX_dBi, beamwidthExponent(2), 10, 150, lossExponent); sensor3 = rfSensor; - sensor3 = sensor3.initialize(P_TX, BW, f_c, G_RX_dBi, 20, 200); + sensor3 = sensor3.initialize(P_TX, BW, f_c, G_RX_dBi, beamwidthExponent(3), 20, 200, lossExponent); pos1 = [0, 0, altitude]; pos2 = [6, -4, altitude - 1];