plot radio metrics as a function of distance

This commit is contained in:
2026-05-06 18:12:40 -07:00
parent 7433310390
commit 740b42eba4
2 changed files with 106 additions and 7 deletions
+104 -4
View File
@@ -1,9 +1,12 @@
function [f, R] = plotRadioLogs(resultsPath)
function [f, fDist, R] = plotRadioLogs(resultsPath, G, tLim)
arguments (Input)
resultsPath (1, 1) string;
G cell = {};
tLim (1, 2) datetime = [datetime(-Inf, 'ConvertFrom', 'datenum'), datetime(Inf, 'ConvertFrom', 'datenum')];
end
arguments (Output)
f (1, 1) matlab.ui.Figure;
fDist (1, 1) matlab.ui.Figure;
R cell;
end
@@ -41,6 +44,7 @@ function [f, R] = plotRadioLogs(resultsPath)
metricNames = ["SNR", "Power", "Quality", "PathLoss", "NoiseFloor", "FreqOffset"];
yLabels = ["SNR (dB)", "Power (dB)", "Quality", "Path Loss (dB)", "Noise Floor (dB)", "Freq Offset (MHz)"];
% --- Time-based figure ---
f = figure;
tl = tiledlayout(numel(metricNames), 1, 'TileSpacing', 'compact', 'Padding', 'compact');
@@ -57,10 +61,10 @@ function [f, R] = plotRadioLogs(resultsPath)
for ti = 1:numel(txIDs)
txID = txIDs(ti);
rows = tbl(tbl.TxUAVID == txID, :);
rows = rows(rows.Timestamp >= tLim(1) & rows.Timestamp <= tLim(2), :);
vals = rows.(metricNames(mi));
% Skip if all NaN for this metric
if all(isnan(vals))
if isempty(rows) || all(isnan(vals))
continue;
end
@@ -81,4 +85,100 @@ function [f, R] = plotRadioLogs(resultsPath)
end
title(tl, 'Radio Channel Metrics');
end
% --- Distance-based figure ---
fDist = figure;
if isempty(G)
return;
end
tl2 = tiledlayout(numel(metricNames), 1, 'TileSpacing', 'compact', 'Padding', 'compact');
for mi = 1:numel(metricNames)
ax = nexttile(tl2);
hold(ax, 'on');
grid(ax, 'on');
legendEntries = string.empty;
ci = 1;
for rxIdx = 1:nUAV
tbl = R{rxIdx};
txIDs = unique(tbl.TxUAVID);
for ti = 1:numel(txIDs)
txID = txIDs(ti);
rows = tbl(tbl.TxUAVID == txID, :);
if isempty(rows)
continue;
end
rows = rows(rows.Timestamp >= tLim(1) & rows.Timestamp <= tLim(2), :);
if isempty(rows)
continue;
end
vals = rows.(metricNames(mi));
if all(isnan(vals))
continue;
end
% Map 0-based UAV IDs to 1-based GPS cell indices
txGpsIdx = double(txID) + 1;
rxGpsIdx = double(rows.RxUAVID(1)) + 1;
if txGpsIdx > numel(G) || rxGpsIdx > numel(G)
continue;
end
Gtx = G{txGpsIdx};
Grx = G{rxGpsIdx};
if ~ismember('East', Gtx.Properties.VariableNames) || ...
~ismember('East', Grx.Properties.VariableNames)
continue;
end
% Strip timezone before posixtime so radio and GPS timestamps
% are treated on the same scale (both are AERPAW wall-clock time)
txTs = Gtx.Timestamp; txTs.TimeZone = '';
rxTs = Grx.Timestamp; rxTs.TimeZone = '';
txPt = posixtime(txTs);
rxPt = posixtime(rxTs);
radioPt = posixtime(rows.Timestamp);
% Interpolate GPS positions at radio measurement times.
% Exclude NaN ENU entries (outside algorithm flight range).
validTx = ~isnan(Gtx.East);
validRx = ~isnan(Grx.East);
txE = interp1(txPt(validTx), Gtx.East(validTx), radioPt, 'linear', NaN);
txN = interp1(txPt(validTx), Gtx.North(validTx), radioPt, 'linear', NaN);
txU = interp1(txPt(validTx), Gtx.Up(validTx), radioPt, 'linear', NaN);
rxE = interp1(rxPt(validRx), Grx.East(validRx), radioPt, 'linear', NaN);
rxN = interp1(rxPt(validRx), Grx.North(validRx), radioPt, 'linear', NaN);
rxU = interp1(rxPt(validRx), Grx.Up(validRx), radioPt, 'linear', NaN);
dist = vecnorm([txE - rxE, txN - rxN, txU - rxU], 2, 2);
if all(isnan(dist))
continue;
end
si = mod(ci - 1, numel(styles)) + 1;
scatter(ax, dist, vals, 9, colors(ci, :), strrep(styles(si), "-", ""), 'filled');
legendEntries(end+1) = sprintf("TX %d → RX %d", txID, rows.RxUAVID(1)); %#ok<AGROW>
ci = ci + 1;
end
end
ylabel(ax, yLabels(mi));
if mi == numel(metricNames)
xlabel(ax, 'Distance (m)');
end
legend(ax, legendEntries, 'Location', 'best');
hold(ax, 'off');
end
title(tl2, 'Radio Channel Metrics vs Distance');
end
+2 -3
View File
@@ -26,9 +26,8 @@ seaToGroundLevel = 110; % measured approximately from USGS national map viewer
plotWholeFlight = true; % do not attempt to automatically trim initial and final positioning and landing from flight plot (buggy)
[fGlobe, G] = plotGpsLogs(resultsPath, seaToGroundLevel, true);
% Plot radio statistics
[fRadio, R] = plotRadioLogs(resultsPath);
set(findobj(fRadio, 'Type', 'axes'), 'XLim', controller.timestamp([1, end]));
% Plot radio statistics (time-based and distance-based)
[fRadio, fRadioDist, R] = plotRadioLogs(resultsPath, G, controller.timestamp([1, end]));
%% Run simulation
% Run miSim using same AERPAW scenario definition CSV