made SINR threshold check bidirectional
This commit is contained in:
1 parent
f9aa9cc44d
commit
1d414e2bd4
5 files changed
+63
-28
No files matched your search
+32
-10
@@ -169,11 +169,11 @@ function [obj] = constrainMotion(obj)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
% SINR comms: keep the SINR of each maintained link above threshold via
|
% SINR comms: a link is feasible only if each agent receives the other
|
||||||
% the barrier h = SINR - gammaLin. Per the connectivity convention the
|
% above threshold, so every maintained pair is held with TWO barrier
|
||||||
% lower-index agent (ii) receives the higher-index transmitter (jj). The
|
% rows, h = SINR - gammaCbf, one per receiver direction. Each gradient
|
||||||
% gradient couples the receiver, transmitter, and every interferer, so
|
% couples the receiver, transmitter, and every interferer, so the QP
|
||||||
% the QP row is dense across all agent blocks.
|
% rows are dense across all agent blocks.
|
||||||
% Maintain SINR a margin above the connectivity threshold so that
|
% Maintain SINR a margin above the connectivity threshold so that
|
||||||
% discrete-time overshoot of the (convex) SINR does not transiently
|
% discrete-time overshoot of the (convex) SINR does not transiently
|
||||||
% drop a maintained link below threshold. Mirrors the fixed-radius
|
% drop a maintained link below threshold. Mirrors the fixed-radius
|
||||||
@@ -188,19 +188,33 @@ function [obj] = constrainMotion(obj)
|
|||||||
for ii = 1:(nAgents - 1)
|
for ii = 1:(nAgents - 1)
|
||||||
for jj = (ii + 1):nAgents
|
for jj = (ii + 1):nAgents
|
||||||
if obj.constraintAdjacencyMatrix(ii, jj)
|
if obj.constraintAdjacencyMatrix(ii, jj)
|
||||||
[sinr, grad] = obj.sinrLink(lastPositions, ii, jj); % receiver ii, transmitter jj
|
% Direction 1: lower-index agent (ii) receives higher (jj).
|
||||||
hComms(ii, jj) = sinr - gammaCbf;
|
% Upper triangle of hComms stores this direction's barrier.
|
||||||
|
[sinr1, grad1] = obj.sinrLink(lastPositions, ii, jj);
|
||||||
|
hComms(ii, jj) = sinr1 - gammaCbf;
|
||||||
% CBF row: A = -grad(h), b = h/dt (one-step forward invariance)
|
% CBF row: A = -grad(h), b = h/dt (one-step forward invariance)
|
||||||
for aa = 1:nAgents
|
for aa = 1:nAgents
|
||||||
A(kk, (3 * aa - 2):(3 * aa)) = -grad(aa, :);
|
A(kk, (3 * aa - 2):(3 * aa)) = -grad1(aa, :);
|
||||||
end
|
end
|
||||||
if norm(A(kk, :)) < 1e-9
|
if norm(A(kk, :)) < 1e-9
|
||||||
b(kk) = 0;
|
b(kk) = 0;
|
||||||
else
|
else
|
||||||
b(kk) = hComms(ii, jj) / obj.timestep;
|
b(kk) = hComms(ii, jj) / obj.timestep;
|
||||||
end
|
end
|
||||||
|
kk = kk + 1;
|
||||||
|
|
||||||
|
% Direction 2: higher-index agent (jj) receives lower (ii).
|
||||||
|
% Lower triangle of hComms stores this direction's barrier.
|
||||||
|
[sinr2, grad2] = obj.sinrLink(lastPositions, jj, ii);
|
||||||
|
hComms(jj, ii) = sinr2 - gammaCbf;
|
||||||
|
for aa = 1:nAgents
|
||||||
|
A(kk, (3 * aa - 2):(3 * aa)) = -grad2(aa, :);
|
||||||
|
end
|
||||||
|
if norm(A(kk, :)) < 1e-9
|
||||||
|
b(kk) = 0;
|
||||||
|
else
|
||||||
|
b(kk) = hComms(jj, ii) / obj.timestep;
|
||||||
|
end
|
||||||
kk = kk + 1;
|
kk = kk + 1;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -208,7 +222,15 @@ function [obj] = constrainMotion(obj)
|
|||||||
end
|
end
|
||||||
|
|
||||||
if coder.target('MATLAB')
|
if coder.target('MATLAB')
|
||||||
obj.barriers(idx:(idx + length(hComms(triu(true(size(hComms)), 1))) - 1), obj.timestepIndex) = hComms(triu(true(size(hComms)), 1));
|
if obj.useSinrComms
|
||||||
|
% Both directions are maintained: log the upper triangle
|
||||||
|
% (lower-index receiver) then the lower triangle (higher-index
|
||||||
|
% receiver), matching the doubled comms-barrier allocation.
|
||||||
|
commsLog = [hComms(triu(true(size(hComms)), 1)); hComms(tril(true(size(hComms)), -1))];
|
||||||
|
else
|
||||||
|
commsLog = hComms(triu(true(size(hComms)), 1));
|
||||||
|
end
|
||||||
|
obj.barriers(idx:(idx + numel(commsLog) - 1), obj.timestepIndex) = commsLog;
|
||||||
end
|
end
|
||||||
|
|
||||||
% Double-integrator: transform QP from velocity to acceleration space.
|
% Double-integrator: transform QP from velocity to acceleration space.
|
||||||
|
|||||||
+6
-1
@@ -143,8 +143,13 @@ function [obj] = initialize(obj, domain, agents, barrierGain, barrierExponent, m
|
|||||||
% Comms barriers: size to the upper bound (full mesh) rather than the initial
|
% Comms barriers: size to the upper bound (full mesh) rather than the initial
|
||||||
% constraint-adjacency count. Connectivity is dynamic (lesser-neighbor and,
|
% constraint-adjacency count. Connectivity is dynamic (lesser-neighbor and,
|
||||||
% especially, SINR) and can later maintain more pairs than at init; sizing to
|
% especially, SINR) and can later maintain more pairs than at init; sizing to
|
||||||
% nAAPairs prevents the QP A/b matrices from overflowing mid-run.
|
% nAAPairs prevents the QP A/b matrices from overflowing mid-run. SINR mode
|
||||||
|
% enforces both directions per link, so it needs two barrier rows per pair.
|
||||||
|
if obj.useSinrComms
|
||||||
|
nLNAPairs = 2 * nAAPairs;
|
||||||
|
else
|
||||||
nLNAPairs = nAAPairs;
|
nLNAPairs = nAAPairs;
|
||||||
|
end
|
||||||
obj.numBarriers = nAAPairs + nAOPairs + nADPairs + nLNAPairs;
|
obj.numBarriers = nAAPairs + nAOPairs + nADPairs + nLNAPairs;
|
||||||
|
|
||||||
if coder.target('MATLAB')
|
if coder.target('MATLAB')
|
||||||
|
|||||||
+11
-7
@@ -36,15 +36,19 @@ function obj = plotGraph(obj)
|
|||||||
for kk = 1:nAgents
|
for kk = 1:nAgents
|
||||||
positions(kk, :) = obj.agents{kk}.pos;
|
positions(kk, :) = obj.agents{kk}.pos;
|
||||||
end
|
end
|
||||||
% Directional convention (matches updateAdjacency/constrainMotion):
|
% A link is feasible only if BOTH directions clear the threshold, so
|
||||||
% the lower-index node is the receiver, the higher-index node the
|
% label each edge with the binding (worse) directional SINR: the min of
|
||||||
% transmitter, with interference from all other agents at the receiver.
|
% the lower-index-receiver and higher-index-receiver links, with
|
||||||
% Labels are bare numbers (no units) so they stay compact; GraphPlot
|
% interference from all other agents at each receiver. Labels are bare
|
||||||
% renders them horizontally, left-to-right.
|
% numbers (no units) so they stay compact; GraphPlot renders them
|
||||||
|
% horizontally, left-to-right.
|
||||||
edgeLabels = strings(size(endNodes, 1), 1);
|
edgeLabels = strings(size(endNodes, 1), 1);
|
||||||
for ee = 1:size(endNodes, 1)
|
for ee = 1:size(endNodes, 1)
|
||||||
sinrLin = obj.sinrLink(positions, endNodes(ee, 1), endNodes(ee, 2));
|
lo = endNodes(ee, 1);
|
||||||
edgeLabels(ee) = sprintf("%.1f", 10 * log10(sinrLin));
|
hi = endNodes(ee, 2);
|
||||||
|
sinrLoRx = obj.sinrLink(positions, lo, hi); % receiver lo (lower index)
|
||||||
|
sinrHiRx = obj.sinrLink(positions, hi, lo); % receiver hi (higher index)
|
||||||
|
edgeLabels(ee) = sprintf("%.1f", 10 * log10(min(sinrLoRx, sinrHiRx)));
|
||||||
end
|
end
|
||||||
o(1).EdgeLabel = edgeLabels;
|
o(1).EdgeLabel = edgeLabels;
|
||||||
% Threshold goes in the existing single-line title (not a subtitle) so
|
% Threshold goes in the existing single-line title (not a subtitle) so
|
||||||
|
|||||||
@@ -23,9 +23,11 @@ function obj = updateAdjacency(obj)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
% SINR model: pair (ii, jj) connected iff the lower-index agent (jj)
|
% SINR model: a link between a pair is feasible only if BOTH directional
|
||||||
% receives the higher-index agent's (ii) signal above the SINR
|
% SINRs clear the threshold, i.e. each agent receives the other's signal
|
||||||
% threshold, with interference from all other agents at the receiver.
|
% above gammaLin (with interference from all other agents at the
|
||||||
|
% receiver). Every ordered pair (permutation) is evaluated; a single
|
||||||
|
% failing direction eliminates the undirected link.
|
||||||
gammaLin = 10^(obj.sinrThreshold / 10); % dB threshold -> linear
|
gammaLin = 10^(obj.sinrThreshold / 10); % dB threshold -> linear
|
||||||
positions = zeros(nAgents, 3);
|
positions = zeros(nAgents, 3);
|
||||||
for kk = 1:nAgents
|
for kk = 1:nAgents
|
||||||
@@ -33,9 +35,10 @@ function obj = updateAdjacency(obj)
|
|||||||
end
|
end
|
||||||
for ii = 2:nAgents
|
for ii = 2:nAgents
|
||||||
for jj = 1:(ii - 1)
|
for jj = 1:(ii - 1)
|
||||||
sinr = obj.sinrLink(positions, jj, ii); % receiver jj, transmitter ii
|
sinrLoRx = obj.sinrLink(positions, jj, ii); % receiver jj (lower), transmitter ii
|
||||||
if sinr < gammaLin
|
sinrHiRx = obj.sinrLink(positions, ii, jj); % receiver ii (higher), transmitter jj
|
||||||
A(ii, jj) = false; % SINR below threshold
|
if sinrLoRx < gammaLin || sinrHiRx < gammaLin
|
||||||
|
A(ii, jj) = false; % at least one direction below threshold
|
||||||
continue;
|
continue;
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
+5
-4
@@ -857,18 +857,19 @@ classdef test_miSim < matlab.unittest.TestCase
|
|||||||
% fixed-radius variant of this test (so the two agents still cannot
|
% fixed-radius variant of this test (so the two agents still cannot
|
||||||
% reach their objectives without breaking connectivity).
|
% reach their objectives without breaking connectivity).
|
||||||
useSinrComms = true;
|
useSinrComms = true;
|
||||||
txPower = 0.1; % transmit power per agent (W)
|
txPower = [0.01, 0.01]; % transmit power per agent (W)
|
||||||
pathLossExponent = 2.0;
|
pathLossExponent = 2.0;
|
||||||
ambientTemp = 290; % K
|
ambientTemp = 290; % K
|
||||||
centerFreq = 2.4e9; % Hz
|
centerFreq = 2.4e9; % Hz
|
||||||
bandwidth = 20e6; % Hz
|
bandwidth = 20e6; % Hz
|
||||||
|
|
||||||
effRange = 4.0; % desired effective comms range (m)
|
effRange = 4.0; % desired effective comms range (m)
|
||||||
K_pl = (4 * pi * centerFreq / 3e8)^2; % free-space path-loss reference
|
K_pl = (4 * pi * centerFreq / 3e8)^2; % free-space path-loss reference
|
||||||
noiseW = 1.380649e-23 * ambientTemp * bandwidth; % thermal noise (W)
|
noiseW = 1.380649e-23 * ambientTemp * bandwidth; % thermal noise (W)
|
||||||
sinrThreshold = 10 * log10(txPower / (K_pl * effRange^pathLossExponent * noiseW)); % dB
|
sinrThreshold = 10 * log10(mean(txPower) / (K_pl * effRange^pathLossExponent * noiseW)); % dB
|
||||||
|
|
||||||
tc.agents{1}.txPower = txPower;
|
tc.agents{1}.txPower = txPower(1);
|
||||||
tc.agents{2}.txPower = txPower;
|
tc.agents{2}.txPower = txPower(2);
|
||||||
|
|
||||||
% Initialize the simulation in SINR comms mode
|
% Initialize the simulation in SINR comms mode
|
||||||
tc.testClass = tc.testClass.initialize(tc.domain, tc.agents, tc.barrierGain, tc.barrierExponent, tc.minAlt, tc.timestep, tc.maxIter, tc.obstacles, tc.makePlots, tc.makeVideo, tc.useDoubleIntegrator, tc.dampingCoeff, tc.useFixedTopology, tc.optimizeSensorPointing, useSinrComms, sinrThreshold, pathLossExponent, ambientTemp, centerFreq, bandwidth);
|
tc.testClass = tc.testClass.initialize(tc.domain, tc.agents, tc.barrierGain, tc.barrierExponent, tc.minAlt, tc.timestep, tc.maxIter, tc.obstacles, tc.makePlots, tc.makeVideo, tc.useDoubleIntegrator, tc.dampingCoeff, tc.useFixedTopology, tc.optimizeSensorPointing, useSinrComms, sinrThreshold, pathLossExponent, ambientTemp, centerFreq, bandwidth);
|
||||||
|
|||||||
Reference in new issue
Block a user