lots of cleanup and simplification in test case construction

This commit is contained in:
2026-01-13 21:17:35 -08:00
parent 08e396c155
commit bcb3bc3da3
65 changed files with 150 additions and 265 deletions

View File

@@ -9,14 +9,9 @@ classdef agent
% State % State
lastPos = NaN(1, 3); % position from previous timestep lastPos = NaN(1, 3); % position from previous timestep
pos = NaN(1, 3); % current position pos = NaN(1, 3); % current position
vel = NaN(1, 3); % current velocity
pan = NaN; % pan angle
tilt = NaN; % tilt angle
% Collision % Collision
collisionGeometry; collisionGeometry;
barrierFunction;
dBarrierFunction;
% FOV cone % FOV cone
fovGeometry; fovGeometry;
@@ -39,7 +34,7 @@ classdef agent
end end
methods (Access = public) methods (Access = public)
[obj] = initialize(obj, pos, vel, pan, tilt, collisionGeometry, sensorModel, guidanceModel, comRange, index, label); [obj] = initialize(obj, pos, pan, tilt, collisionGeometry, sensorModel, guidanceModel, comRange, index, label);
[obj] = run(obj, domain, partitioning, t, index, agents); [obj] = run(obj, domain, partitioning, t, index, agents);
[partitioning] = partition(obj, agents, objective) [partitioning] = partition(obj, agents, objective)
[obj, f] = plot(obj, ind, f); [obj, f] = plot(obj, ind, f);

View File

