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
lastPos = NaN(1, 3); % position from previous timestep
pos = NaN(1, 3); % current position
vel = NaN(1, 3); % current velocity
pan = NaN; % pan angle
tilt = NaN; % tilt angle
% Collision
collisionGeometry;
barrierFunction;
dBarrierFunction;
% FOV cone
fovGeometry;
@@ -39,7 +34,7 @@ classdef agent
end
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);
[partitioning] = partition(obj, agents, objective)
[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)
obj (1, 1) {mustBeA(obj, 'agent')};
pos (1, 3) double;
vel (1, 3) double;
pan (1, 1) double;
tilt (1, 1) double;
collisionGeometry (1, 1) {mustBeGeometry};
sensorModel (1, 1) {mustBeSensor};
comRange (1, 1) double;
@@ -17,9 +14,6 @@ function obj = initialize(obj, pos, vel, pan, tilt, collisionGeometry, sensorMod
end
obj.pos = pos;
obj.vel = vel;
obj.pan = pan;
obj.tilt = tilt;
obj.collisionGeometry = collisionGeometry;
obj.sensorModel = sensorModel;
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
% 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 = cat(3, agentPerformances{:});

View File

@@ -13,6 +13,10 @@ function obj = run(obj, domain, partitioning, timestepIndex, index, agents)
% Collect objective function values across partition
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
% Compute sensor performance on partition
@@ -30,7 +34,7 @@ function obj = run(obj, domain, partitioning, timestepIndex, index, agents)
% Compute performance values on partition
if ii < 5
% 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.
% Those values are computed once before the loop and are only
% 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
maskedX = domain.objective.X(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
% Rearrange data into image arrays

View File

@@ -5,6 +5,13 @@ function updatePlots(obj)
arguments (Output)
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
for ii = 1:size(obj.scatterPoints, 1)
obj.scatterPoints(ii).XData = obj.pos(1);
@@ -12,9 +19,6 @@ function updatePlots(obj)
obj.scatterPoints(ii).ZData = obj.pos(3);
end
% Find change in agent position since last timestep
deltaPos = obj.pos - obj.lastPos;
% Collision geometry edges
for jj = 1:size(obj.collisionGeometry.lines, 2)
% Update plotting

View File

@@ -14,6 +14,11 @@ function [obj] = constrainMotion(obj)
agents = [obj.agents{:}];
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
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)
obj (1, 1) {mustBeA(obj, 'miSim')};
domain (1, 1) {mustBeGeometry};
objective (1, 1) {mustBeA(objective, 'sensingObjective')};
agents (:, 1) cell;
minAlt (1, 1) double = 1;
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");
end
% Define objective
obj.objective = objective;
% Define agents
obj.agents = agents;
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)];
% 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
obj.partitioning = obj.agents{1}.partition(obj.agents, obj.domain.objective);

View File

@@ -55,7 +55,7 @@ classdef miSim
end
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] = lesserNeighbor(obj);
[obj] = constrainMotion(obj);
@@ -69,6 +69,7 @@ classdef miSim
[obj] = plotH(obj);
[obj] = updatePlots(obj);
validate(obj);
teardown(obj);
end
methods (Access = private)
[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)
obj (1, 1) {mustBeA(obj, 'sigmoidSensor')}
alphaDist (1, 1) double;
betaDist (1, 1) double;
alphaPan (1, 1) double;
betaPan (1, 1) double;
alphaTilt (1, 1) double;
betaTilt (1, 1) double;
end
@@ -14,8 +12,6 @@ function obj = initialize(obj, alphaDist, betaDist, alphaPan, betaPan, alphaTilt
obj.alphaDist = alphaDist;
obj.betaDist = betaDist;
obj.alphaPan = alphaPan;
obj.betaPan = betaPan;
obj.alphaTilt = alphaTilt;
obj.betaTilt = betaTilt;
end

View File

@@ -1,9 +1,7 @@
function value = sensorPerformance(obj, agentPos, agentPan, agentTilt, targetPos)
function value = sensorPerformance(obj, agentPos, targetPos)
arguments (Input)
obj (1, 1) {mustBeA(obj, 'sigmoidSensor')};
agentPos (1, 3) double;
agentPan (1, 1) double;
agentTilt (1, 1) double;
targetPos (:, 3) double;
end
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)
% compute tilt angle
tiltAngle = (180 - atan2d(x, targetPos(:, 3) - agentPos(3))) - agentTilt; % degrees
tiltAngle = (180 - atan2d(x, targetPos(:, 3) - agentPos(3))); % degrees
% Membership functions
mu_d = obj.distanceMembership(d);

