From d07df25528358f29ced9e06725f42949f609e9d3 Mon Sep 17 00:00:00 2001 From: Kevin D Date: Sun, 26 Apr 2026 10:28:28 -0700 Subject: [PATCH] RF antenna azimuth, plotting improvements --- @rfSensor/RSS.m | 7 ++- @rfSensor/antennaGain.m | 17 ------ @rfSensor/computePointToPoints.m | 7 ++- @rfSensor/initialize.m | 4 +- @rfSensor/plotParameters.m | 57 ++++++++++++------- @rfSensor/rfSensor.m | 13 +++-- @rfSensor/sensorPerformance.m | 23 ++++---- @rfSensor/transmitterGain.m | 16 ++++++ @sigmoidSensor/sigmoidSensor.m | 2 +- .../0TUOPB3gylGuEK1Q5NsFsa57FBQp.xml | 2 - ...d.xml => Y0nVGErZr2RP2C5DDHiHUMtLRnod.xml} | 0 .../Y0nVGErZr2RP2C5DDHiHUMtLRnop.xml | 2 + test/test_rfSensor.m | 3 +- 13 files changed, 88 insertions(+), 65 deletions(-) delete mode 100644 @rfSensor/antennaGain.m create mode 100644 @rfSensor/transmitterGain.m delete mode 100644 resources/project/MoO8eFA7MNcwhsnIRzm_IDZfmpg/0TUOPB3gylGuEK1Q5NsFsa57FBQp.xml rename resources/project/MoO8eFA7MNcwhsnIRzm_IDZfmpg/{0TUOPB3gylGuEK1Q5NsFsa57FBQd.xml => Y0nVGErZr2RP2C5DDHiHUMtLRnod.xml} (100%) create mode 100644 resources/project/MoO8eFA7MNcwhsnIRzm_IDZfmpg/Y0nVGErZr2RP2C5DDHiHUMtLRnop.xml diff --git a/@rfSensor/RSS.m b/@rfSensor/RSS.m index 605e287..c512a56 100644 --- a/@rfSensor/RSS.m +++ b/@rfSensor/RSS.m @@ -1,14 +1,15 @@ -function value = RSS(obj, d, t) +function value = RSS(obj, d, t, a) arguments (Input) obj (1, 1) {mustBeA(obj, "rfSensor")}; d (:, 1) double; % distance from agent to target t (:, 1) double; % LOS tilt angle + a (:, 1) double; % LOS azimuth angle end arguments (Output) value (:, 1) double 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) + Antenna Gain (dB) - Path Loss (dB) - value = obj.P_TX_dBm + obj.antennaGain(t) - obj.pathLoss(d); + % RSS (dBm) = TX Power (dBm) + TX Antenna Gain (dB) + 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/antennaGain.m b/@rfSensor/antennaGain.m deleted file mode 100644 index b34dfb3..0000000 --- a/@rfSensor/antennaGain.m +++ /dev/null @@ -1,17 +0,0 @@ -function value = antennaGain(obj, t) - arguments (Input) - obj (1, 1) {mustBeA(obj, "rfSensor")}; - t (:, 1) double; % LOS tilt angle - end - arguments (Output) - value (:, 1) double - end - - %% TODO - - % Temporary logic to make nadir-pointing most effective - value = 10*log10(cosd(t) .^ 8); - - % % Temporary logic for 0 dB at all tilt angles - % value = zeros(size(t)); -end diff --git a/@rfSensor/computePointToPoints.m b/@rfSensor/computePointToPoints.m index 1a4e46e..fcf36ca 100644 --- a/@rfSensor/computePointToPoints.m +++ b/@rfSensor/computePointToPoints.m @@ -1,4 +1,4 @@ -function [d, t] = computePointToPoints(obj, agentPos, targetPos) +function [d, t, a] = computePointToPoints(obj, agentPos, targetPos) arguments (Input) obj (1, 1) {mustBeA(obj, "rfSensor")}; agentPos (1, 3) double; @@ -7,6 +7,7 @@ function [d, t] = computePointToPoints(obj, agentPos, targetPos) arguments (Output) d (:, 1) double; t (:, 1) double; + a (:, 1) double; end % distance from sensor to target @@ -15,7 +16,9 @@ function [d, t] = computePointToPoints(obj, agentPos, targetPos) % distance from sensor nadir to target nadir (i.e. distance ignoring altitude) x = vecnorm(agentPos(1:2) - targetPos(:, 1:2), 2, 2); - % tilt angle (degrees) + % tilt angle (degrees) (-90, 0 (down), 90) t = (180 - atan2d(x, targetPos(:, 3) - agentPos(3))); + % azimuth angle (degrees) (0 (+y) clockwise to 360) + a = mod(atan2d(targetPos(:,1) - agentPos(1), targetPos(:,2) - agentPos(2)), 360); end \ No newline at end of file diff --git a/@rfSensor/initialize.m b/@rfSensor/initialize.m index be8dda6..9dfb966 100644 --- a/@rfSensor/initialize.m +++ b/@rfSensor/initialize.m @@ -1,9 +1,10 @@ -function obj = initialize(obj, txPower, bandwidth, centerFreq) +function obj = initialize(obj, txPower, bandwidth, centerFreq, rxGain_dBi) 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; end arguments (Output) obj (1, 1) {mustBeA(obj, "rfSensor")} @@ -13,6 +14,7 @@ function obj = initialize(obj, txPower, bandwidth, centerFreq) 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) % Computed values obj.P_TX_dBm = 10*log10(obj.P_TX/1e-3); % Transmit power in dBm diff --git a/@rfSensor/plotParameters.m b/@rfSensor/plotParameters.m index 579589c..e4c5778 100644 --- a/@rfSensor/plotParameters.m +++ b/@rfSensor/plotParameters.m @@ -7,32 +7,49 @@ function f = plotParameters(obj) end % Distance and tilt sample points - d_values = [0.01, 0.1, 0.25, 0.5, 0.75, 1, 2, 3, 4, 5:5:100]; - % t = zeros(size(d)); - t_values = -90:15:90; + d_values = [0.1, 0.5, 1:1:9, 10:2:19, 20:5:49, 50:10:100]; + t_values = -90:0.5:90; + a_values = 0:0.5:360; % Make grid of values of distances and tilts - [d_mg, t_mg] = meshgrid(d_values, t_values); - d = d_mg(:); t = t_mg(:); % flatten + [d_mg, t_mg, a_mg] = meshgrid(d_values, t_values, a_values); + d = d_mg(:); t = t_mg(:); a = a_mg(:); % flatten - % Sample SINR (SNR) function by distances, tilts - % using SINR method with no other transmitters defined is equivalent to SNR - s_x = obj.sensorPerformance(d, t); % don't define other sensors + % Sample received signal strength (no interference or noise) + s_x = obj.RSS(d, t, a); s_x = reshape(s_x, size(d_mg)); - % Plot resultant sigmoid curves + [T, A] = meshgrid(t_values, a_values); % Naz x Nel + Tr = deg2rad(T); + Ar = deg2rad(A); + figure; - plot(d_values.', s_x(repmat((t_values == 0).', 1, size(d_values, 2))), "LineWidth", 2); - grid("on"); - title("SNR vs Distance at 0 tilt"); - xlabel("Distance (m)"); - ylabel("SNR (dB)"); + hold("on"); - figure; - surf(d_mg, t_mg, s_x); + for ii = 1:numel(d_values) + % geometry (your "tilt from nadir, stack by distance") + X = d_values(ii) * cos(Ar) .* sin(Tr); + Y = d_values(ii) * sin(Ar) .* sin(Tr); + Z = d_values(ii) * ones(size(X)); + + % evaluate or extract this slice + Fslice = squeeze(s_x(:, ii, :))'; + + % plot as its own surface + h = surf(X, Y, Z, Fslice); + h.EdgeColor = 'none'; + h.FaceColor = 'interp'; + h.FaceAlpha = 0.25; + end + + colormap(turbo); + colorbar; + daspect([1 1 0.2]) % Separate Z further for more distinct layers + xlabel('X'); ylabel('Y'); zlabel('Distance (m)'); + set(gca,'ZDir','reverse'); + view(3); + axis("vis3d"); grid("on"); - title("SNR vs Distance and Tilt"); - xlabel("Distance (m)"); - ylabel("Tilt (deg)"); - zlabel("SNR (dB)"); + scatter3(0, 0, 0, 'rx'); + hold("off"); end \ No newline at end of file diff --git a/@rfSensor/rfSensor.m b/@rfSensor/rfSensor.m index 9d56285..14381e2 100644 --- a/@rfSensor/rfSensor.m +++ b/@rfSensor/rfSensor.m @@ -8,20 +8,21 @@ classdef rfSensor P_TX = NaN; % Transmit power (Watts) BW = NaN; % Bandwidth (Hz) f_c = NaN; % Center frequency (Hz) + G_RX_dBi = NaN; % Receiver antenna gain % Values computed at initialization P_TX_dBm = NaN; % Transmit power (dBm) N = NaN; % Thermal noise end methods (Access = public) - [obj] = initialize(obj, txPower, bandwidth, centerFreq); % TODO initialize sensor, define parameters - [SINR] = sensorPerformance(obj, agentPos, agentPan, agentTilt, targetPos); % determine sensor performance for a given single sensor and target geometry + [obj] = initialize(obj, txPower, bandwidth, centerFreq, rxGain); % initialize sensor, define parameters + [SINR] = sensorPerformance(obj, agentPos, targetPos, otherSensorsPos, otherSensors); % determine sensor performance for a given single sensor and target geometry [f] = plotParameters(obj); % debug, plot sensor response as a function of distance and tilt angle - [d, t] = computePointToPoints(obj, agentPos, targetPos); + [d, t, a] = computePointToPoints(obj, agentPos, targetPos); end methods (Access = private) - x = RSS(obj, d, t); % Received signal strength (function of distance and tilt angle) - G_TX_dB = antennaGain(obj, agentPos, targetPos); % TODO Antenna gain for a given TX/RX pair - L_FSPL_dB = pathLoss(obj, agentPos, targetPos); % Free space path loss for a given TX/RX pair + x = RSS(obj, d, t, a); % Received signal strength (function of distance and tilt angle) + G_TX_dB = transmitterGain(obj, t, a); % TODO Antenna gain for a given TX/RX pair + L_FSPL_dB = pathLoss(obj, d); % Free space path loss for a given TX/RX pair end end \ No newline at end of file diff --git a/@rfSensor/sensorPerformance.m b/@rfSensor/sensorPerformance.m index be6d329..9e35fff 100644 --- a/@rfSensor/sensorPerformance.m +++ b/@rfSensor/sensorPerformance.m @@ -1,25 +1,24 @@ -function SINR = sensorPerformance(obj, d, t, d_other, t_other, otherSensors) +function SINR = sensorPerformance(obj, agentPos, targetPos, otherSensorsPos, otherSensors) arguments (Input) obj (1, 1) {mustBeA(obj, "rfSensor")}; - d (:, 1) double; - t(:, 1) double; - d_other (:, :) double = []; - t_other (:, :) double = []; - otherSensors (1, :) cell = {}; + agentPos (1, 3) double; + targetPos (:, 3) double; + otherSensorsPos (:, 3) double = []; + otherSensors (:, 1) cell = {}; end arguments (Output) SINR (:, 1) double; end - assert(size(d, 1) == size(t, 1), "Mismatch in number of distance (%d) and angle (%d) pairs provided", size(d, 1), size(t, 1)); - assert(size(d_other, 1) == size(t_other, 1), "Mismatch in number of distances (%d) and tilts (%d) provided to other sensors", size(t, 1), size(t_other, 1)); - assert(size(d_other, 2) == size(t_other, 2), "Mismatch in number of other sensors given distances (%d) and tilts (%d)", size(d_other, 1), size(t_other, 1)); - assert(size(otherSensors, 2) == size(d_other, 2), "Mismatch in number of distances from other sensors (%d) and number of other sensors (%d) provided", size(d_other, 2), size(otherSensors, 2)); + assert(size(otherSensorsPos, 1) == size(otherSensors, 1), "Mismatch in number of other sensor positions (%d) and number of other sensors (%d) provided", size(otherSensorsPos, 1), size(otherSensors, 1)); + + [d, t, a] = obj.computePointToPoints(agentPos, targetPos); % Performance is measured as SINR for this sensor - S = 10 .^ (0.1 * obj.RSS(d, t)); % Signal + S = 10 .^ (0.1 .* obj.RSS(d, t, a)); % Signal I = zeros(size(d)); % Interference from other agents for ii = 1:size(otherSensors, 2) - I = I + 10 .^ (0.1 * otherSensors{ii}.RSS(d_other(:, ii), t_other(:, ii))); + [d_other, t_other, a_other] = otherSensors{ii}.computePointToPoints(otherSensorsPos(ii, 1:3), targetPos); + I = I + 10 .^ (0.1 .* otherSensors{ii}.RSS(d_other, t_other, a_other)); end SINR = 10*log10(S ./ (I + obj.N)); diff --git a/@rfSensor/transmitterGain.m b/@rfSensor/transmitterGain.m new file mode 100644 index 0000000..2b7a0c6 --- /dev/null +++ b/@rfSensor/transmitterGain.m @@ -0,0 +1,16 @@ +function value = transmitterGain(obj, t, a) + arguments (Input) + obj (1, 1) {mustBeA(obj, "rfSensor")}; + t (:, 1) double; % LOS tilt angle + a (:, 1) double; % LOS azimuth angle + end + arguments (Output) + value (:, 1) double + end + if ~isequal(size(t), size(a)) + error("t and a must be the same size"); + end + + % Temporary logic to make nadir-pointing most effective + value = 10 .* log10(cosd(t) .^ 2) + 10 .* log10((0.5 + 0.5 .* cosd(a)) .^ 4); +end diff --git a/@sigmoidSensor/sigmoidSensor.m b/@sigmoidSensor/sigmoidSensor.m index e25bd79..958e9f2 100644 --- a/@sigmoidSensor/sigmoidSensor.m +++ b/@sigmoidSensor/sigmoidSensor.m @@ -9,7 +9,7 @@ classdef sigmoidSensor methods (Access = public) [obj] = initialize(obj, alphaDist, betaDist, alphaTilt, betaTilt); % initialize sensor, define parameters - [value] = sensorPerformance(obj, agentPos, agentPan, agentTilt, targetPos); % determine sensor performance for a given single sensor and target geometry + [value] = sensorPerformance(obj, agentPos, targetPos); % determine sensor performance for a given single sensor and target geometry [f] = plotParameters(obj); % debug, plot sensor response as a function of distance and tilt angle end methods (Access = private) diff --git a/resources/project/MoO8eFA7MNcwhsnIRzm_IDZfmpg/0TUOPB3gylGuEK1Q5NsFsa57FBQp.xml b/resources/project/MoO8eFA7MNcwhsnIRzm_IDZfmpg/0TUOPB3gylGuEK1Q5NsFsa57FBQp.xml deleted file mode 100644 index 4401f9c..0000000 --- a/resources/project/MoO8eFA7MNcwhsnIRzm_IDZfmpg/0TUOPB3gylGuEK1Q5NsFsa57FBQp.xml +++ /dev/null @@ -1,2 +0,0 @@ - - \ No newline at end of file diff --git a/resources/project/MoO8eFA7MNcwhsnIRzm_IDZfmpg/0TUOPB3gylGuEK1Q5NsFsa57FBQd.xml b/resources/project/MoO8eFA7MNcwhsnIRzm_IDZfmpg/Y0nVGErZr2RP2C5DDHiHUMtLRnod.xml similarity index 100% rename from resources/project/MoO8eFA7MNcwhsnIRzm_IDZfmpg/0TUOPB3gylGuEK1Q5NsFsa57FBQd.xml rename to resources/project/MoO8eFA7MNcwhsnIRzm_IDZfmpg/Y0nVGErZr2RP2C5DDHiHUMtLRnod.xml diff --git a/resources/project/MoO8eFA7MNcwhsnIRzm_IDZfmpg/Y0nVGErZr2RP2C5DDHiHUMtLRnop.xml b/resources/project/MoO8eFA7MNcwhsnIRzm_IDZfmpg/Y0nVGErZr2RP2C5DDHiHUMtLRnop.xml new file mode 100644 index 0000000..d3618f2 --- /dev/null +++ b/resources/project/MoO8eFA7MNcwhsnIRzm_IDZfmpg/Y0nVGErZr2RP2C5DDHiHUMtLRnop.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/test/test_rfSensor.m b/test/test_rfSensor.m index 1819401..2cafc6f 100644 --- a/test/test_rfSensor.m +++ b/test/test_rfSensor.m @@ -17,8 +17,9 @@ classdef test_rfSensor < matlab.unittest.TestCase P_TX = 1e-3; % Transmit power (Watts) BW = 20e6; % Bandwidth (Hz) f_c = 2e9; % Center frequency (Hz) + G_RX_dBi = 3; % Receiving Antenna Gain (dBi) - tc.testClass = tc.testClass.initialize(P_TX, BW, f_c); + tc.testClass = tc.testClass.initialize(P_TX, BW, f_c, G_RX_dBi); tc.testClass.plotParameters(); end