rf sensor model cleanup

This commit is contained in:
kdee committed 2026-05-29 19:38:51 -07:00
1 parent 8e8bb39cd9
commit 2f9f13fdc8
8 files changed
+43 -45

No files matched your search

+1 -2
View File
@@ -19,6 +19,5 @@ function value = RSS(obj, d, dx, dy, dz)
cos_theta = (st .* (dx .* sa + dy .* ca) - ct .* dz) ./ max(d, eps);
cos_theta = max(-1, min(1, cos_theta));
theta = acosd(cos_theta);
gain = 10 .* obj.beamwidthExponent .* log10((1 + cosd(theta)) ./ 2);
value = obj.P_TX_dBm + gain + obj.G_RX_dBi - obj.pathLoss(d);
value = obj.P_TX_dBm + obj.transmitterGain(theta) + obj.G_RX_dBi - obj.pathLoss(d);
end
+1 -5
View File
@@ -5,12 +5,8 @@ function value = halfAngle(obj)
arguments (Output)
value (1, 1) double;
end
% Sweep angular offset from boresight by evaluating transmitterGain at
% (obj.tilt + dtheta, obj.azimuth). The cosine difference identity guarantees
% the resulting angular offset from boresight equals dtheta exactly,
% independent of the actual pointing direction.
dtheta = (0:0.1:179.9)';
gain = obj.transmitterGain(obj.tilt + dtheta, obj.azimuth * ones(size(dtheta)));
gain = obj.transmitterGain(dtheta);
target = gain(1) - 3;
idx = find(gain <= target, 1);
if isempty(idx) || idx == 1
+4 -1
View File
@@ -1,7 +1,8 @@
function obj = initialize(obj, txPower, bandwidth, centerFreq, rxGain_dBi, beamwidthExponent, tilt, azimuth, lossExponent)
function obj = initialize(obj, txPower, temperature, bandwidth, centerFreq, rxGain_dBi, beamwidthExponent, tilt, azimuth, lossExponent)
arguments (Input)
obj (1, 1) {mustBeA(obj, "rfSensor")}
txPower (1, 1) double;
temperature (1, 1) double;
bandwidth (1, 1) double;
centerFreq (1, 1) double;
rxGain_dBi (1, 1) double;
@@ -16,6 +17,7 @@ function obj = initialize(obj, txPower, bandwidth, centerFreq, rxGain_dBi, beamw
%% Provided values
obj.P_TX = txPower; % Transmit power (W)
obj.T_0 = temperature; % Temperature (K)
obj.BW = bandwidth; % Bandwidth (Hz)
obj.f_c = centerFreq; % Center frequency (Hz)
obj.G_RX_dBi = rxGain_dBi; % Receiving Antenna Gain (dBi)
@@ -29,4 +31,5 @@ function obj = initialize(obj, txPower, bandwidth, centerFreq, rxGain_dBi, beamw
%% 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
obj.constantGainTerm_dB = 10 .* log10(2 * (obj.beamwidthExponent + 1)); % used in RSS calculation, only need to compute once
end
+5 -2
View File
@@ -23,8 +23,11 @@ function f = plotParameters(obj)
% For agent at altitude alt, ground target at tilt T has slant distance:
D = alt ./ cosd(T);
% Compute RSS for each (d, t, a) triple
rss = obj.RSS(D(:), T(:), A(:));
% Convert LOS (D, T, A) to displacement vectors for RSS
dx = D .* sind(T) .* sind(A);
dy = D .* sind(T) .* cosd(A);
dz = -D .* cosd(T); % negative: ground targets are below agent
rss = obj.RSS(D(:), dx(:), dy(:), dz(:));
Fslice = reshape(rss, size(D));
% Disc geometry: t=0 (nadir) -> center, t~90 (horizon) -> edge
+3 -2
View File
@@ -14,6 +14,7 @@ classdef rfSensor
% Values computed at initialization
P_TX_dBm = NaN; % Transmit power (dBm)
N = NaN; % Thermal noise
constantGainTerm_dB = NaN; % used in RSS calculation, only need to compute once
% Cached state (per timestep)
end
properties (Access = public)
@@ -23,7 +24,7 @@ classdef rfSensor
end
methods (Access = public)
[obj] = initialize(obj, txPower, bandwidth, centerFreq, rxGain, beamwidthExponent, tilt, azimuth); % initialize sensor, define parameters
[obj] = initialize(obj, txPower, temperature, 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, dx, dy, dz] = computePointToPoints(obj, agentPos, targetPos);
[value] = halfAngle(obj); % tilt angle (deg) at which sensor performance is halved
@@ -34,7 +35,7 @@ classdef rfSensor
end
methods (Access = private)
x = RSS(obj, d, dx, dy, dz); % Received signal strength (function of distance and tilt angle)
G_TX_dB = transmitterGain(obj, t, a); % Antenna gain for a given TX/RX pair
G_TX_dB = transmitterGain(obj, theta); % Antenna gain for a given angle from boresight (degrees)
L_FSPL_dB = pathLoss(obj, d); % Free space path loss for a given TX/RX pair
end
end
+6 -17
View File
@@ -1,23 +1,12 @@
function value = transmitterGain(obj, t, a)
function value = transmitterGain(obj, theta)
arguments (Input)
obj (1, 1) {mustBeA(obj, "rfSensor")};
t (:, 1) double; % LOS tilt angle
a (:, 1) double; % LOS azimuth angle
obj (1, 1) {mustBeA(obj, "rfSensor")};
theta (:, 1) double; % angle from boresight (degrees)
end
arguments (Output)
value (:, 1) double
end
if ~isequal(size(t), size(a))
error("t and a must be the same size");
end
% 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) + ...
cosd(obj.tilt) .* cosd(t);
cos_theta = max(-1, min(1, cos_theta)); % clamp for numerical safety
theta = acosd(cos_theta);
% Cardioid family: peak at boresight (theta=0), null opposite (theta=180°)
value = 10 .* obj.beamwidthExponent .* log10((1 + cosd(theta)) ./ 2);
% Cosine pattern: peak at boresight, -inf dB at 90°.
% Clamped so targets behind the antenna (theta > 90°) get -inf rather than NaN.
value = obj.constantGainTerm_dB + 10 .* obj.beamwidthExponent .* log10(max(0, cosd(theta)));
end