View File

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

View File

@@ -48,13 +48,4 @@ function obj = initialize(obj, bounds, tag, label, objectiveFunction, discretiza
if tag == REGION_TYPE.DOMAIN
obj.objective = sensingObjective;
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

View File

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

View File

@@ -18,11 +18,6 @@ function obj = initialize(obj, center, radius, tag, label)
obj.radius = 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
obj.vertices = [obj.center + [obj.radius, 0, 0]; ...
obj.center - [obj.radius, 0, 0]; ...

View File

@@ -11,10 +11,6 @@ classdef spherical
% Plotting
lines;
% collision
barrierFunction;
dBarrierFunction;
end
properties (SetAccess = public, GetAccess = public)
% 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
testClass = miSim;
domain = rectangularPrism;
objective = sensingObjective;
obstacles = cell(1, 0);
%% Diagnostic Parameters
@@ -16,33 +15,52 @@ classdef parametricTestSuite < matlab.unittest.TestCase
end
properties (TestParameter)
%% Simulation Parameters
maxIter = num2cell([200, 400]); % number of timesteps to run
maxIter = num2cell([25]); % number of timesteps to run
% 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
discretizationStep = num2cell([0.01, 0.05]);
discretizationStep = num2cell([0.01]);
% Agent Parameters
collisionRange = num2cell([0.1, 0.5]);
collisionRadius = num2cell([0.1]);
% Sensor Model Parameters
betaDist = num2cell(3:6:15);
betaTilt = num2cell(3:6:15);
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
comRange = num2cell(1:2:5);
comRange = num2cell([3]);
end
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)
1;
end
end
% Set up agent
sensorModel = sigmoidSensor;
sensorModel = sensorModel.initialize(alphaDist, betaDist, alphaTilt, betaTilt);
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

View File

@@ -157,10 +157,10 @@ classdef test_miSim < matlab.unittest.TestCase
% Initialize candidate agent sensor model
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
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
% domain
@@ -208,7 +208,7 @@ classdef test_miSim < matlab.unittest.TestCase
end
% 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
function misim_run(tc)
% randomly create obstacles
@@ -291,10 +291,10 @@ classdef test_miSim < matlab.unittest.TestCase
% Initialize candidate agent sensor model
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
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
% domain
@@ -342,7 +342,7 @@ classdef test_miSim < matlab.unittest.TestCase
end
% 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
tc.testClass = tc.testClass.run();
@@ -367,26 +367,26 @@ classdef test_miSim < matlab.unittest.TestCase
% Initialize agent sensor model
sensor = sigmoidSensor;
% 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
% 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)
% f = sensor.plotParameters();
% Initialize agents
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{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{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], geometry2, sensor, 3*d, tc.maxIter);
% Optional third agent along the +Y axis
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);
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
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.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
sensor = sigmoidSensor;
% 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
sensor = sensor.initialize(alphaDist, 3, NaN, NaN, 20, 3);
sensor = sensor.initialize(alphaDist, 3, 20, 3);
% Plot sensor parameters (optional)
% f = sensor.plotParameters();
% Initialize agents
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
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);
tc.verifyEqual(unique(tc.testClass.partitioning), [0; 1]);
@@ -442,9 +442,9 @@ classdef test_miSim < matlab.unittest.TestCase
% Initialize agent sensor model
sensor = sigmoidSensor;
% 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
sensor = sensor.initialize(alphaDist, 3, NaN, NaN, 20, 3);
sensor = sensor.initialize(alphaDist, 3, 20, 3);
% Plot sensor parameters (optional)
% f = sensor.plotParameters();
@@ -452,10 +452,10 @@ classdef test_miSim < matlab.unittest.TestCase
% Initialize agents
nIter = 100;
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
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
tc.testClass = tc.testClass.run();
@@ -484,18 +484,18 @@ classdef test_miSim < matlab.unittest.TestCase
% Initialize agent sensor model
sensor = sigmoidSensor;
% 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
sensor = sensor.initialize(alphaDist, 3, NaN, NaN, 15, 3);
sensor = sensor.initialize(alphaDist, 3, 15, 3);
% Initialize agents
nIter = 50;
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{2} = tc.agents{2}.initialize(tc.domain.center - d, zeros(1,3), 0, 0, geometry2, 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, geometry2, sensor, 5, nIter);
% 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
tc.testClass.run();
@@ -529,7 +529,7 @@ classdef test_miSim < matlab.unittest.TestCase
% Initialize agent sensor model
sensor = sigmoidSensor;
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
obstacleLength = 1;
@@ -539,11 +539,10 @@ classdef test_miSim < matlab.unittest.TestCase
% Initialize agents
commsRadius = (2*radius + obstacleLength) * 0.9; % defined such that they cannot go around the obstacle on both sides
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{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{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], geometry2, sensor, commsRadius, tc.maxIter);
% 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
tc.testClass.run();
@@ -571,7 +570,7 @@ classdef test_miSim < matlab.unittest.TestCase
% Initialize agent sensor model
sensor = sigmoidSensor;
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
tc.obstacles = {};
@@ -580,11 +579,11 @@ classdef test_miSim < matlab.unittest.TestCase
nIter = 75;
commsRadius = 4; % defined such that they cannot reach their objective without breaking connectivity
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{2} = tc.agents{2}.initialize(dom.center - d, zeros(1,3), 0, 0, geometry2, 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, geometry2, sensor, commsRadius, nIter);
% 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
tc.testClass = tc.testClass.run();
@@ -611,14 +610,14 @@ classdef test_miSim < matlab.unittest.TestCase
% Initialize agent sensor model
sensor = sigmoidSensor;
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
nIter = 125;
commsRadius = 5;
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{2} = tc.agents{2}.initialize(tc.domain.center - [0, d, 0], zeros(1,3), 0, 0, geometry2, 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], geometry2, sensor, commsRadius, nIter);
% Initialize obstacles
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");
% 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
tc.assertEqual(tc.testClass.adjacency, logical(true(2)));
@@ -657,20 +656,20 @@ classdef test_miSim < matlab.unittest.TestCase
% Initialize agent sensor model
sensor = sigmoidSensor;
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
nIter = 125;
commsRadius = d;
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{2} = tc.agents{2}.initialize(tc.domain.center, zeros(1,3), 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{4} = tc.agents{4}.initialize(tc.domain.center + [-2*d, d, 0], zeros(1,3), 0, 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{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, 0, geometry2, 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], geometry4, sensor, commsRadius, nIter);
tc.agents{5} = tc.agents{5}.initialize(tc.domain.center + [0, d, 0], geometry5, sensor, commsRadius, nIter);
% 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
tc.assertEqual(tc.testClass.constraintAdjacencyMatrix, logical( ...
@@ -708,22 +707,22 @@ classdef test_miSim < matlab.unittest.TestCase
% Initialize agent sensor model
sensor = sigmoidSensor;
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
nIter = 125;
commsRadius = d;
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{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{3} = tc.agents{3}.initialize(tc.domain.center + [0.9 * d, 0, 0], zeros(1,3), 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{5} = tc.agents{5}.initialize(tc.domain.center + [0, 0.9 * d, 0], zeros(1,3), 0, 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{7} = tc.agents{7}.initialize(tc.domain.center + [d/2, d/2, 0], zeros(1,3), 0, 0, geometry7, 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], geometry2, 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], geometry4, 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, geometry6, 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
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
tc.assertEqual(tc.testClass.constraintAdjacencyMatrix, logical( ...

View File

@@ -21,7 +21,7 @@ classdef test_sigmoidSensor < matlab.unittest.TestCase
function tc = setup(tc)
% Reinitialize sensor with random parameters
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
@@ -34,28 +34,28 @@ classdef test_sigmoidSensor < matlab.unittest.TestCase
alphaTilt = 15; % degrees
betaTilt = 3;
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)
% tc.testClass.plotParameters();
% Anticipate perfect performance for a point directly below and
% 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
% when alphaTilt and betaTilt are small, which seems wrong
% 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
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
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
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

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