Compare commits
8 Commits
main
...
f23675a54c
| Author | SHA1 | Date | |
|---|---|---|---|
| f23675a54c | |||
| 8c3b853895 | |||
| e77b05bc0f | |||
| 6b74347411 | |||
| a3837a6ef4 | |||
| 01f2af9102 | |||
| 0d02e5d1f5 | |||
| 2a0e2e500f |
@@ -36,4 +36,4 @@ function obj = initialize(obj, pos, collisionGeometry, sensorModel, comRange, ma
|
|||||||
% Initialize FOV cone
|
% Initialize FOV cone
|
||||||
obj.fovGeometry = cone;
|
obj.fovGeometry = cone;
|
||||||
obj.fovGeometry = obj.fovGeometry.initialize([obj.pos(1:3)], tand(obj.sensorModel.alphaTilt) * obj.pos(3), obj.pos(3), REGION_TYPE.FOV, sprintf("%s FOV", obj.label));
|
obj.fovGeometry = obj.fovGeometry.initialize([obj.pos(1:3)], tand(obj.sensorModel.alphaTilt) * obj.pos(3), obj.pos(3), REGION_TYPE.FOV, sprintf("%s FOV", obj.label));
|
||||||
end
|
end
|
||||||
@@ -138,12 +138,6 @@ function [obj] = initialize(obj, domain, agents, barrierGain, barrierExponent, m
|
|||||||
% Initialize variable that will store barrier function values per timestep for analysis purposes
|
% Initialize variable that will store barrier function values per timestep for analysis purposes
|
||||||
obj.barriers = NaN(obj.numBarriers, size(obj.times, 1));
|
obj.barriers = NaN(obj.numBarriers, size(obj.times, 1));
|
||||||
|
|
||||||
% Initialize constraint adjacency history (nAgents x nAgents x nTimesteps)
|
|
||||||
nAgents = size(obj.agents, 1);
|
|
||||||
obj.constraintAdjacencyHist = false(nAgents, nAgents, size(obj.times, 1));
|
|
||||||
obj.constraintAdjacencyHist(:, :, 1) = obj.constraintAdjacencyMatrix;
|
|
||||||
|
|
||||||
|
|
||||||
% Set up plots showing initialized state
|
% Set up plots showing initialized state
|
||||||
obj = obj.plot();
|
obj = obj.plot();
|
||||||
|
|
||||||
|
|||||||
@@ -27,7 +27,6 @@ classdef miSim
|
|||||||
spatialPlotIndices = [6, 4, 3, 2];
|
spatialPlotIndices = [6, 4, 3, 2];
|
||||||
numBarriers = 0; % Number of barrier functions needed
|
numBarriers = 0; % Number of barrier functions needed
|
||||||
barriers = []; % log barrier function values at each timestep for analysis
|
barriers = []; % log barrier function values at each timestep for analysis
|
||||||
constraintAdjacencyHist = []; % log constraint adjacency matrix at each timestep
|
|
||||||
end
|
end
|
||||||
|
|
||||||
properties (Access = private)
|
properties (Access = private)
|
||||||
|
|||||||
@@ -34,11 +34,6 @@ function [obj] = run(obj)
|
|||||||
obj = obj.lesserNeighbor();
|
obj = obj.lesserNeighbor();
|
||||||
end
|
end
|
||||||
|
|
||||||
% Log constraint adjacency for this timestep
|
|
||||||
if coder.target('MATLAB')
|
|
||||||
obj.constraintAdjacencyHist(:, :, ii) = obj.constraintAdjacencyMatrix;
|
|
||||||
end
|
|
||||||
|
|
||||||
% Moving
|
% Moving
|
||||||
% Iterate over agents to simulate their unconstrained motion
|
% Iterate over agents to simulate their unconstrained motion
|
||||||
for jj = 1:size(obj.agents, 1)
|
for jj = 1:size(obj.agents, 1)
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ function obj = teardown(obj)
|
|||||||
out.dampingCoeff = obj.dampingCoeff;
|
out.dampingCoeff = obj.dampingCoeff;
|
||||||
out.useDoubleIntegrator = obj.useDoubleIntegrator;
|
out.useDoubleIntegrator = obj.useDoubleIntegrator;
|
||||||
out.useFixedTopology = obj.useFixedTopology;
|
out.useFixedTopology = obj.useFixedTopology;
|
||||||
out.constraintAdjacency = obj.constraintAdjacencyHist(:, :, 1:(end - 1));
|
|
||||||
for ii = 1:size(obj.agents, 1)
|
for ii = 1:size(obj.agents, 1)
|
||||||
out.agent(ii).pos = squeeze(obj.posHist(ii, 1:(end - 1), 1:3));
|
out.agent(ii).pos = squeeze(obj.posHist(ii, 1:(end - 1), 1:3));
|
||||||
out.agent(ii).vel = squeeze(obj.velHist(ii, 1:(end - 1), 1:3));
|
out.agent(ii).vel = squeeze(obj.velHist(ii, 1:(end - 1), 1:3));
|
||||||
@@ -44,7 +43,6 @@ function obj = teardown(obj)
|
|||||||
obj.agents = cell(0, 1);
|
obj.agents = cell(0, 1);
|
||||||
obj.adjacency = NaN;
|
obj.adjacency = NaN;
|
||||||
obj.constraintAdjacencyMatrix = NaN;
|
obj.constraintAdjacencyMatrix = NaN;
|
||||||
obj.constraintAdjacencyHist = [];
|
|
||||||
obj.partitioning = NaN;
|
obj.partitioning = NaN;
|
||||||
obj.performance = 0;
|
obj.performance = 0;
|
||||||
obj.barrierGain = NaN;
|
obj.barrierGain = NaN;
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ function validate(obj)
|
|||||||
for kk = 1:size(obj.agents, 1)
|
for kk = 1:size(obj.agents, 1)
|
||||||
P = min(max(obj.agents{kk}.pos, obj.obstacles{jj}.minCorner), obj.obstacles{jj}.maxCorner);
|
P = min(max(obj.agents{kk}.pos, obj.obstacles{jj}.minCorner), obj.obstacles{jj}.maxCorner);
|
||||||
d = obj.agents{kk}.pos - P;
|
d = obj.agents{kk}.pos - P;
|
||||||
if dot(d, d) < obj.agents{kk}.collisionGeometry.radius^2
|
if dot(d, d) < obj.agents{kk}.collisionGeometry.radius^2 - 1e-3
|
||||||
error("%s colliding with %s by %d", obj.agents{kk}.label, obj.obstacles{jj}.label, dot(d, d) - obj.agents{kk}.collisionGeometry.radius^2); % this will cause quadprog to fail
|
error("%s colliding with %s by %d", obj.agents{kk}.label, obj.obstacles{jj}.label, - dot(d, d) + obj.agents{kk}.collisionGeometry.radius^2); % this will cause quadprog to fail
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ function writeInits(obj)
|
|||||||
obsMinCorners = cell2mat(cellfun(@(x) x.minCorner, obj.obstacles, 'UniformOutput', false));
|
obsMinCorners = cell2mat(cellfun(@(x) x.minCorner, obj.obstacles, 'UniformOutput', false));
|
||||||
obsMaxCorners = cell2mat(cellfun(@(x) x.maxCorner, obj.obstacles, 'UniformOutput', false));
|
obsMaxCorners = cell2mat(cellfun(@(x) x.maxCorner, obj.obstacles, 'UniformOutput', false));
|
||||||
|
|
||||||
|
|
||||||
% Combine with simulation parameters
|
% Combine with simulation parameters
|
||||||
inits = struct("timestep", obj.timestep, "maxIter", obj.maxIter, "minAlt", obj.obstacles{end}.maxCorner(3), ...
|
inits = struct("timestep", obj.timestep, "maxIter", obj.maxIter, "minAlt", obj.obstacles{end}.maxCorner(3), ...
|
||||||
"discretizationStep", obj.domain.objective.discretizationStep, "protectedRange", obj.domain.objective.protectedRange, ...
|
"discretizationStep", obj.domain.objective.discretizationStep, "protectedRange", obj.domain.objective.protectedRange, ...
|
||||||
|
|||||||
@@ -38,7 +38,7 @@ function obj = initialize(obj, objectiveFunction, domain, discretizationStep, pr
|
|||||||
obj.values = obj.values ./ max(obj.values, [], "all");
|
obj.values = obj.values ./ max(obj.values, [], "all");
|
||||||
|
|
||||||
% store ground position
|
% store ground position
|
||||||
idx = obj.values == 1;
|
idx = obj.values == 1;
|
||||||
if any(isnan(objectiveMu))
|
if any(isnan(objectiveMu))
|
||||||
obj.groundPos = [obj.X(idx), obj.Y(idx)];
|
obj.groundPos = [obj.X(idx), obj.Y(idx)];
|
||||||
obj.groundPos = obj.groundPos(1, 1:2); % for safety, in case 2 points are maximal (somehow)
|
obj.groundPos = obj.groundPos(1, 1:2); % for safety, in case 2 points are maximal (somehow)
|
||||||
@@ -47,5 +47,5 @@ function obj = initialize(obj, objectiveFunction, domain, discretizationStep, pr
|
|||||||
end
|
end
|
||||||
obj.objectiveSigma = objectiveSigma;
|
obj.objectiveSigma = objectiveSigma;
|
||||||
|
|
||||||
assert(domain.distance([obj.groundPos, ones(size(obj.groundPos, 1), 1) .* domain.center(3)]) > protectedRange, "Domain is crowding the sensing objective");
|
assert(domain.distance([obj.groundPos, ones(size(obj.groundPos, 1), 1) .* domain.center(3)]) > protectedRange, "Domain is crowding the sensing objective")
|
||||||
end
|
end
|
||||||
189
plot_1.m
Normal file
189
plot_1.m
Normal file
@@ -0,0 +1,189 @@
|
|||||||
|
clear;
|
||||||
|
% Load data
|
||||||
|
dataPath = fullfile('.', 'sandbox', 'plot1');
|
||||||
|
simHists = dir(dataPath); simHists = simHists(3:end);
|
||||||
|
simInits = simHists(endsWith({simHists.name}, 'miSimInits.mat'));
|
||||||
|
simHists = simHists(endsWith({simHists.name}, 'miSimHist.mat'));
|
||||||
|
assert(length(simHists) == length(simInits), "input data availability mismatch");
|
||||||
|
|
||||||
|
% Initialize plotting data
|
||||||
|
nRuns = length(simHists);
|
||||||
|
Cfinal = NaN(nRuns, 1);
|
||||||
|
n = NaN(nRuns, 1);
|
||||||
|
doubleIntegrator = NaN(nRuns, 1);
|
||||||
|
numObjective = NaN(nRuns, 1);
|
||||||
|
positions = cell(6, nRuns);
|
||||||
|
commsRadius = NaN(nRuns, 1);
|
||||||
|
collisionRadius = NaN(nRuns, 1);
|
||||||
|
|
||||||
|
% Aggregate relevant data
|
||||||
|
for ii = 1:length(simHists)
|
||||||
|
initName = strrep(simInits(ii).name, "_miSimInits.mat", "");
|
||||||
|
histName = strrep(simHists(ii).name, "_miSimHist.mat", "");
|
||||||
|
assert(initName == histName);
|
||||||
|
|
||||||
|
init = load(fullfile(simInits(ii).folder, simInits(ii).name));
|
||||||
|
hist = load(fullfile(simHists(ii).folder, simHists(ii).name));
|
||||||
|
|
||||||
|
% Stash relevant data
|
||||||
|
Cfinal(ii) = hist.out.perf(end) / init.objectiveIntegral;
|
||||||
|
n(ii) = init.numAgents;
|
||||||
|
doubleIntegrator(ii) = init.useDoubleIntegrator;
|
||||||
|
numObjective(ii) = size(init.objectivePos, 1);
|
||||||
|
commsRadius(ii) = unique(init.comRange);
|
||||||
|
collisionRadius(ii) = unique(init.collisionRadius);
|
||||||
|
for jj = 1:length(hist.out.agent)
|
||||||
|
alphaDist(jj, ii) = hist.out.agent(jj).sensor.alphaDist;
|
||||||
|
positions{jj, ii} = hist.out.agent(jj).pos;
|
||||||
|
assert(hist.out.agent(jj).commsRadius == commsRadius(ii));
|
||||||
|
assert(hist.out.agent(jj).collisionRadius == collisionRadius(ii));
|
||||||
|
end
|
||||||
|
|
||||||
|
alphaDist2 = unique(alphaDist);
|
||||||
|
if length(alphaDist2) > 1
|
||||||
|
alphaDist2 = alphaDist2(1);
|
||||||
|
end
|
||||||
|
if doubleIntegrator(ii) && all(alphaDist(1:n(ii), ii) == alphaDist2) && numObjective(ii) == 1
|
||||||
|
a2betaIdx = ii;
|
||||||
|
a2beta = struct("init", init, "hist", hist.out);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
commsRadius = unique(commsRadius); assert(isscalar(commsRadius));
|
||||||
|
collisionRadius = unique(collisionRadius); assert(isscalar(collisionRadius));
|
||||||
|
sensors = flip(unique(alphaDist(1, :)));
|
||||||
|
n_unique = sort(unique(n));
|
||||||
|
nGroups = length(n_unique);
|
||||||
|
|
||||||
|
% Build config label for each run
|
||||||
|
config = strings(nRuns, 1);
|
||||||
|
baseConfig = strings(nRuns, 1);
|
||||||
|
for ii = 1:nRuns
|
||||||
|
s = "";
|
||||||
|
if numObjective(ii) == 1
|
||||||
|
s = s + "A";
|
||||||
|
elseif numObjective(ii) == 2
|
||||||
|
s = s + "B";
|
||||||
|
end
|
||||||
|
if alphaDist(1, ii) == sensors(1)
|
||||||
|
s = s + "_I";
|
||||||
|
elseif alphaDist(1, ii) == sensors(2)
|
||||||
|
s = s + "_II";
|
||||||
|
end
|
||||||
|
if ~doubleIntegrator(ii)
|
||||||
|
s = s + "_alpha";
|
||||||
|
else
|
||||||
|
s = s + "_beta";
|
||||||
|
end
|
||||||
|
baseConfig(ii) = s;
|
||||||
|
config(ii) = n(ii) + "_" + s;
|
||||||
|
end
|
||||||
|
configOrder = unique(baseConfig(n == n_unique(1)), 'stable');
|
||||||
|
nConfigsPerN = length(configOrder);
|
||||||
|
|
||||||
|
%%
|
||||||
|
close all;
|
||||||
|
f1 = figure;
|
||||||
|
x1 = axes;
|
||||||
|
|
||||||
|
C_mean = NaN(nGroups, nConfigsPerN);
|
||||||
|
C_var = NaN(nGroups, nConfigsPerN);
|
||||||
|
for ii = 1:nGroups
|
||||||
|
for jj = 1:nConfigsPerN
|
||||||
|
mask = (n == n_unique(ii)) & (baseConfig == configOrder(jj));
|
||||||
|
C_mean(ii, jj) = mean(Cfinal(mask));
|
||||||
|
C_var(ii, jj) = var(Cfinal(mask));
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
hBar = bar(x1, C_mean);
|
||||||
|
hold(x1, 'on');
|
||||||
|
for jj = 1:nConfigsPerN
|
||||||
|
xPos = hBar(jj).XEndPoints;
|
||||||
|
errorbar(x1, xPos, C_mean(:, jj), C_var(:, jj), 'k.', 'LineWidth', 1, 'HandleVisibility', 'off'); % disabled the error bars because they are small to the point of meaninglessness
|
||||||
|
end
|
||||||
|
hold(x1, 'off');
|
||||||
|
set(x1, 'XTickLabel', string(n_unique));
|
||||||
|
xlabel("Number of agents");
|
||||||
|
ylabel("Final coverage (normalized)");
|
||||||
|
title("Final performance of parameterizations");
|
||||||
|
legend(["$AI\alpha$"; "$AI\beta$"; "$AII\alpha$"; "$BI\beta$"], "Interpreter", "latex", "Location", "northwest");
|
||||||
|
grid("on");
|
||||||
|
ylim([0, 1/2]);
|
||||||
|
|
||||||
|
savefig(f1, "plot1.fig");
|
||||||
|
exportgraphics(f1, "plot1.png");
|
||||||
|
|
||||||
|
%%
|
||||||
|
f2 = figure;
|
||||||
|
x2 = axes;
|
||||||
|
|
||||||
|
% Compute pairwise distances between agents
|
||||||
|
maxPairs = nchoosek(6, 2);
|
||||||
|
pairDist = cell(maxPairs, nRuns);
|
||||||
|
for ii = 1:nRuns
|
||||||
|
pp = 0;
|
||||||
|
for jj = 1:n(ii)-1
|
||||||
|
for kk = jj+1:n(ii)
|
||||||
|
pp = pp + 1;
|
||||||
|
pairDist{pp, ii} = vecnorm(positions{jj, ii} - positions{kk, ii}, 2, 2);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
% Cap pairwise distances at communications range
|
||||||
|
for ii = 1:nRuns
|
||||||
|
nPairs = nchoosek(n(ii), 2);
|
||||||
|
for pp = 1:nPairs
|
||||||
|
pairDist{pp, ii} = min(pairDist{pp, ii}, commsRadius);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
% Compute mean, min, max pairwise distance across all pairs and timesteps per run
|
||||||
|
meanPairDist = NaN(nRuns, 1);
|
||||||
|
minPairDist = NaN(nRuns, 1);
|
||||||
|
maxPairDist = NaN(nRuns, 1);
|
||||||
|
for ii = 1:nRuns
|
||||||
|
nPairs = nchoosek(n(ii), 2);
|
||||||
|
D = vertcat(pairDist{1:nPairs, ii});
|
||||||
|
meanPairDist(ii) = mean(D);
|
||||||
|
minPairDist(ii) = min(D);
|
||||||
|
maxPairDist(ii) = max(D);
|
||||||
|
end
|
||||||
|
|
||||||
|
% Group pairwise distance stats by (n, config), aggregating across reps
|
||||||
|
meanD = NaN(nGroups, nConfigsPerN);
|
||||||
|
minD = NaN(nGroups, nConfigsPerN);
|
||||||
|
maxD = NaN(nGroups, nConfigsPerN);
|
||||||
|
for ii = 1:nGroups
|
||||||
|
for jj = 1:nConfigsPerN
|
||||||
|
mask = (n == n_unique(ii)) & (baseConfig == configOrder(jj));
|
||||||
|
meanD(ii, jj) = mean(meanPairDist(mask));
|
||||||
|
minD(ii, jj) = min(minPairDist(mask));
|
||||||
|
maxD(ii, jj) = max(maxPairDist(mask));
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
% Plot whiskers (min to max) with mean markers
|
||||||
|
barWidth = 0.8;
|
||||||
|
groupWidth = barWidth / nConfigsPerN;
|
||||||
|
hold(x2, 'on');
|
||||||
|
for jj = 1:nConfigsPerN
|
||||||
|
xPos = (1:nGroups) + (jj - (nConfigsPerN + 1) / 2) * groupWidth;
|
||||||
|
errorbar(x2, xPos, meanD(:, jj), meanD(:, jj) - minD(:, jj), maxD(:, jj) - meanD(:, jj), ...
|
||||||
|
'o', 'LineWidth', 1.5, 'MarkerSize', 6, 'CapSize', 10);
|
||||||
|
end
|
||||||
|
hold(x2, 'off');
|
||||||
|
set(x2, 'XTick', 1:nGroups, 'XTickLabel', string(n_unique));
|
||||||
|
xlabel(x2, "Number of agents");
|
||||||
|
ylabel(x2, "Pairwise distance");
|
||||||
|
title(x2, "Pairwise Agent Distances (min/mean/max)");
|
||||||
|
legend(x2, ["$AI\alpha$"; "$AI\beta$"; "$AII\alpha$"; "$BI\beta$"], "Interpreter", "latex");
|
||||||
|
grid(x2, "on");
|
||||||
|
|
||||||
|
yline(collisionRadius, 'r--', "Label", "Collision Radius", "LabelHorizontalAlignment", "left", "HandleVisibility", "off");
|
||||||
|
yline(commsRadius, 'r--', "Label", "Communications Radius", "LabelHorizontalAlignment", "left", "HandleVisibility", "off");
|
||||||
|
ylim([0, commsRadius + 5]);
|
||||||
|
|
||||||
|
savefig(f2, "plot2.fig");
|
||||||
|
exportgraphics(f2, "plot2.png");
|
||||||
142
plot_3.m
Normal file
142
plot_3.m
Normal file
@@ -0,0 +1,142 @@
|
|||||||
|
clear;
|
||||||
|
% Load data
|
||||||
|
dataPath = fullfile('.', 'sandbox', 'plot3');
|
||||||
|
simHists = dir(dataPath); simHists = simHists(3:end);
|
||||||
|
simInits = simHists(endsWith({simHists.name}, 'miSimInits.mat'));
|
||||||
|
simHists = simHists(endsWith({simHists.name}, 'miSimHist.mat'));
|
||||||
|
assert(length(simHists) == length(simInits), "input data availability mismatch");
|
||||||
|
assert(isscalar(simHists));
|
||||||
|
|
||||||
|
init = fullfile(simInits(1).folder, simInits(1).name);
|
||||||
|
hist = fullfile(simHists(1).folder, simHists(1).name);
|
||||||
|
|
||||||
|
init = load(init);
|
||||||
|
hist = load(hist);
|
||||||
|
hist = hist.out;
|
||||||
|
|
||||||
|
f3 = figure;
|
||||||
|
x3 = axes;
|
||||||
|
assert(size(init.objectivePos, 1) == 1)
|
||||||
|
assert(hist.useDoubleIntegrator);
|
||||||
|
|
||||||
|
plot(hist.perf./init.objectiveIntegral, "LineWidth", 2);
|
||||||
|
hold("on");
|
||||||
|
for ii = 1:length(hist.agent)
|
||||||
|
plot(hist.agent(ii).perf./init.objectiveIntegral, "LineWidth", 2);
|
||||||
|
end
|
||||||
|
grid("on");
|
||||||
|
ylabel("Performance (normalized)");
|
||||||
|
xlabel("Timestep");
|
||||||
|
legend(["Cumulative"; "Agent 1"; "Agent 2"; "Agent 3"; "Agent 4"], "Location", "northwest");
|
||||||
|
title("$AII\beta$ Performance", "Interpreter", "latex");
|
||||||
|
|
||||||
|
savefig(f3, "plot3.fig");
|
||||||
|
exportgraphics(f3, "plot3.png");
|
||||||
|
|
||||||
|
f4 = figure;
|
||||||
|
x4 = axes;
|
||||||
|
|
||||||
|
% Compute pairwise distances between agents over time
|
||||||
|
nAgents = length(hist.agent);
|
||||||
|
commsRadius = hist.agent(1).commsRadius;
|
||||||
|
collisionRadius = hist.agent(1).collisionRadius;
|
||||||
|
nPairs = nchoosek(nAgents, 2);
|
||||||
|
T = size(hist.agent(1).pos, 1);
|
||||||
|
pairDistMat = NaN(T, nPairs);
|
||||||
|
pp = 0;
|
||||||
|
for jj = 1:nAgents-1
|
||||||
|
for kk = jj+1:nAgents
|
||||||
|
pp = pp + 1;
|
||||||
|
pairDistMat(:, pp) = vecnorm(hist.agent(jj).pos - hist.agent(kk).pos, 2, 2);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
% Cap at communications range
|
||||||
|
% pairDistMat = min(pairDistMat, commsRadius);
|
||||||
|
|
||||||
|
% Plot all pairwise distances over time
|
||||||
|
hold(x4, 'on');
|
||||||
|
hLeft = gobjects(nPairs, 1);
|
||||||
|
for pp = 1:nPairs
|
||||||
|
hLeft(pp) = plot(x4, pairDistMat(:, pp), 'LineWidth', 2);
|
||||||
|
end
|
||||||
|
yline(x4, collisionRadius, 'r--', "Label", "Collision Radius", "LabelHorizontalAlignment", "left", "HandleVisibility", "off");
|
||||||
|
yline(x4, commsRadius, 'r--', "Label", "Communications Radius", "LabelHorizontalAlignment", "left", "HandleVisibility", "off");
|
||||||
|
hold(x4, 'off');
|
||||||
|
xlabel(x4, "Timestep");
|
||||||
|
ylabel(x4, "Pairwise distance");
|
||||||
|
title(x4, "$AII\beta$ Pairwise Agent Distances and Barrier Function Values", "Interpreter", "latex");
|
||||||
|
grid(x4, "on");
|
||||||
|
ylim(x4, [0, commsRadius + 5]);
|
||||||
|
|
||||||
|
% Build legend labels
|
||||||
|
pairLabels = strings(nPairs, 1);
|
||||||
|
pp = 0;
|
||||||
|
for jj = 1:nAgents-1
|
||||||
|
for kk = jj+1:nAgents
|
||||||
|
pp = pp + 1;
|
||||||
|
pairLabels(pp) = sprintf("Agents %d-%d Distance", jj, kk);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
l = legend(hLeft(:), pairLabels(:), "Location", "northeast");
|
||||||
|
|
||||||
|
savefig(f4, "plot4_distanceOnly.fig");
|
||||||
|
exportgraphics(f4, "plot4_distanceOnly.png");
|
||||||
|
|
||||||
|
% Plot all barrier function values on right Y-axis
|
||||||
|
nObs = init.numObstacles;
|
||||||
|
nAA = nchoosek(nAgents, 2);
|
||||||
|
nAO = nAgents * nObs;
|
||||||
|
nAD = nAgents * 6;
|
||||||
|
nComms = size(hist.barriers, 1) - nAA - nAO - nAD;
|
||||||
|
|
||||||
|
yyaxis(x4, 'right');
|
||||||
|
hold(x4, 'on');
|
||||||
|
|
||||||
|
% Color palettes: pairs share colors across collision/comms,
|
||||||
|
% agents share colors across obstacle/domain
|
||||||
|
pairColors = lines(nAA);
|
||||||
|
agentColors = lines(nAgents);
|
||||||
|
|
||||||
|
% Row offsets in hist.barriers
|
||||||
|
colStart = 1;
|
||||||
|
obsStart = colStart + nAA;
|
||||||
|
domStart = obsStart + nAO;
|
||||||
|
comStart = domStart + nAD;
|
||||||
|
|
||||||
|
% Collision + Comms barriers grouped per pair (same color)
|
||||||
|
hRight = gobjects(0, 1);
|
||||||
|
rightLabels = strings(0, 1);
|
||||||
|
for pp = 1:nAA
|
||||||
|
hRight(end+1) = plot(x4, hist.barriers(colStart + pp - 1, :), '--', 'LineWidth', 1.5, 'Color', pairColors(pp, :));
|
||||||
|
rightLabels(end+1) = sprintf('h_{col} %d', pp);
|
||||||
|
end
|
||||||
|
for pp = 1:nComms
|
||||||
|
hRight(end+1) = plot(x4, hist.barriers(comStart + pp - 1, :), '-.', 'LineWidth', 1.5, 'Color', pairColors(pp, :));
|
||||||
|
rightLabels(end+1) = sprintf('h_{com} %d', pp);
|
||||||
|
end
|
||||||
|
|
||||||
|
% Obstacle barriers — colored by agent
|
||||||
|
% idx = obsStart;
|
||||||
|
% for aa = 1:nAgents
|
||||||
|
% for oo = 1:nObs
|
||||||
|
% hRight(end+1) = plot(x4, hist.barriers(idx, :), ':', 'LineWidth', 1, 'Color', agentColors(aa, :));
|
||||||
|
% rightLabels(end+1) = sprintf('h_{obs} a%d-o%d', aa, oo);
|
||||||
|
% idx = idx + 1;
|
||||||
|
% end
|
||||||
|
% end
|
||||||
|
|
||||||
|
hold(x4, 'off');
|
||||||
|
ylabel(x4, "Barrier function $h$", "Interpreter", "latex");
|
||||||
|
|
||||||
|
% Clamp both Y-axes to start at 0
|
||||||
|
yyaxis(x4, 'left'); ylim(x4, [0, 25]);
|
||||||
|
yyaxis(x4, 'right'); ylim(x4, [0, 275]);
|
||||||
|
x4.YAxis(2).Color = 'k';
|
||||||
|
|
||||||
|
% Combined legend
|
||||||
|
l = legend([hLeft(:); hRight(:)], [pairLabels(:); rightLabels(:)], "Location", "eastoutside");
|
||||||
|
|
||||||
|
savefig(f4, "plot4.fig");
|
||||||
|
exportgraphics(f4, "plot4.png");
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info/>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info location="1" type="DIR_SIGNIFIER"/>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info>
|
||||||
|
<Category UUID="FileClassCategory">
|
||||||
|
<Label UUID="test"/>
|
||||||
|
</Category>
|
||||||
|
</Info>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info location="results.m" type="File"/>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info/>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info location="1" type="DIR_SIGNIFIER"/>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info/>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info location="1" type="DIR_SIGNIFIER"/>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info/>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info location="plot3" type="File"/>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info/>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info location="plot1_2" type="File"/>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info/>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info location="plot1" type="File"/>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info/>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info location="plot1_3" type="File"/>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info>
|
||||||
|
<Category UUID="FileClassCategory">
|
||||||
|
<Label UUID="design"/>
|
||||||
|
</Category>
|
||||||
|
</Info>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info location="plot_1.m" type="File"/>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info>
|
||||||
|
<Category UUID="FileClassCategory">
|
||||||
|
<Label UUID="design"/>
|
||||||
|
</Category>
|
||||||
|
</Info>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info location="plot_3.m" type="File"/>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info/>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info location="1" type="DIR_SIGNIFIER"/>
|
||||||
338
test/results.m
Normal file
338
test/results.m
Normal file
@@ -0,0 +1,338 @@
|
|||||||
|
classdef results < matlab.unittest.TestCase
|
||||||
|
properties (Constant, Access = private)
|
||||||
|
seed = 1;
|
||||||
|
domainSize = [150, 150, 100]; % fixed domain size [X, Y, Z]
|
||||||
|
end
|
||||||
|
|
||||||
|
properties (Access = private)
|
||||||
|
% System under test
|
||||||
|
testClass = miSim;
|
||||||
|
|
||||||
|
%% Diagnostic Parameters
|
||||||
|
% No effect on simulation dynamics
|
||||||
|
makeVideo = true; % disable video writing for big performance increase
|
||||||
|
makePlots = true; % disable plotting for big performance increase (also disables video)
|
||||||
|
plotCommsGeometry = false; % disable plotting communications geometries
|
||||||
|
|
||||||
|
%% Scenario Reinitialization
|
||||||
|
% Number of extra reinitializations per test case (3 n-values x 4 configs = 12).
|
||||||
|
% Order: n3/A_1_alpha, n3/A_1_beta, n3/A_2_alpha, n3/B_1_beta,
|
||||||
|
% n5/A_1_alpha, ..., n6/B_1_beta
|
||||||
|
% Set inspectScenarios = true to pause after init for manual review.
|
||||||
|
% At the keyboard prompt, type the number of reinits needed into
|
||||||
|
% the variable 'reinitCount', then 'dbcont' to continue.
|
||||||
|
inspectScenarios = false;
|
||||||
|
reinit = zeros(1, 12);
|
||||||
|
|
||||||
|
%% Fixed Test Parameters
|
||||||
|
useFixedTopology = true; % No lesser neighbor, fixed network instead
|
||||||
|
discretizationStep = 0.5;
|
||||||
|
protectedRange = 5;
|
||||||
|
collisionRadius = 5;
|
||||||
|
sensorPerformanceMinimum = 0.005;
|
||||||
|
comRange = 20;
|
||||||
|
maxIter = 400;
|
||||||
|
initialStepSize = 1;
|
||||||
|
% Each row: [minX minY minZ maxX maxY maxZ]
|
||||||
|
obstacleCorners = [results.domainSize(1)/2, results.domainSize(2)*5/8, 0, results.domainSize(1)*5/8, results.domainSize(2), 35;
|
||||||
|
results.domainSize(1)/3, 0, 0, results.domainSize(1)/2, results.domainSize(2)*3/8, 40];
|
||||||
|
barrierGain = 1;
|
||||||
|
barrierExponent = 1;
|
||||||
|
timestep = 0.5;
|
||||||
|
dampingCoeff = 2;
|
||||||
|
end
|
||||||
|
|
||||||
|
properties (TestParameter)
|
||||||
|
%% Test Iterations
|
||||||
|
% Specific parameter combos to run iterations on
|
||||||
|
n = struct('n3', 3, 'n5', 5, 'n6', 6); % number of agents
|
||||||
|
config = results.makeConfigs();
|
||||||
|
end
|
||||||
|
|
||||||
|
properties (MethodSetupParameter)
|
||||||
|
trials = struct('r1', 1, 'r2', 2, 'r3', 3, 'r4', 4, 'r5', 5);
|
||||||
|
end
|
||||||
|
|
||||||
|
methods (TestMethodSetup)
|
||||||
|
function setSeed(tc, trials)
|
||||||
|
rng(tc.seed + trials);
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
methods (Static, Access = public)
|
||||||
|
function c = makeConfigs()
|
||||||
|
rng(results.seed);
|
||||||
|
abMin = 6; % alpha*beta >= 6 ensures membership(0) = tanh(3) >= 0.995
|
||||||
|
alphaDist = rand(1, 2) .* [75, 45];
|
||||||
|
betaDist = abMin ./ alphaDist + rand(1, 2) .* [1, 1/8] .* (20 - abMin ./ alphaDist);
|
||||||
|
alphaTilt = 10 + rand(1, 2) .* [20, 20];
|
||||||
|
betaTilt = abMin ./ alphaTilt + rand(1, 2) .* (50 - abMin ./ alphaTilt);
|
||||||
|
sensors = struct('alphaDist', num2cell(alphaDist), 'alphaTilt', num2cell(alphaTilt), 'betaDist', num2cell(betaDist), 'betaTilt', num2cell(betaTilt));
|
||||||
|
sensor1 = sigmoidSensor;
|
||||||
|
sensor2 = sigmoidSensor;
|
||||||
|
sensor1 = sensor1.initialize(sensors(1).alphaDist, sensors(1).betaDist, sensors(1).alphaTilt, sensors(1).betaTilt);
|
||||||
|
sensor2 = sensor2.initialize(sensors(2).alphaDist, sensors(2).betaDist, sensors(2).alphaTilt, sensors(2).betaTilt);
|
||||||
|
sensor1.plotParameters;
|
||||||
|
sensor2.plotParameters;
|
||||||
|
c = struct('A_1_alpha', struct('objectivePos', [3, 1] / 4 .* results.domainSize(1:2), 'sensor', sensors(1), 'doubleIntegrator', false), ...
|
||||||
|
'A_1_beta', struct('objectivePos', [3, 1] / 4 .* results.domainSize(1:2), 'sensor', sensors(1), 'doubleIntegrator', true), ...
|
||||||
|
'A_2_alpha', struct('objectivePos', [3, 1] / 4 .* results.domainSize(1:2), 'sensor', sensors(2), 'doubleIntegrator', false), ...
|
||||||
|
'B_1_beta', struct('objectivePos', [[3, 1] / 4 .* results.domainSize(1:2); [3, 1] / 4 .* results.domainSize(1:2) + 25 .* [-1, 1] ./ sqrt(2)], 'sensor', sensors(1), 'doubleIntegrator', true));
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
methods (Test)
|
||||||
|
function plot1_runs(tc, n, config)
|
||||||
|
% if n == 5 && config.doubleIntegrator == true
|
||||||
|
% tc.makePlots = true;
|
||||||
|
% else
|
||||||
|
% tc.makePlots = false;
|
||||||
|
% end
|
||||||
|
% Compute test case index for reinit lookup
|
||||||
|
nKeys = fieldnames(tc.n);
|
||||||
|
configKeys = fieldnames(tc.config);
|
||||||
|
nIdx = find(cellfun(@(k) tc.n.(k) == n, nKeys));
|
||||||
|
configIdx = find(cellfun(@(k) isequal(tc.config.(k), config), configKeys));
|
||||||
|
testIdx = (nIdx - 1) * numel(configKeys) + configIdx;
|
||||||
|
|
||||||
|
% Determine number of reinitializations
|
||||||
|
reinitCount = tc.reinit(testIdx);
|
||||||
|
|
||||||
|
for reroll = 0:reinitCount
|
||||||
|
|
||||||
|
% Set up fixed-size domain
|
||||||
|
minAlt = tc.domainSize(3)/10 + rand * 1/10 * tc.domainSize(3);
|
||||||
|
% Place sensing objective(s) at fixed positions from config
|
||||||
|
objectiveMu = config.objectivePos;
|
||||||
|
numDist = size(objectiveMu, 1);
|
||||||
|
objectiveSigma = [];
|
||||||
|
for ii = 1:numDist
|
||||||
|
sig = [200, 140; 140, 280];
|
||||||
|
if ~mod(ii, 2)
|
||||||
|
sig = rot90(sig,2);
|
||||||
|
end
|
||||||
|
sig = reshape(sig, [1, 2, 2]);
|
||||||
|
objectiveSigma = cat(1, objectiveSigma, sig);
|
||||||
|
end
|
||||||
|
tc.testClass.domain = tc.testClass.domain.initialize([zeros(1, 3); tc.domainSize], REGION_TYPE.DOMAIN, "Domain");
|
||||||
|
tc.testClass.domain.objective = tc.testClass.domain.objective.initialize(objectiveFunctionWrapper(objectiveMu, objectiveSigma), tc.testClass.domain, tc.discretizationStep, tc.protectedRange, tc.sensorPerformanceMinimum, objectiveMu, objectiveSigma);
|
||||||
|
|
||||||
|
% Initialize agents
|
||||||
|
agents = cell(n, 1);
|
||||||
|
[agents{:}] = deal(agent);
|
||||||
|
|
||||||
|
% Initialize sensor model
|
||||||
|
sensorModel = sigmoidSensor;
|
||||||
|
sensorModel = sensorModel.initialize(config.sensor.alphaDist, config.sensor.betaDist, config.sensor.alphaTilt, config.sensor.betaTilt);
|
||||||
|
|
||||||
|
% Initialize fixed obstacles from corner coordinates
|
||||||
|
nObs = size(tc.obstacleCorners, 1);
|
||||||
|
obstacles = cell(nObs, 1);
|
||||||
|
for jj = 1:nObs
|
||||||
|
corners = [tc.obstacleCorners(jj, 1:3); tc.obstacleCorners(jj, 4:6)];
|
||||||
|
obstacles{jj} = rectangularPrism;
|
||||||
|
obstacles{jj} = obstacles{jj}.initialize(corners, REGION_TYPE.OBSTACLE, sprintf("Obstacle %d", jj));
|
||||||
|
end
|
||||||
|
|
||||||
|
% Place agents in small-x, large-y quadrant (opposite objectives)
|
||||||
|
% with chain topology: each agent connected only to its neighbors
|
||||||
|
midXY = (tc.testClass.domain.minCorner(1:2) + tc.testClass.domain.maxCorner(1:2)) / 2;
|
||||||
|
quadrantSize = tc.testClass.domain.maxCorner(1:2) / 2;
|
||||||
|
margin = quadrantSize / 6;
|
||||||
|
agentBounds = [tc.testClass.domain.minCorner(1) + margin(1), ...
|
||||||
|
midXY(2) + margin(2); ...
|
||||||
|
midXY(1) - margin(1), ...
|
||||||
|
tc.testClass.domain.maxCorner(2) - margin(2)];
|
||||||
|
% Find a fixed altitude where sensor performance passes at ALL
|
||||||
|
% corners of the placement bounds (worst-case XY)
|
||||||
|
corners = [agentBounds(1,1), agentBounds(1,2);
|
||||||
|
agentBounds(2,1), agentBounds(1,2);
|
||||||
|
agentBounds(1,1), agentBounds(2,2);
|
||||||
|
agentBounds(2,1), agentBounds(2,2)];
|
||||||
|
agentAlt = tc.testClass.domain.maxCorner(3) - tc.collisionRadius;
|
||||||
|
while agentAlt > minAlt + 2 * tc.collisionRadius
|
||||||
|
worstPerf = inf;
|
||||||
|
for cc = 1:4
|
||||||
|
p = sensorModel.sensorPerformance([corners(cc,:), agentAlt], [corners(cc,:), 0]);
|
||||||
|
worstPerf = min(worstPerf, p);
|
||||||
|
end
|
||||||
|
if worstPerf >= tc.sensorPerformanceMinimum * 10
|
||||||
|
break;
|
||||||
|
end
|
||||||
|
agentAlt = agentAlt - 1;
|
||||||
|
end
|
||||||
|
chainSpacingMin = 0.7 * tc.comRange;
|
||||||
|
chainSpacingMax = 0.9 * tc.comRange;
|
||||||
|
collisionGeometry = spherical;
|
||||||
|
for jj = 1:n
|
||||||
|
retry = true;
|
||||||
|
while retry
|
||||||
|
retry = false;
|
||||||
|
|
||||||
|
if jj == 1
|
||||||
|
% First agent: random XY within bounds, fixed altitude
|
||||||
|
agentPos = [agentBounds(1, :) + (agentBounds(2, :) - agentBounds(1, :)) .* rand(1, 2), agentAlt];
|
||||||
|
else
|
||||||
|
% Place at 0.7-0.9 * comRange in XY from previous agent, same altitude
|
||||||
|
dir = randn(1, 2);
|
||||||
|
dir = dir / norm(dir);
|
||||||
|
r = chainSpacingMin + rand * (chainSpacingMax - chainSpacingMin);
|
||||||
|
agentPos = [agents{jj-1}.pos(1:2) + r * dir, agentAlt];
|
||||||
|
end
|
||||||
|
|
||||||
|
% Check within placement bounds (XY only, Z is fixed)
|
||||||
|
if any(agentPos(1:2) <= agentBounds(1, :)) || any(agentPos(1:2) >= agentBounds(2, :))
|
||||||
|
retry = true;
|
||||||
|
continue;
|
||||||
|
end
|
||||||
|
|
||||||
|
% Check sensor performance threshold; lower altitude if it fails
|
||||||
|
if sensorModel.sensorPerformance(agentPos, [agentPos(1:2), 0]) < tc.sensorPerformanceMinimum * 10
|
||||||
|
agentAlt = max(agentAlt - tc.collisionRadius, minAlt + 1.1 * tc.collisionRadius);
|
||||||
|
agentPos(3) = agentAlt;
|
||||||
|
% If we've hit the floor and still failing, widen XY search
|
||||||
|
if agentAlt <= minAlt + 2 * tc.collisionRadius
|
||||||
|
agentBounds = [tc.testClass.domain.minCorner(1) + tc.collisionRadius, ...
|
||||||
|
tc.testClass.domain.minCorner(2) + tc.collisionRadius; ...
|
||||||
|
tc.testClass.domain.maxCorner(1) - tc.collisionRadius, ...
|
||||||
|
tc.testClass.domain.maxCorner(2) - tc.collisionRadius];
|
||||||
|
end
|
||||||
|
retry = true;
|
||||||
|
continue;
|
||||||
|
end
|
||||||
|
|
||||||
|
% Must be within comRange of previous agent (chain link)
|
||||||
|
if jj > 1 && norm(agents{jj-1}.pos - agentPos) >= tc.comRange
|
||||||
|
retry = true;
|
||||||
|
continue;
|
||||||
|
end
|
||||||
|
|
||||||
|
% Must be BEYOND comRange of all non-adjacent agents (sparsity)
|
||||||
|
% for kk = 1:(jj - 2)
|
||||||
|
% if norm(agents{kk}.pos - agentPos) < tc.comRange
|
||||||
|
% retry = true;
|
||||||
|
% break;
|
||||||
|
% end
|
||||||
|
% end
|
||||||
|
% if retry, continue; end
|
||||||
|
|
||||||
|
% No collision with any existing agent
|
||||||
|
for kk = 1:(jj - 1)
|
||||||
|
if norm(agents{kk}.pos - agentPos) < agents{kk}.collisionGeometry.radius + tc.collisionRadius
|
||||||
|
retry = true;
|
||||||
|
break;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if retry, continue; end
|
||||||
|
|
||||||
|
% No collision with any obstacle
|
||||||
|
for kk = 1:nObs
|
||||||
|
P = min(max(agentPos, obstacles{kk}.minCorner), obstacles{kk}.maxCorner);
|
||||||
|
d = agentPos - P;
|
||||||
|
if dot(d, d) <= tc.collisionRadius^2
|
||||||
|
retry = true;
|
||||||
|
break;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
% Initialize agent
|
||||||
|
collisionGeometry = collisionGeometry.initialize(agentPos, tc.collisionRadius, REGION_TYPE.COLLISION, sprintf("Agent %d Collision Region", jj));
|
||||||
|
agents{jj} = agents{jj}.initialize(agentPos, collisionGeometry, sensorModel, tc.comRange, tc.maxIter, tc.initialStepSize, sprintf("Agent %d", jj), tc.plotCommsGeometry);
|
||||||
|
end
|
||||||
|
|
||||||
|
% Randomly shuffle agents to vary index-based topology
|
||||||
|
agents = agents(randperm(numel(agents)));
|
||||||
|
|
||||||
|
end % reroll loop
|
||||||
|
|
||||||
|
% Inspect scenario if enabled
|
||||||
|
if tc.inspectScenarios
|
||||||
|
tc.testClass = tc.testClass.initialize(tc.testClass.domain, agents, tc.barrierGain, tc.barrierExponent, minAlt, tc.timestep, tc.maxIter, obstacles, tc.makePlots, tc.makeVideo, config.doubleIntegrator, tc.dampingCoeff, tc.useFixedTopology);
|
||||||
|
fprintf("Test %d (n=%d, config=%s): reinit=%d. Inspect plot.\n", testIdx, n, configKeys{configIdx}, reinitCount);
|
||||||
|
fprintf("To add reinits, update tc.reinit(%d) and rerun.\n", testIdx);
|
||||||
|
keyboard;
|
||||||
|
tc.testClass = tc.testClass.teardown();
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
% Set up simulation
|
||||||
|
tc.testClass = tc.testClass.initialize(tc.testClass.domain, agents, tc.barrierGain, tc.barrierExponent, minAlt, tc.timestep, tc.maxIter, obstacles, tc.makePlots, tc.makeVideo, config.doubleIntegrator, tc.dampingCoeff, tc.useFixedTopology);
|
||||||
|
|
||||||
|
% Save simulation parameters to output file
|
||||||
|
tc.testClass.writeInits();
|
||||||
|
|
||||||
|
% Run
|
||||||
|
tc.testClass = tc.testClass.run();
|
||||||
|
|
||||||
|
% Cleanup
|
||||||
|
tc.testClass = tc.testClass.teardown();
|
||||||
|
close all;
|
||||||
|
end
|
||||||
|
function AIIbeta_plots_3_4(tc)
|
||||||
|
% test-specific parameters
|
||||||
|
tc.makePlots = true;
|
||||||
|
tc.makeVideo = true;
|
||||||
|
maxIters = 400;
|
||||||
|
|
||||||
|
configs = results.makeConfigs();
|
||||||
|
c = configs.A_2_alpha;
|
||||||
|
c.doubleIntegrator = true; % make a2alpha into a2beta
|
||||||
|
|
||||||
|
% Set up fixed-size domain
|
||||||
|
minAlt = tc.domainSize(3)/10 + rand * 1/10 * tc.domainSize(3);
|
||||||
|
tc.testClass.domain = tc.testClass.domain.initialize([zeros(1, 3); tc.domainSize], REGION_TYPE.DOMAIN, "Domain");
|
||||||
|
|
||||||
|
% Set objective
|
||||||
|
objectiveMu = [tc.domainSize(1) * 2 / 3, tc.domainSize(2) * 3 / 4];
|
||||||
|
objectiveSigma = reshape([215, 100; 100, 175], [1, 2, 2]);
|
||||||
|
tc.testClass.domain.objective = tc.testClass.domain.objective.initialize(objectiveFunctionWrapper(objectiveMu, objectiveSigma), tc.testClass.domain, tc.discretizationStep, tc.protectedRange, tc.sensorPerformanceMinimum, objectiveMu, objectiveSigma);
|
||||||
|
|
||||||
|
% Set agent initial states (fully connected network of 4)
|
||||||
|
centerPos = [tc.domainSize(1) / 4, tc.domainSize(2) / 4];
|
||||||
|
d = tc.collisionRadius + (tc.comRange - tc.collisionRadius) / 4;
|
||||||
|
agentsPos = centerPos + [1, 1; 1, -1; -1, -1; -1, 1] / sqrt(2) * d;
|
||||||
|
agentAlt = minAlt * 1.5;
|
||||||
|
agentsPos = [agentsPos, agentAlt * ones(4, 1) + rand * 5 - 2.5];
|
||||||
|
|
||||||
|
agents = {agent, agent, agent, agent};
|
||||||
|
cg = spherical;
|
||||||
|
sensorModel = sigmoidSensor;
|
||||||
|
sensorModel = sensorModel.initialize(c.sensor.alphaDist, c.sensor.betaDist, c.sensor.alphaTilt, c.sensor.betaTilt);
|
||||||
|
agents{1} = agents{1}.initialize(agentsPos(1, :), cg.initialize(agentsPos(1, :), tc.collisionRadius, REGION_TYPE.COLLISION, "Agent 1 Collision Geometry"), sensorModel, tc.comRange, maxIters, tc.initialStepSize, "Agent 1", false);
|
||||||
|
agents{2} = agents{2}.initialize(agentsPos(2, :), cg.initialize(agentsPos(2, :), tc.collisionRadius, REGION_TYPE.COLLISION, "Agent 2 Collision Geometry"), sensorModel, tc.comRange, maxIters, tc.initialStepSize, "Agent 2", false);
|
||||||
|
agents{3} = agents{3}.initialize(agentsPos(3, :), cg.initialize(agentsPos(3, :), tc.collisionRadius, REGION_TYPE.COLLISION, "Agent 3 Collision Geometry"), sensorModel, tc.comRange, maxIters, tc.initialStepSize, "Agent 3", false);
|
||||||
|
agents{4} = agents{4}.initialize(agentsPos(4, :), cg.initialize(agentsPos(4, :), tc.collisionRadius, REGION_TYPE.COLLISION, "Agent 4 Collision Geometry"), sensorModel, tc.comRange, maxIters, tc.initialStepSize, "Agent 4", false);
|
||||||
|
|
||||||
|
obstacles = cell(1, 1);
|
||||||
|
obstacles{1} = rectangularPrism;
|
||||||
|
obstacles{1} = obstacles{1}.initialize([0, tc.domainSize(2)/2, 0; tc.domainSize(1) * 0.4, tc.domainSize(2), 40],REGION_TYPE.OBSTACLE, "Obstacle 1");
|
||||||
|
|
||||||
|
% Set up simulation
|
||||||
|
tc.testClass = tc.testClass.initialize(tc.testClass.domain, agents, tc.barrierGain, tc.barrierExponent, minAlt, tc.timestep, maxIters, obstacles, tc.makePlots, tc.makeVideo, c.doubleIntegrator, tc.dampingCoeff, tc.useFixedTopology);
|
||||||
|
|
||||||
|
% Save simulation parameters to output file
|
||||||
|
tc.testClass.writeInits();
|
||||||
|
|
||||||
|
% Run
|
||||||
|
tc.testClass = tc.testClass.run();
|
||||||
|
|
||||||
|
% Cleanup
|
||||||
|
tc.testClass = tc.testClass.teardown();
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
methods
|
||||||
|
function c = obstacleCollisionCheck(~, obstacles, obstacle)
|
||||||
|
% Check if the obstacle intersects with any other obstacles
|
||||||
|
c = false;
|
||||||
|
for ii = 1:size(obstacles, 1)
|
||||||
|
if geometryIntersects(obstacles{ii}, obstacle)
|
||||||
|
c = true;
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -9,7 +9,7 @@ function f = objectiveFunctionWrapper(center, sigma)
|
|||||||
arguments (Output)
|
arguments (Output)
|
||||||
f (1, 1) {mustBeA(f, "function_handle")};
|
f (1, 1) {mustBeA(f, "function_handle")};
|
||||||
end
|
end
|
||||||
|
|
||||||
assert(size(center, 1) == size(sigma, 1));
|
assert(size(center, 1) == size(sigma, 1));
|
||||||
f = @(x,y) sum(cell2mat(arrayfun(@(i) mvnpdf([x(:), y(:)], center(i,:), squeeze(sigma(i, :, :))), 1:size(center,1), "UniformOutput", false)), 2);
|
f = @(x,y) sum(cell2mat(arrayfun(@(i) mvnpdf([x(:), y(:)], center(i,:), squeeze(sigma(i, :, :))), 1:size(center,1), "UniformOutput", false)), 2);
|
||||||
|
|
||||||
end
|
end
|
||||||
Reference in New Issue
Block a user