@@ -1,10 +1,7 @@
function obj = initialize(obj, pos, vel, pan, tilt, collisionGeometry, sensorModel, comRange, maxIter, label, plotCommsGeometry) function obj = initialize(obj, pos, collisionGeometry, sensorModel, comRange, maxIter, label, plotCommsGeometry)
arguments (Input) arguments (Input)
obj (1, 1) {mustBeA(obj, 'agent')}; obj (1, 1) {mustBeA(obj, 'agent')};
pos (1, 3) double; pos (1, 3) double;
vel (1, 3) double;
pan (1, 1) double;
tilt (1, 1) double;
collisionGeometry (1, 1) {mustBeGeometry}; collisionGeometry (1, 1) {mustBeGeometry};
sensorModel (1, 1) {mustBeSensor}; sensorModel (1, 1) {mustBeSensor};
comRange (1, 1) double; comRange (1, 1) double;
@@ -17,9 +14,6 @@ function obj = initialize(obj, pos, vel, pan, tilt, collisionGeometry, sensorMod
end end
obj.pos = pos; obj.pos = pos;
obj.vel = vel;
obj.pan = pan;
obj.tilt = tilt;
obj.collisionGeometry = collisionGeometry; obj.collisionGeometry = collisionGeometry;
obj.sensorModel = sensorModel; obj.sensorModel = sensorModel;
obj.label = label; obj.label = label;

View File

@@ -10,7 +10,7 @@ function [partitioning] = partition(obj, agents, objective)
% Assess sensing performance of each agent at each sample point % Assess sensing performance of each agent at each sample point
% in the domain % in the domain
agentPerformances = cellfun(@(x) reshape(x.sensorModel.sensorPerformance(x.pos, x.pan, x.tilt, [objective.X(:), objective.Y(:), zeros(size(objective.X(:)))]), size(objective.X)), agents, 'UniformOutput', false); agentPerformances = cellfun(@(x) reshape(x.sensorModel.sensorPerformance(x.pos, [objective.X(:), objective.Y(:), zeros(size(objective.X(:)))]), size(objective.X)), agents, 'UniformOutput', false);
agentPerformances{end + 1} = objective.sensorPerformanceMinimum * ones(size(agentPerformances{end})); % add additional layer to represent the threshold that has to be cleared for assignment to any partiton agentPerformances{end + 1} = objective.sensorPerformanceMinimum * ones(size(agentPerformances{end})); % add additional layer to represent the threshold that has to be cleared for assignment to any partiton
agentPerformances = cat(3, agentPerformances{:}); agentPerformances = cat(3, agentPerformances{:});

View File

@@ -13,6 +13,10 @@ function obj = run(obj, domain, partitioning, timestepIndex, index, agents)
% Collect objective function values across partition % Collect objective function values across partition
partitionMask = partitioning == index; partitionMask = partitioning == index;
if ~unique(partitionMask)
% This agent has no partition, maintain current state
return;
end
objectiveValues = domain.objective.values(partitionMask); % f(omega) on W_n objectiveValues = domain.objective.values(partitionMask); % f(omega) on W_n
% Compute sensor performance on partition % Compute sensor performance on partition
@@ -30,7 +34,7 @@ function obj = run(obj, domain, partitioning, timestepIndex, index, agents)
% Compute performance values on partition % Compute performance values on partition
if ii < 5 if ii < 5
% Compute sensing performance % Compute sensing performance
sensorValues = obj.sensorModel.sensorPerformance(pos, obj.pan, obj.tilt, [maskedX, maskedY, zeros(size(maskedX))]); % S_n(omega, P_n) on W_n sensorValues = obj.sensorModel.sensorPerformance(pos, [maskedX, maskedY, zeros(size(maskedX))]); % S_n(omega, P_n) on W_n
% Objective performance does not change for 0, +/- X, Y steps. % Objective performance does not change for 0, +/- X, Y steps.
% Those values are computed once before the loop and are only % Those values are computed once before the loop and are only
% recomputed when +/- Z steps are applied % recomputed when +/- Z steps are applied
@@ -45,7 +49,7 @@ function obj = run(obj, domain, partitioning, timestepIndex, index, agents)
% Recompute partiton-derived performance values for sensing % Recompute partiton-derived performance values for sensing
maskedX = domain.objective.X(partitionMask); maskedX = domain.objective.X(partitionMask);
maskedY = domain.objective.Y(partitionMask); maskedY = domain.objective.Y(partitionMask);
sensorValues = obj.sensorModel.sensorPerformance(pos, obj.pan, obj.tilt, [maskedX, maskedY, zeros(size(maskedX))]); % S_n(omega, P_n) on W_n sensorValues = obj.sensorModel.sensorPerformance(pos, [maskedX, maskedY, zeros(size(maskedX))]); % S_n(omega, P_n) on W_n
end end
% Rearrange data into image arrays % Rearrange data into image arrays

View File

@@ -5,6 +5,13 @@ function updatePlots(obj)
arguments (Output) arguments (Output)
end end
% Find change in agent position since last timestep
deltaPos = obj.pos - obj.lastPos;
if all(isnan(deltaPos)) || all(deltaPos == zeros(1, 3))
% Agent did not move, so nothing has to move on the plots
return;
end
% Scatterplot point positions % Scatterplot point positions
for ii = 1:size(obj.scatterPoints, 1) for ii = 1:size(obj.scatterPoints, 1)
obj.scatterPoints(ii).XData = obj.pos(1); obj.scatterPoints(ii).XData = obj.pos(1);
@@ -12,9 +19,6 @@ function updatePlots(obj)
obj.scatterPoints(ii).ZData = obj.pos(3); obj.scatterPoints(ii).ZData = obj.pos(3);
end end
% Find change in agent position since last timestep
deltaPos = obj.pos - obj.lastPos;
% Collision geometry edges % Collision geometry edges
for jj = 1:size(obj.collisionGeometry.lines, 2) for jj = 1:size(obj.collisionGeometry.lines, 2)
% Update plotting % Update plotting

View File

@@ -14,6 +14,11 @@ function [obj] = constrainMotion(obj)
agents = [obj.agents{:}]; agents = [obj.agents{:}];
v = reshape(([agents.pos] - [agents.lastPos])./obj.timestep, 3, size(obj.agents, 1))'; v = reshape(([agents.pos] - [agents.lastPos])./obj.timestep, 3, size(obj.agents, 1))';
if all(isnan(v)) || all(v == zeros(1, 3))
% Agents are not attempting to move, so there is no motion to be
% constrained
return;
end
% Initialize QP based on number of agents and obstacles % Initialize QP based on number of agents and obstacles
nAOPairs = size(obj.agents, 1) * size(obj.obstacles, 1); % unique agent/obstacle pairs nAOPairs = size(obj.agents, 1) * size(obj.obstacles, 1); % unique agent/obstacle pairs

View File

@@ -1,8 +1,7 @@
function obj = initialize(obj, domain, objective, agents, minAlt, timestep, maxIter, obstacles, makePlots, makeVideo) function obj = initialize(obj, domain, agents, minAlt, timestep, maxIter, obstacles, makePlots, makeVideo)
arguments (Input) arguments (Input)
obj (1, 1) {mustBeA(obj, 'miSim')}; obj (1, 1) {mustBeA(obj, 'miSim')};
domain (1, 1) {mustBeGeometry}; domain (1, 1) {mustBeGeometry};
objective (1, 1) {mustBeA(objective, 'sensingObjective')};
agents (:, 1) cell; agents (:, 1) cell;
minAlt (1, 1) double = 1; minAlt (1, 1) double = 1;
timestep (:, 1) double = 0.05; timestep (:, 1) double = 0.05;
@@ -44,9 +43,6 @@ function obj = initialize(obj, domain, objective, agents, minAlt, timestep, maxI
obj.obstacles{end, 1} = obj.obstacles{end, 1}.initialize([obj.domain.minCorner; obj.domain.maxCorner(1:2), obj.minAlt], "OBSTACLE", "Minimum Altitude Domain Constraint"); obj.obstacles{end, 1} = obj.obstacles{end, 1}.initialize([obj.domain.minCorner; obj.domain.maxCorner(1:2), obj.minAlt], "OBSTACLE", "Minimum Altitude Domain Constraint");
end end
% Define objective
obj.objective = objective;
% Define agents % Define agents
obj.agents = agents; obj.agents = agents;
obj.constraintAdjacencyMatrix = logical(eye(size(agents, 1))); obj.constraintAdjacencyMatrix = logical(eye(size(agents, 1)));
@@ -76,7 +72,7 @@ function obj = initialize(obj, domain, objective, agents, minAlt, timestep, maxI
obj.perf = [zeros(size(obj.agents, 1) + 1, 1), NaN(size(obj.agents, 1) + 1, size(obj.partitioningTimes, 1) - 1)]; obj.perf = [zeros(size(obj.agents, 1) + 1, 1), NaN(size(obj.agents, 1) + 1, size(obj.partitioningTimes, 1) - 1)];
% Prepare h function data store % Prepare h function data store
obj.h = NaN(size(obj.agents, 1) * (size(obj.agents, 1) - 1) / 2 + size(obj.agents, 1) * size(obj.obstacles, 1) + 6, size(obj.times, 1) - 1); obj.h = NaN(size(obj.agents, 1) * (size(obj.agents, 1) - 1) / 2 + size(obj.agents, 1) * size(obj.obstacles, 1) + 6, size(obj.times, 1));
% Create initial partitioning % Create initial partitioning
obj.partitioning = obj.agents{1}.partition(obj.agents, obj.domain.objective); obj.partitioning = obj.agents{1}.partition(obj.agents, obj.domain.objective);

View File

@@ -55,7 +55,7 @@ classdef miSim
end end
methods (Access = public) methods (Access = public)
[obj] = initialize(obj, domain, objective, agents, timestep, partitoningFreq, maxIter, obstacles); [obj] = initialize(obj, domain, agents, timestep, partitoningFreq, maxIter, obstacles);
[obj] = run(obj); [obj] = run(obj);
[obj] = lesserNeighbor(obj); [obj] = lesserNeighbor(obj);
[obj] = constrainMotion(obj); [obj] = constrainMotion(obj);
@@ -69,6 +69,7 @@ classdef miSim
[obj] = plotH(obj); [obj] = plotH(obj);
[obj] = updatePlots(obj); [obj] = updatePlots(obj);
validate(obj); validate(obj);
teardown(obj);
end end
methods (Access = private) methods (Access = private)
[v] = setupVideoWriter(obj); [v] = setupVideoWriter(obj);

13
@miSim/teardown.m Normal file
View File

@@ -0,0 +1,13 @@
function teardown(obj)
arguments (Input)
obj (1, 1) {mustBeA(obj, 'miSim')};
end
arguments (Output)
end
% Close plots
close(obj.hf);
close(obj.fPerf);
close(obj.f);
end

View File

@@ -1,10 +1,8 @@
function obj = initialize(obj, alphaDist, betaDist, alphaPan, betaPan, alphaTilt, betaTilt) function obj = initialize(obj, alphaDist, betaDist, alphaTilt, betaTilt)
arguments (Input) arguments (Input)
obj (1, 1) {mustBeA(obj, 'sigmoidSensor')} obj (1, 1) {mustBeA(obj, 'sigmoidSensor')}
alphaDist (1, 1) double; alphaDist (1, 1) double;
betaDist (1, 1) double; betaDist (1, 1) double;
alphaPan (1, 1) double;
betaPan (1, 1) double;
alphaTilt (1, 1) double; alphaTilt (1, 1) double;
betaTilt (1, 1) double; betaTilt (1, 1) double;
end end
@@ -14,8 +12,6 @@ function obj = initialize(obj, alphaDist, betaDist, alphaPan, betaPan, alphaTilt
obj.alphaDist = alphaDist; obj.alphaDist = alphaDist;
obj.betaDist = betaDist; obj.betaDist = betaDist;
obj.alphaPan = alphaPan;
obj.betaPan = betaPan;
obj.alphaTilt = alphaTilt; obj.alphaTilt = alphaTilt;
obj.betaTilt = betaTilt; obj.betaTilt = betaTilt;
end end

View File

@@ -1,9 +1,7 @@
function value = sensorPerformance(obj, agentPos, agentPan, agentTilt, targetPos) function value = sensorPerformance(obj, agentPos, targetPos)
arguments (Input) arguments (Input)
obj (1, 1) {mustBeA(obj, 'sigmoidSensor')}; obj (1, 1) {mustBeA(obj, 'sigmoidSensor')};
agentPos (1, 3) double; agentPos (1, 3) double;
agentPan (1, 1) double;
agentTilt (1, 1) double;
targetPos (:, 3) double; targetPos (:, 3) double;
end end
arguments (Output) arguments (Output)
@@ -15,7 +13,7 @@ function value = sensorPerformance(obj, agentPos, agentPan, agentTilt, targetPos
x = vecnorm(agentPos(1:2) - targetPos(:, 1:2), 2, 2); % distance from sensor nadir to target nadir (i.e. distance ignoring height difference) x = vecnorm(agentPos(1:2) - targetPos(:, 1:2), 2, 2); % distance from sensor nadir to target nadir (i.e. distance ignoring height difference)
% compute tilt angle % compute tilt angle
tiltAngle = (180 - atan2d(x, targetPos(:, 3) - agentPos(3))) - agentTilt; % degrees tiltAngle = (180 - atan2d(x, targetPos(:, 3) - agentPos(3))); % degrees
% Membership functions % Membership functions
mu_d = obj.distanceMembership(d); mu_d = obj.distanceMembership(d);

View File

@@ -3,15 +3,12 @@ classdef sigmoidSensor
% Sensor parameters % Sensor parameters
alphaDist = NaN; alphaDist = NaN;
betaDist = NaN; betaDist = NaN;
alphaPan = NaN;
betaPan = NaN;
alphaTilt = NaN; % degrees alphaTilt = NaN; % degrees
betaTilt = NaN; betaTilt = NaN;
end end
methods (Access = public) methods (Access = public)
[obj] = initialize(obj, alphaDist, betaDist, alphaPan, betaPan, alphaTilt, betaTilt); [obj] = initialize(obj, alphaDist, betaDist, alphaTilt, betaTilt);
[values, positions] = sense(obj, agent, sensingObjective, domain, partitioning);
[value] = sensorPerformance(obj, agentPos, agentPan, agentTilt, targetPos); [value] = sensorPerformance(obj, agentPos, agentPan, agentTilt, targetPos);
[f] = plotParameters(obj); [f] = plotParameters(obj);
end end

View File

@@ -48,13 +48,4 @@ function obj = initialize(obj, bounds, tag, label, objectiveFunction, discretiza
if tag == REGION_TYPE.DOMAIN if tag == REGION_TYPE.DOMAIN
obj.objective = sensingObjective; obj.objective = sensingObjective;
end end
% Initialize CBF
% first part evaluates to +/-1 if the point is outside/inside the collision geometry
% Second part determines the distance from the point to the boundary of the collision geometry
obj.barrierFunction = @(x) (1 - 2 * obj.collisionGeometry.contains(x)) * obj.collisionGeometry.distance(x); % x is 1x3
% gradient of barrier function
obj.dBarrierFunction = @(x) obj.collisionGeometry.distanceGradient(x); % x is 1x3
% as long as the collisionGeometry object is updated during runtime,
% these functions never have to be updated again
end end

View File

@@ -20,10 +20,6 @@ classdef rectangularPrism
% Plotting % Plotting
lines; lines;
% collision
barrierFunction;
dBarrierFunction;
end end
properties (SetAccess = public, GetAccess = public) properties (SetAccess = public, GetAccess = public)
label = ""; label = "";

View File

@@ -18,11 +18,6 @@ function obj = initialize(obj, center, radius, tag, label)
obj.radius = radius; obj.radius = radius;
obj.diameter = 2 * obj.radius; obj.diameter = 2 * obj.radius;
% Initialize CBF
obj.barrierFunction = @(x) NaN;
% gradient of barrier function
obj.dBarrierFunction = @(x) NaN;
% fake vertices in a cross pattern % fake vertices in a cross pattern
obj.vertices = [obj.center + [obj.radius, 0, 0]; ... obj.vertices = [obj.center + [obj.radius, 0, 0]; ...
obj.center - [obj.radius, 0, 0]; ... obj.center - [obj.radius, 0, 0]; ...

View File

@@ -11,10 +11,6 @@ classdef spherical
% Plotting % Plotting
lines; lines;
% collision
barrierFunction;
dBarrierFunction;
end end
properties (SetAccess = public, GetAccess = public) properties (SetAccess = public, GetAccess = public)
% Meta % Meta

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="@fixedCardinalSensor" type="File"/>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info/>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="objectiveFunctionWrapper.m" type="File"/>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info Ref="sensorModels" Type="Relative"/>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="d143c27d-6824-4569-9093-8150b60976cb" type="Reference"/>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="teardown.m" type="File"/>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="partition.m" type="File"/>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info/>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="sensorModels" type="File"/>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="fixedCardinalSensor.m" type="File"/>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="sense.m" type="File"/>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info/>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="1" type="DIR_SIGNIFIER"/>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info/>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="1" type="DIR_SIGNIFIER"/>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="sensorPerformance.m" type="File"/>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info>
<Category UUID="FileClassCategory">
<Label UUID="design"/>
</Category>
</Info>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info>
<Category UUID="FileClassCategory">
<Label UUID="design"/>
</Category>
</Info>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info>
<Category UUID="FileClassCategory">
<Label UUID="design"/>
</Category>
</Info>

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="initialize.m" type="File"/>

View File

@@ -1,13 +0,0 @@
classdef fixedCardinalSensor
% Senses in the +/-x, +/- y directions at some specified fixed length
properties
alphaTilt = NaN;
r = 0.1; % fixed sensing length
end
methods (Access = public)
[obj] = initialize(obj, r);
[neighborValues, neighborPos] = sense(obj, agent, sensingObjective, domain, partitioning);
[value] = sensorPerformance(obj, agentPos, agentPan, agentTilt, targetPos);
end
end

View File

@@ -1,10 +0,0 @@
function obj = initialize(obj, r)
arguments(Input)
obj (1, 1) {mustBeA(obj, 'fixedCardinalSensor')};
r (1, 1) double;
end
arguments(Output)
obj (1, 1) {mustBeA(obj, 'fixedCardinalSensor')};
end
obj.r = r;
end

View File

@@ -1,45 +0,0 @@
function [neighborValues, neighborPos] = sense(obj, agent, sensingObjective, domain, partitioning)
arguments (Input)
obj (1, 1) {mustBeA(obj, 'fixedCardinalSensor')};
agent (1, 1) {mustBeA(agent, 'agent')};
sensingObjective (1, 1) {mustBeA(sensingObjective, 'sensingObjective')};
domain (1, 1) {mustBeGeometry};
partitioning (:, :) double = NaN;
end
arguments (Output)
neighborValues (4, 1) double;
neighborPos (4, 3) double;
end
% Set alphaTilt to produce an FOV cone with radius 'r' on the ground
obj.alphaTilt = atan2(obj.r, agent.pos(3));
% Evaluate objective at position offsets +/-[r, 0, 0] and +/-[0, r, 0]
currentPos = agent.pos(1:2);
neighborPos = [currentPos(1) + obj.r, currentPos(2); ... % (+x)
currentPos(1), currentPos(2) + obj.r; ... % (+y)
currentPos(1) - obj.r, currentPos(2); ... % (-x)
currentPos(1), currentPos(2) - obj.r; ... % (-y)
];
% Check for neighbor positions that fall outside of the domain
outOfBounds = false(size(neighborPos, 1), 1);
for ii = 1:size(neighborPos, 1)
if ~domain.contains([neighborPos(ii, :), 0])
outOfBounds(ii) = true;
end
end
% Replace out of bounds positions with inoffensive in-bounds positions
neighborPos(outOfBounds, 1:3) = repmat(agent.pos, sum(outOfBounds), 1);
% Sense values at selected positions
neighborValues = [sensingObjective.objectiveFunction(neighborPos(1, 1), neighborPos(1, 2)), ... % (+x)
sensingObjective.objectiveFunction(neighborPos(2, 1), neighborPos(2, 2)), ... % (+y)
sensingObjective.objectiveFunction(neighborPos(3, 1), neighborPos(3, 2)), ... % (-x)
sensingObjective.objectiveFunction(neighborPos(4, 1), neighborPos(4, 2)), ... % (-y)
];
% Prevent out of bounds locations from ever possibly being selected
neighborValues(outOfBounds) = 0;
end

View File

@@ -1,14 +0,0 @@
function value = sensorPerformance(obj, agentPos, agentPan, agentTilt, targetPos)
arguments (Input)
obj (1, 1) {mustBeA(obj, 'fixedCardinalSensor')};
agentPos (1, 3) double;
agentPan (1, 1) double;
agentTilt (1, 1) double;
targetPos (:, 3) double;
end
arguments (Output)
value (:, 1) double;
end
value = 0.5 * ones(size(targetPos, 1), 1);
end

View File

@@ -3,7 +3,6 @@ classdef parametricTestSuite < matlab.unittest.TestCase
% System under test % System under test
testClass = miSim; testClass = miSim;
domain = rectangularPrism; domain = rectangularPrism;
objective = sensingObjective;
obstacles = cell(1, 0); obstacles = cell(1, 0);
%% Diagnostic Parameters %% Diagnostic Parameters
@@ -16,33 +15,52 @@ classdef parametricTestSuite < matlab.unittest.TestCase
end end
properties (TestParameter) properties (TestParameter)
%% Simulation Parameters %% Simulation Parameters
maxIter = num2cell([200, 400]); % number of timesteps to run maxIter = num2cell([25]); % number of timesteps to run
% Domain parameters % Domain parameters
minAlt = num2cell([1, 3]); % minimum allowed agent altitude, make sure test cases don't conflict with this minAlt = num2cell([1]); % minimum allowed agent altitude, make sure test cases don't conflict with this
% Sensing Objective Parameters % Sensing Objective Parameters
discretizationStep = num2cell([0.01, 0.05]); discretizationStep = num2cell([0.01]);
% Agent Parameters % Agent Parameters
collisionRange = num2cell([0.1, 0.5]); collisionRadius = num2cell([0.1]);
% Sensor Model Parameters % Sensor Model Parameters
betaDist = num2cell(3:6:15);
betaTilt = num2cell(3:6:15);
alphaDist = num2cell([2.5, 5]); alphaDist = num2cell([2.5, 5]);
alphaTilt = num2cell([15, 30]); % (degrees) betaDist = num2cell([3, 15]);
alphaTilt = num2cell([15, 30]); % (degrees)methods
betaTilt = num2cell([3, 15]);
% Communications Parameters % Communications Parameters
comRange = num2cell(1:2:5); comRange = num2cell([3]);
end end
methods (Test, ParameterCombination = "exhaustive") methods (Test, ParameterCombination = "exhaustive")
% Test methods % Test cases
function single_agent_gradient_ascent(tc, maxIter, minAlt, discretizationStep, collisionRadius, alphaDist, betaDist, alphaTilt, betaTilt, comRange)
% Set up square domain
l = 10;
tc.domain = tc.domain.initialize([zeros(1, 3); l * ones(1, 3)], REGION_TYPE.DOMAIN, "Domain");
tc.domain.objective = tc.domain.objective.initialize(objectiveFunctionWrapper([.75 * l, 0.75 * l]), tc.domain, discretizationStep, tc.protectedRange);
function single_agent_gradient_ascent(tc, maxIter, minAlt, discretizationStep, collisionRange, alphaDist, alphaTilt, betaDist, betaTilt, comRange) % Set up agent
1; sensorModel = sigmoidSensor;
end sensorModel = sensorModel.initialize(alphaDist, betaDist, alphaTilt, betaTilt);
end agentPos = [l/4, l/4, 3*l/4];
collisionGeometry = spherical;
collisionGeometry = collisionGeometry.initialize(agentPos, collisionRadius, REGION_TYPE.COLLISION, "Agent 1 Collision Region");
agents = {agent};
agents{1} = agents{1}.initialize(agentPos, collisionGeometry, sensorModel, comRange, maxIter, "Agent 1", tc.plotCommsGeometry);
% Set up simulation
tc.testClass = tc.testClass.initialize(tc.domain, agents, minAlt, tc.timestep, maxIter, tc.obstacles, tc.makePlots, tc.makeVideo);
% Run
tc.testClass = tc.testClass.run();
% Cleanup
tc.testClass.teardown();
end
end
end end

View File

@@ -157,10 +157,10 @@ classdef test_miSim < matlab.unittest.TestCase
% Initialize candidate agent sensor model % Initialize candidate agent sensor model
sensor = sigmoidSensor; sensor = sigmoidSensor;
sensor = sensor.initialize(tc.alphaDistMin + rand * (tc.alphaDistMax - tc.alphaDistMin), tc.betaDistMin + rand * (tc.betaDistMax - tc.betaDistMin), NaN, NaN, tc.alphaTiltMin + rand * (tc.alphaTiltMax - tc.alphaTiltMin), tc.betaTiltMin + rand * (tc.betaTiltMax - tc.betaTiltMin)); sensor = sensor.initialize(tc.alphaDistMin + rand * (tc.alphaDistMax - tc.alphaDistMin), tc.betaDistMin + rand * (tc.betaDistMax - tc.betaDistMin), tc.alphaTiltMin + rand * (tc.alphaTiltMax - tc.alphaTiltMin), tc.betaTiltMin + rand * (tc.betaTiltMax - tc.betaTiltMin));
% Initialize candidate agent % Initialize candidate agent
newAgent = tc.agents{ii}.initialize(candidatePos, zeros(1,3), 0, 0, candidateGeometry, sensor, tc.comRange, tc.maxIter); newAgent = tc.agents{ii}.initialize(candidatePos, candidateGeometry, sensor, tc.comRange, tc.maxIter);
% Make sure candidate agent doesn't collide with % Make sure candidate agent doesn't collide with
% domain % domain
@@ -208,7 +208,7 @@ classdef test_miSim < matlab.unittest.TestCase
end end
% Initialize the simulation % Initialize the simulation
tc.testClass = tc.testClass.initialize(tc.domain, tc.domain.objective, tc.agents, tc.minAlt, tc.timestep, tc.maxIter, tc.obstacles, tc.makeVideo); tc.testClass = tc.testClass.initialize(tc.domain, tc.agents, tc.minAlt, tc.timestep, tc.maxIter, tc.obstacles, tc.makeVideo);
end end
function misim_run(tc) function misim_run(tc)
% randomly create obstacles % randomly create obstacles
@@ -291,10 +291,10 @@ classdef test_miSim < matlab.unittest.TestCase
% Initialize candidate agent sensor model % Initialize candidate agent sensor model
sensor = sigmoidSensor; sensor = sigmoidSensor;
sensor = sensor.initialize(tc.alphaDistMin + rand * (tc.alphaDistMax - tc.alphaDistMin), tc.betaDistMin + rand * (tc.betaDistMax - tc.betaDistMin), NaN, NaN, tc.alphaTiltMin + rand * (tc.alphaTiltMax - tc.alphaTiltMin), tc.betaTiltMin + rand * (tc.betaTiltMax - tc.betaTiltMin)); sensor = sensor.initialize(tc.alphaDistMin + rand * (tc.alphaDistMax - tc.alphaDistMin), tc.betaDistMin + rand * (tc.betaDistMax - tc.betaDistMin), tc.alphaTiltMin + rand * (tc.alphaTiltMax - tc.alphaTiltMin), tc.betaTiltMin + rand * (tc.betaTiltMax - tc.betaTiltMin));
% Initialize candidate agent % Initialize candidate agent
newAgent = tc.agents{ii}.initialize(candidatePos, zeros(1,3), 0, 0, candidateGeometry, sensor, tc.comRange, tc.maxIter); newAgent = tc.agents{ii}.initialize(candidatePos, candidateGeometry, sensor, tc.comRange, tc.maxIter);
% Make sure candidate agent doesn't collide with % Make sure candidate agent doesn't collide with
% domain % domain
@@ -342,7 +342,7 @@ classdef test_miSim < matlab.unittest.TestCase
end end
% Initialize the simulation % Initialize the simulation
tc.testClass = tc.testClass.initialize(tc.domain, tc.domain.objective, tc.agents, tc.minAlt, tc.timestep, tc.maxIter, tc.obstacles, tc.makeVideo); tc.testClass = tc.testClass.initialize(tc.domain, tc.agents, tc.minAlt, tc.timestep, tc.maxIter, tc.obstacles, tc.makeVideo);
% Run simulation loop % Run simulation loop
tc.testClass = tc.testClass.run(); tc.testClass = tc.testClass.run();
@@ -367,26 +367,26 @@ classdef test_miSim < matlab.unittest.TestCase
% Initialize agent sensor model % Initialize agent sensor model
sensor = sigmoidSensor; sensor = sigmoidSensor;
% Homogeneous sensor model parameters % Homogeneous sensor model parameters
sensor = sensor.initialize(2.75, 9, NaN, NaN, 22.5, 9); sensor = sensor.initialize(2.75, 9, 22.5, 9);
% Heterogeneous sensor model parameters % Heterogeneous sensor model parameters
% sensor = sensor.initialize(tc.alphaDistMin + rand * (tc.alphaDistMax - tc.alphaDistMin), tc.betaDistMin + rand * (tc.betaDistMax - tc.betaDistMin), NaN, NaN, tc.alphaTiltMin + rand * (tc.alphaTiltMax - tc.alphaTiltMin), tc.betaTiltMin + rand * (tc.betaTiltMax - tc.betaTiltMin)); % sensor = sensor.initialize(tc.alphaDistMin + rand * (tc.alphaDistMax - tc.alphaDistMin), tc.betaDistMin + rand * (tc.betaDistMax - tc.betaDistMin), tc.alphaTiltMin + rand * (tc.alphaTiltMax - tc.alphaTiltMin), tc.betaTiltMin + rand * (tc.betaTiltMax - tc.betaTiltMin));
% Plot sensor parameters (optional) % Plot sensor parameters (optional)
% f = sensor.plotParameters(); % f = sensor.plotParameters();
% Initialize agents % Initialize agents
tc.agents = {agent; agent}; tc.agents = {agent; agent};
tc.agents{1} = tc.agents{1}.initialize(tc.domain.center + dh + [d, 0, 0], zeros(1,3), 0, 0, geometry1, sensor, 3*d, tc.maxIter); tc.agents{1} = tc.agents{1}.initialize(tc.domain.center + dh + [d, 0, 0], geometry1, sensor, 3*d, tc.maxIter);
tc.agents{2} = tc.agents{2}.initialize(tc.domain.center + dh - [d, 0, 0], zeros(1,3), 0, 0, geometry2, sensor, 3*d, tc.maxIter); tc.agents{2} = tc.agents{2}.initialize(tc.domain.center + dh - [d, 0, 0], geometry2, sensor, 3*d, tc.maxIter);
% Optional third agent along the +Y axis % Optional third agent along the +Y axis
geometry3 = rectangularPrism; geometry3 = rectangularPrism;
geometry3 = geometry3.initialize([tc.domain.center + dh - [0, d, 0] - tc.collisionRanges(1) * ones(1, 3); tc.domain.center + dh - [0, d, 0] + tc.collisionRanges(1) * ones(1, 3)], REGION_TYPE.COLLISION); geometry3 = geometry3.initialize([tc.domain.center + dh - [0, d, 0] - tc.collisionRanges(1) * ones(1, 3); tc.domain.center + dh - [0, d, 0] + tc.collisionRanges(1) * ones(1, 3)], REGION_TYPE.COLLISION);
tc.agents{3} = agent; tc.agents{3} = agent;
tc.agents{3} = tc.agents{3}.initialize(tc.domain.center + dh - [0, d, 0], zeros(1, 3), 0, 0, geometry3, sensor, 3*d, tc.maxIter); tc.agents{3} = tc.agents{3}.initialize(tc.domain.center + dh - [0, d, 0], geometry3, sensor, 3*d, tc.maxIter);
% Initialize the simulation % Initialize the simulation
tc.testClass = tc.testClass.initialize(tc.domain, tc.domain.objective, tc.agents, tc.minAlt, tc.timestep, tc.maxIter, cell(0, 1), false, false); tc.testClass = tc.testClass.initialize(tc.domain, tc.agents, tc.minAlt, tc.timestep, tc.maxIter, cell(0, 1), false, false);
tc.verifyEqual(tc.testClass.partitioning(500, 500:502), [2, 3, 1]); % all three near center tc.verifyEqual(tc.testClass.partitioning(500, 500:502), [2, 3, 1]); % all three near center
tc.verifyLessThan(sum(tc.testClass.partitioning == 1, 'all'), sum(tc.testClass.partitioning == 0, 'all')); % more non-assignments than partition 1 assignments tc.verifyLessThan(sum(tc.testClass.partitioning == 1, 'all'), sum(tc.testClass.partitioning == 0, 'all')); % more non-assignments than partition 1 assignments
@@ -409,19 +409,19 @@ classdef test_miSim < matlab.unittest.TestCase
% Initialize agent sensor model % Initialize agent sensor model
sensor = sigmoidSensor; sensor = sigmoidSensor;
% Homogeneous sensor model parameters % Homogeneous sensor model parameters
% sensor = sensor.initialize(2.5666, 5.0807, NaN, NaN, 20.8614, 13); % 13 % sensor = sensor.initialize(2.5666, 5.0807, 20.8614, 13); % 13
alphaDist = l/2; % half of domain length/width alphaDist = l/2; % half of domain length/width
sensor = sensor.initialize(alphaDist, 3, NaN, NaN, 20, 3); sensor = sensor.initialize(alphaDist, 3, 20, 3);
% Plot sensor parameters (optional) % Plot sensor parameters (optional)
% f = sensor.plotParameters(); % f = sensor.plotParameters();
% Initialize agents % Initialize agents
tc.agents = {agent}; tc.agents = {agent};
tc.agents{1} = tc.agents{1}.initialize([tc.domain.center(1:2), 3], zeros(1,3), 0, 0, geometry1, sensor, 3, tc.maxIter); tc.agents{1} = tc.agents{1}.initialize([tc.domain.center(1:2), 3], geometry1, sensor, 3, tc.maxIter);
% Initialize the simulation % Initialize the simulation
tc.testClass = tc.testClass.initialize(tc.domain, tc.domain.objective, tc.agents, tc.minAlt, tc.timestep, tc.maxIter, cell(0, 1), false, false); tc.testClass = tc.testClass.initialize(tc.domain, tc.agents, tc.minAlt, tc.timestep, tc.maxIter, cell(0, 1), false, false);
close(tc.testClass.fPerf); close(tc.testClass.fPerf);
tc.verifyEqual(unique(tc.testClass.partitioning), [0; 1]); tc.verifyEqual(unique(tc.testClass.partitioning), [0; 1]);
@@ -442,9 +442,9 @@ classdef test_miSim < matlab.unittest.TestCase
% Initialize agent sensor model % Initialize agent sensor model
sensor = sigmoidSensor; sensor = sigmoidSensor;
% Homogeneous sensor model parameters % Homogeneous sensor model parameters
% sensor = sensor.initialize(2.5666, 5.0807, NaN, NaN, 20.8614, 13); % 13 % sensor = sensor.initialize(2.5666, 5.0807, 20.8614, 13); % 13
alphaDist = l/2; % half of domain length/width alphaDist = l/2; % half of domain length/width
sensor = sensor.initialize(alphaDist, 3, NaN, NaN, 20, 3); sensor = sensor.initialize(alphaDist, 3, 20, 3);
% Plot sensor parameters (optional) % Plot sensor parameters (optional)
% f = sensor.plotParameters(); % f = sensor.plotParameters();
@@ -452,10 +452,10 @@ classdef test_miSim < matlab.unittest.TestCase
% Initialize agents % Initialize agents
nIter = 100; nIter = 100;
tc.agents = {agent}; tc.agents = {agent};
tc.agents{1} = tc.agents{1}.initialize([tc.domain.center(1:2)-tc.domain.dimensions(1)/4, 3], zeros(1,3), 0, 0, geometry1, sensor, 3, nIter); tc.agents{1} = tc.agents{1}.initialize([tc.domain.center(1:2)-tc.domain.dimensions(1)/4, 3], geometry1, sensor, 3, nIter);
% Initialize the simulation % Initialize the simulation
tc.testClass = tc.testClass.initialize(tc.domain, tc.domain.objective, tc.agents, tc.minAlt, tc.timestep, nIter, cell(0, 1)); tc.testClass = tc.testClass.initialize(tc.domain, tc.agents, tc.minAlt, tc.timestep, nIter, cell(0, 1));
% Run the simulation % Run the simulation
tc.testClass = tc.testClass.run(); tc.testClass = tc.testClass.run();
@@ -484,18 +484,18 @@ classdef test_miSim < matlab.unittest.TestCase
% Initialize agent sensor model % Initialize agent sensor model
sensor = sigmoidSensor; sensor = sigmoidSensor;
% Homogeneous sensor model parameters % Homogeneous sensor model parameters
% sensor = sensor.initialize(2.5666, 5.0807, NaN, NaN, 20.8614, 13); % 13 % sensor = sensor.initialize(2.5666, 5.0807, 20.8614, 13); % 13
alphaDist = l/2; % half of domain length/width alphaDist = l/2; % half of domain length/width
sensor = sensor.initialize(alphaDist, 3, NaN, NaN, 15, 3); sensor = sensor.initialize(alphaDist, 3, 15, 3);
% Initialize agents % Initialize agents
nIter = 50; nIter = 50;
tc.agents = {agent; agent}; tc.agents = {agent; agent};
tc.agents{1} = tc.agents{1}.initialize(tc.domain.center + d, zeros(1,3), 0, 0, geometry1, sensor, 5, nIter); tc.agents{1} = tc.agents{1}.initialize(tc.domain.center + d, geometry1, sensor, 5, nIter);
tc.agents{2} = tc.agents{2}.initialize(tc.domain.center - d, zeros(1,3), 0, 0, geometry2, sensor, 5, nIter); tc.agents{2} = tc.agents{2}.initialize(tc.domain.center - d, geometry2, sensor, 5, nIter);
% Initialize the simulation % Initialize the simulation
tc.testClass = tc.testClass.initialize(tc.domain, tc.domain.objective, tc.agents, tc.minAlt, tc.timestep, nIter, cell(0, 1), tc.makeVideo, tc.makePlots); tc.testClass = tc.testClass.initialize(tc.domain, tc.agents, tc.minAlt, tc.timestep, nIter, cell(0, 1), tc.makeVideo, tc.makePlots);
% Run the simulation % Run the simulation
tc.testClass.run(); tc.testClass.run();
@@ -529,7 +529,7 @@ classdef test_miSim < matlab.unittest.TestCase
% Initialize agent sensor model % Initialize agent sensor model
sensor = sigmoidSensor; sensor = sigmoidSensor;
alphaDist = l/2; % half of domain length/width alphaDist = l/2; % half of domain length/width
sensor = sensor.initialize(alphaDist, 3, NaN, NaN, 15, 3); sensor = sensor.initialize(alphaDist, 3, 15, 3);
% Initialize obstacles % Initialize obstacles
obstacleLength = 1; obstacleLength = 1;
@@ -539,11 +539,10 @@ classdef test_miSim < matlab.unittest.TestCase
% Initialize agents % Initialize agents
commsRadius = (2*radius + obstacleLength) * 0.9; % defined such that they cannot go around the obstacle on both sides commsRadius = (2*radius + obstacleLength) * 0.9; % defined such that they cannot go around the obstacle on both sides
tc.agents = {agent; agent;}; tc.agents = {agent; agent;};
tc.agents{1} = tc.agents{1}.initialize(tc.domain.center - d + [0, radius * 1.1 - yOffset, 0], zeros(1,3), 0, 0, geometry1, sensor, commsRadius, tc.maxIter); tc.agents{1} = tc.agents{1}.initialize(tc.domain.center - d + [0, radius * 1.1 - yOffset, 0], geometry1, sensor, commsRadius, tc.maxIter);
tc.agents{2} = tc.agents{2}.initialize(tc.domain.center - d - [0, radius *1.1 + yOffset, 0], zeros(1,3), 0, 0, geometry2, sensor, commsRadius, tc.maxIter); tc.agents{2} = tc.agents{2}.initialize(tc.domain.center - d - [0, radius *1.1 + yOffset, 0], geometry2, sensor, commsRadius, tc.maxIter);
% Initialize the simulation % Initialize the simulation
tc.testClass = tc.testClass.initialize(tc.domain, tc.domain.objective, tc.agents, tc.minAlt, tc.timestep, tc.maxIter, tc.obstacles, tc.makeVideo); tc.testClass = tc.testClass.initialize(tc.domain, tc.agents, tc.minAlt, tc.timestep, tc.maxIter, tc.obstacles, tc.makeVideo);
% Run the simulation % Run the simulation
tc.testClass.run(); tc.testClass.run();
@@ -571,7 +570,7 @@ classdef test_miSim < matlab.unittest.TestCase
% Initialize agent sensor model % Initialize agent sensor model
sensor = sigmoidSensor; sensor = sigmoidSensor;
alphaDist = l/2; % half of domain length/width alphaDist = l/2; % half of domain length/width
sensor = sensor.initialize(alphaDist, 3, NaN, NaN, 15, 3); sensor = sensor.initialize(alphaDist, 3, 15, 3);
% Initialize obstacles % Initialize obstacles
tc.obstacles = {}; tc.obstacles = {};
@@ -580,11 +579,11 @@ classdef test_miSim < matlab.unittest.TestCase
nIter = 75; nIter = 75;
commsRadius = 4; % defined such that they cannot reach their objective without breaking connectivity commsRadius = 4; % defined such that they cannot reach their objective without breaking connectivity
tc.agents = {agent; agent;}; tc.agents = {agent; agent;};
tc.agents{1} = tc.agents{1}.initialize(dom.center + d, zeros(1,3), 0, 0, geometry1, sensor, commsRadius, nIter); tc.agents{1} = tc.agents{1}.initialize(dom.center + d, geometry1, sensor, commsRadius, nIter);
tc.agents{2} = tc.agents{2}.initialize(dom.center - d, zeros(1,3), 0, 0, geometry2, sensor, commsRadius, nIter); tc.agents{2} = tc.agents{2}.initialize(dom.center - d, geometry2, sensor, commsRadius, nIter);
% Initialize the simulation % Initialize the simulation
tc.testClass = tc.testClass.initialize(dom, dom.objective, tc.agents, tc.minAlt, tc.timestep, nIter, tc.obstacles, true, false); tc.testClass = tc.testClass.initialize(dom, tc.agents, tc.minAlt, tc.timestep, nIter, tc.obstacles, true, false);
% Run the simulation % Run the simulation
tc.testClass = tc.testClass.run(); tc.testClass = tc.testClass.run();
@@ -611,14 +610,14 @@ classdef test_miSim < matlab.unittest.TestCase
% Initialize agent sensor model % Initialize agent sensor model
sensor = sigmoidSensor; sensor = sigmoidSensor;
alphaDist = l/2; % half of domain length/width alphaDist = l/2; % half of domain length/width
sensor = sensor.initialize(alphaDist, 3, NaN, NaN, 15, 3); sensor = sensor.initialize(alphaDist, 3, 15, 3);
% Initialize agents % Initialize agents
nIter = 125; nIter = 125;
commsRadius = 5; commsRadius = 5;
tc.agents = {agent; agent;}; tc.agents = {agent; agent;};
tc.agents{1} = tc.agents{1}.initialize(tc.domain.center - [d, 0, 0], zeros(1,3), 0, 0, geometry1, sensor, commsRadius, nIter); tc.agents{1} = tc.agents{1}.initialize(tc.domain.center - [d, 0, 0], geometry1, sensor, commsRadius, nIter);
tc.agents{2} = tc.agents{2}.initialize(tc.domain.center - [0, d, 0], zeros(1,3), 0, 0, geometry2, sensor, commsRadius, nIter); tc.agents{2} = tc.agents{2}.initialize(tc.domain.center - [0, d, 0], geometry2, sensor, commsRadius, nIter);
% Initialize obstacles % Initialize obstacles
obstacleLength = 1.5; obstacleLength = 1.5;
@@ -626,7 +625,7 @@ classdef test_miSim < matlab.unittest.TestCase
tc.obstacles{1} = tc.obstacles{1}.initialize([tc.domain.center(1:2) - obstacleLength, 0; tc.domain.center(1:2) + obstacleLength, tc.domain.maxCorner(3)], REGION_TYPE.OBSTACLE, "Obstacle 1"); tc.obstacles{1} = tc.obstacles{1}.initialize([tc.domain.center(1:2) - obstacleLength, 0; tc.domain.center(1:2) + obstacleLength, tc.domain.maxCorner(3)], REGION_TYPE.OBSTACLE, "Obstacle 1");
% Initialize the simulation % Initialize the simulation
tc.testClass = tc.testClass.initialize(tc.domain, tc.domain.objective, tc.agents, 0, tc.timestep, nIter, tc.obstacles, false, false); tc.testClass = tc.testClass.initialize(tc.domain, tc.agents, 0, tc.timestep, nIter, tc.obstacles, false, false);
% No communications link should be established % No communications link should be established
tc.assertEqual(tc.testClass.adjacency, logical(true(2))); tc.assertEqual(tc.testClass.adjacency, logical(true(2)));
@@ -657,20 +656,20 @@ classdef test_miSim < matlab.unittest.TestCase
% Initialize agent sensor model % Initialize agent sensor model
sensor = sigmoidSensor; sensor = sigmoidSensor;
alphaDist = l/2; % half of domain length/width alphaDist = l/2; % half of domain length/width
sensor = sensor.initialize(alphaDist, 3, NaN, NaN, 15, 3); sensor = sensor.initialize(alphaDist, 3, 15, 3);
% Initialize agents % Initialize agents
nIter = 125; nIter = 125;
commsRadius = d; commsRadius = d;
tc.agents = {agent; agent; agent; agent; agent;}; tc.agents = {agent; agent; agent; agent; agent;};
tc.agents{1} = tc.agents{1}.initialize(tc.domain.center + [d, 0, 0], zeros(1,3), 0, 0, geometry1, sensor, commsRadius, nIter); tc.agents{1} = tc.agents{1}.initialize(tc.domain.center + [d, 0, 0], geometry1, sensor, commsRadius, nIter);
tc.agents{2} = tc.agents{2}.initialize(tc.domain.center, zeros(1,3), 0, 0, geometry2, sensor, commsRadius, nIter); tc.agents{2} = tc.agents{2}.initialize(tc.domain.center, 0, 0, geometry2, sensor, commsRadius, nIter);
tc.agents{3} = tc.agents{3}.initialize(tc.domain.center + [-d, d, 0], zeros(1,3), 0, 0, geometry3, sensor, commsRadius, nIter); tc.agents{3} = tc.agents{3}.initialize(tc.domain.center + [-d, d, 0], geometry3, sensor, commsRadius, nIter);
tc.agents{4} = tc.agents{4}.initialize(tc.domain.center + [-2*d, d, 0], zeros(1,3), 0, 0, geometry4, sensor, commsRadius, nIter); tc.agents{4} = tc.agents{4}.initialize(tc.domain.center + [-2*d, d, 0], geometry4, sensor, commsRadius, nIter);
tc.agents{5} = tc.agents{5}.initialize(tc.domain.center + [0, d, 0], zeros(1,3), 0, 0, geometry5, sensor, commsRadius, nIter); tc.agents{5} = tc.agents{5}.initialize(tc.domain.center + [0, d, 0], geometry5, sensor, commsRadius, nIter);
% Initialize the simulation % Initialize the simulation
tc.testClass = tc.testClass.initialize(tc.domain, tc.domain.objective, tc.agents, 0, tc.timestep, nIter, tc.obstacles, false, false); tc.testClass = tc.testClass.initialize(tc.domain, tc.agents, 0, tc.timestep, nIter, tc.obstacles, false, false);
% Constraint adjacency matrix defined by LNA should be as follows % Constraint adjacency matrix defined by LNA should be as follows
tc.assertEqual(tc.testClass.constraintAdjacencyMatrix, logical( ... tc.assertEqual(tc.testClass.constraintAdjacencyMatrix, logical( ...
@@ -708,22 +707,22 @@ classdef test_miSim < matlab.unittest.TestCase
% Initialize agent sensor model % Initialize agent sensor model
sensor = sigmoidSensor; sensor = sigmoidSensor;
alphaDist = l/2; % half of domain length/width alphaDist = l/2; % half of domain length/width
sensor = sensor.initialize(alphaDist, 3, NaN, NaN, 15, 3); sensor = sensor.initialize(alphaDist, 3, 15, 3);
% Initialize agents % Initialize agents
nIter = 125; nIter = 125;
commsRadius = d; commsRadius = d;
tc.agents = {agent; agent; agent; agent; agent; agent; agent;}; tc.agents = {agent; agent; agent; agent; agent; agent; agent;};
tc.agents{1} = tc.agents{1}.initialize(tc.domain.center + [-0.9 * d/sqrt(2), 0.9 * d/sqrt(2), 0], zeros(1,3), 0, 0, geometry1, sensor, commsRadius, nIter); tc.agents{1} = tc.agents{1}.initialize(tc.domain.center + [-0.9 * d/sqrt(2), 0.9 * d/sqrt(2), 0], geometry1, sensor, commsRadius, nIter);
tc.agents{2} = tc.agents{2}.initialize(tc.domain.center + [-0.5 * d, 0.25 * d, 0], zeros(1,3), 0, 0, geometry2, sensor, commsRadius, nIter); tc.agents{2} = tc.agents{2}.initialize(tc.domain.center + [-0.5 * d, 0.25 * d, 0], geometry2, sensor, commsRadius, nIter);
tc.agents{3} = tc.agents{3}.initialize(tc.domain.center + [0.9 * d, 0, 0], zeros(1,3), 0, 0, geometry3, sensor, commsRadius, nIter); tc.agents{3} = tc.agents{3}.initialize(tc.domain.center + [0.9 * d, 0, 0], geometry3, sensor, commsRadius, nIter);
tc.agents{4} = tc.agents{4}.initialize(tc.domain.center + [0.9 * d/sqrt(2), -0.9 * d/sqrt(2), 0], zeros(1,3), 0, 0, geometry4, sensor, commsRadius, nIter); tc.agents{4} = tc.agents{4}.initialize(tc.domain.center + [0.9 * d/sqrt(2), -0.9 * d/sqrt(2), 0], geometry4, sensor, commsRadius, nIter);
tc.agents{5} = tc.agents{5}.initialize(tc.domain.center + [0, 0.9 * d, 0], zeros(1,3), 0, 0, geometry5, sensor, commsRadius, nIter); tc.agents{5} = tc.agents{5}.initialize(tc.domain.center + [0, 0.9 * d, 0], geometry5, sensor, commsRadius, nIter);
tc.agents{6} = tc.agents{6}.initialize(tc.domain.center, zeros(1,3), 0, 0, geometry6, sensor, commsRadius, nIter); tc.agents{6} = tc.agents{6}.initialize(tc.domain.center, geometry6, sensor, commsRadius, nIter);
tc.agents{7} = tc.agents{7}.initialize(tc.domain.center + [d/2, d/2, 0], zeros(1,3), 0, 0, geometry7, sensor, commsRadius, nIter); tc.agents{7} = tc.agents{7}.initialize(tc.domain.center + [d/2, d/2, 0], geometry7, sensor, commsRadius, nIter);
% Initialize the simulation % Initialize the simulation
tc.testClass = tc.testClass.initialize(tc.domain, tc.domain.objective, tc.agents, 0, tc.timestep, nIter, tc.obstacles, false, false); tc.testClass = tc.testClass.initialize(tc.domain, tc.agents, 0, tc.timestep, nIter, tc.obstacles, false, false);
% Constraint adjacency matrix defined by LNA should be as follows % Constraint adjacency matrix defined by LNA should be as follows
tc.assertEqual(tc.testClass.constraintAdjacencyMatrix, logical( ... tc.assertEqual(tc.testClass.constraintAdjacencyMatrix, logical( ...

View File

@@ -21,7 +21,7 @@ classdef test_sigmoidSensor < matlab.unittest.TestCase
function tc = setup(tc) function tc = setup(tc)
% Reinitialize sensor with random parameters % Reinitialize sensor with random parameters
tc.testClass = sigmoidSensor; tc.testClass = sigmoidSensor;
tc.testClass = tc.testClass.initialize(tc.alphaDistMin + rand * (tc.alphaDistMax - tc.alphaDistMin), tc.betaDistMin + rand * (tc.betaDistMax - tc.betaDistMin), NaN, NaN, tc.alphaTiltMin + rand * (tc.alphaTiltMax - tc.alphaTiltMin), tc.betaTiltMin + rand * (tc.betaTiltMax - tc.betaTiltMin)); tc.testClass = tc.testClass.initialize(tc.alphaDistMin + rand * (tc.alphaDistMax - tc.alphaDistMin), tc.betaDistMin + rand * (tc.betaDistMax - tc.betaDistMin), tc.alphaTiltMin + rand * (tc.alphaTiltMax - tc.alphaTiltMin), tc.betaTiltMin + rand * (tc.betaTiltMax - tc.betaTiltMin));
end end
end end
@@ -34,28 +34,28 @@ classdef test_sigmoidSensor < matlab.unittest.TestCase
alphaTilt = 15; % degrees alphaTilt = 15; % degrees
betaTilt = 3; betaTilt = 3;
h = 1e-6; h = 1e-6;
tc.testClass = tc.testClass.initialize(alphaDist, betaDist, NaN, NaN, alphaTilt, betaTilt); tc.testClass = tc.testClass.initialize(alphaDist, betaDist, alphaTilt, betaTilt);
% Plot (optional) % Plot (optional)
% tc.testClass.plotParameters(); % tc.testClass.plotParameters();
% Anticipate perfect performance for a point directly below and % Anticipate perfect performance for a point directly below and
% extremely close % extremely close
tc.verifyEqual(tc.testClass.sensorPerformance([0, 0, h], NaN, 0, [0, 0, 0]), 1, 'RelTol', 1e-3); tc.verifyEqual(tc.testClass.sensorPerformance([0, 0, h], 0, [0, 0, 0]), 1, 'RelTol', 1e-3);
% It looks like mu_t can max out at really low values like 0.37 % It looks like mu_t can max out at really low values like 0.37
% when alphaTilt and betaTilt are small, which seems wrong % when alphaTilt and betaTilt are small, which seems wrong
% Performance at nadir point, distance alphaDist should be 1/2 exactly % Performance at nadir point, distance alphaDist should be 1/2 exactly
tc.verifyEqual(tc.testClass.sensorPerformance([0, 0, alphaDist], NaN, 0, [0, 0, 0]), 1/2); tc.verifyEqual(tc.testClass.sensorPerformance([0, 0, alphaDist], 0, [0, 0, 0]), 1/2);
% Performance at (almost) 0 distance, alphaTilt should be 1/2 % Performance at (almost) 0 distance, alphaTilt should be 1/2
tc.verifyEqual(tc.testClass.sensorPerformance([0, 0, h], NaN, 0, [tand(alphaTilt)*h, 0, 0]), 1/2, 'RelTol', 1e-3); tc.verifyEqual(tc.testClass.sensorPerformance([0, 0, h], 0, [tand(alphaTilt)*h, 0, 0]), 1/2, 'RelTol', 1e-3);
% Performance at great distance should be 0 % Performance at great distance should be 0
tc.verifyEqual(tc.testClass.sensorPerformance([0, 0, 10], NaN, 0, [0, 0, 0]), 0, 'AbsTol', 1e-9); tc.verifyEqual(tc.testClass.sensorPerformance([0, 0, 10], 0, [0, 0, 0]), 0, 'AbsTol', 1e-9);
% Performance at great tilt should be 0 % Performance at great tilt should be 0
tc.verifyEqual(tc.testClass.sensorPerformance([0, 0, h], NaN, 0, [5, 5, 0]), 0, 'AbsTol', 1e-9); tc.verifyEqual(tc.testClass.sensorPerformance([0, 0, h], 0, [5, 5, 0]), 0, 'AbsTol', 1e-9);
end end
end end

View File

@@ -0,0 +1,13 @@
function f = objectiveFunctionWrapper(center)
% Convenience function to generate MVNPDFs at a point
% Makes it look a lot neater to instantiate and sum these to make
% composite objectives in particular
arguments (Input)
center (1, 2) double;
end
arguments (Output)
f (1, 1) {mustBeA(f, 'function_handle')};
end
f = @(x, y) mvnpdf([x(:), y(:)], center);
end