diff --git a/@miSim/initialize.m b/@miSim/initialize.m index 1669885..4f93527 100644 --- a/@miSim/initialize.m +++ b/@miSim/initialize.m @@ -1,4 +1,4 @@ -function [obj, f] = initialize(obj, domain, objective, agents, timestep, partitoningFreq, maxIter, obstacles) +function obj = initialize(obj, domain, objective, agents, timestep, partitoningFreq, maxIter, obstacles) arguments (Input) obj (1, 1) {mustBeA(obj, 'miSim')}; domain (1, 1) {mustBeGeometry}; @@ -11,7 +11,6 @@ function [obj, f] = initialize(obj, domain, objective, agents, timestep, partito end arguments (Output) obj (1, 1) {mustBeA(obj, 'miSim')}; - f (1, 1) {mustBeA(f, 'matlab.ui.Figure')}; end % Define simulation time parameters @@ -38,5 +37,5 @@ function [obj, f] = initialize(obj, domain, objective, agents, timestep, partito obj = obj.partition(); % Set up plots showing initialized state - [obj, f] = obj.plot(); + obj = obj.plot(); end \ No newline at end of file diff --git a/@miSim/miSim.m b/@miSim/miSim.m index dc5387e..29bef49 100644 --- a/@miSim/miSim.m +++ b/@miSim/miSim.m @@ -13,14 +13,19 @@ classdef miSim adjacency = NaN; % Adjacency matrix representing communications network graph sensorPerformanceMinimum = 1e-6; % minimum sensor performance to allow assignment of a point in the domain to a partition partitioning = NaN; + performance = NaN; % current cumulative sensor performance end properties (Access = private) % Plot objects + f = firstPlotSetup(); % main plotting tiled layout figure connectionsPlot; % objects for lines connecting agents in spatial plots graphPlot; % objects for abstract network graph plot partitionPlot; % objects for partition plot + fPerf = figure; % performance plot figure + performancePlot; % objects for sensor performance plot + % Indicies for various plot types in the main tiled layout figure spatialPlotIndices = [6, 4, 3, 2]; objectivePlotIndices = [6, 4]; @@ -29,15 +34,15 @@ classdef miSim end methods (Access = public) - [obj, f] = initialize(obj, domain, objective, agents, timestep, partitoningFreq, maxIter, obstacles); - [obj, f] = run(obj, f); - [obj] = partition(obj); - [obj] = updateAdjacency(obj); - [obj, f] = plot(obj); - [obj, f] = plotConnections(obj, ind, f); - [obj, f] = plotPartitions(obj, ind, f); - [obj, f] = plotGraph(obj, ind, f); - [obj, f] = updatePlots(obj, f, updatePartitions); + [obj] = initialize(obj, domain, objective, agents, timestep, partitoningFreq, maxIter, obstacles); + [obj] = run(obj); + [obj] = partition(obj); + [obj] = updateAdjacency(obj); + [obj] = plot(obj); + [obj] = plotConnections(obj); + [obj] = plotPartitions(obj); + [obj] = plotGraph(obj); + [obj] = updatePlots(obj, updatePartitions); end methods (Access = private) [v] = setupVideoWriter(obj); diff --git a/@miSim/partition.m b/@miSim/partition.m index 6a2ac30..44782f9 100644 --- a/@miSim/partition.m +++ b/@miSim/partition.m @@ -15,6 +15,9 @@ function obj = partition(obj) % Get highest performance value at each point [~, idx] = max(agentPerformances, [], 3); + % Current total performance + obj.performance = sum(max(agentPerformances(:, :, 1:(end - 1)), [], 3), 'all'); + % Collect agent indices in the same way agentInds = cellfun(@(x) x.index * ones(size(obj.objective.X)), obj.agents, 'UniformOutput', false); agentInds{end + 1} = zeros(size(agentInds{end})); % index for no assignment diff --git a/@miSim/plot.m b/@miSim/plot.m index 4fea9fa..07c22dd 100644 --- a/@miSim/plot.m +++ b/@miSim/plot.m @@ -1,41 +1,40 @@ -function [obj, f] = plot(obj) +function obj = plot(obj) arguments (Input) obj (1, 1) {mustBeA(obj, 'miSim')}; end arguments (Output) obj (1, 1) {mustBeA(obj, 'miSim')}; - f (1, 1) {mustBeA(f, 'matlab.ui.Figure')}; end % Plot domain - [obj.domain, f] = obj.domain.plotWireframe(obj.spatialPlotIndices); + [obj.domain, obj.f] = obj.domain.plotWireframe(obj.spatialPlotIndices); % Plot obstacles for ii = 1:size(obj.obstacles, 1) - [obj.obstacles{ii}, f] = obj.obstacles{ii}.plotWireframe(obj.spatialPlotIndices, f); + [obj.obstacles{ii}, obj.f] = obj.obstacles{ii}.plotWireframe(obj.spatialPlotIndices, obj.f); end % Plot objective gradient - f = obj.domain.objective.plot(obj.objectivePlotIndices, f); + obj.f = obj.domain.objective.plot(obj.objectivePlotIndices, obj.f); % Plot agents and their collision geometries for ii = 1:size(obj.agents, 1) - [obj.agents{ii}, f] = obj.agents{ii}.plot(obj.spatialPlotIndices, f); + [obj.agents{ii}, obj.f] = obj.agents{ii}.plot(obj.spatialPlotIndices, obj.f); end % Plot communication links - [obj, f] = obj.plotConnections(obj.spatialPlotIndices, f); + obj = obj.plotConnections(); % Plot abstract network graph - [obj, f] = obj.plotGraph(obj.networkGraphIndex, f); + obj = obj.plotGraph(); % Plot domain partitioning - [obj, f] = obj.plotPartitions(obj.partitionGraphIndex, f); + obj = obj.plotPartitions(); % Enforce plot limits for ii = 1:size(obj.spatialPlotIndices, 2) - xlim(f.Children(1).Children(obj.spatialPlotIndices(ii)), [obj.domain.minCorner(1), obj.domain.maxCorner(1)]); - ylim(f.Children(1).Children(obj.spatialPlotIndices(ii)), [obj.domain.minCorner(2), obj.domain.maxCorner(2)]); - zlim(f.Children(1).Children(obj.spatialPlotIndices(ii)), [obj.domain.minCorner(3), obj.domain.maxCorner(3)]); + xlim(obj.f.Children(1).Children(obj.spatialPlotIndices(ii)), [obj.domain.minCorner(1), obj.domain.maxCorner(1)]); + ylim(obj.f.Children(1).Children(obj.spatialPlotIndices(ii)), [obj.domain.minCorner(2), obj.domain.maxCorner(2)]); + zlim(obj.f.Children(1).Children(obj.spatialPlotIndices(ii)), [obj.domain.minCorner(3), obj.domain.maxCorner(3)]); end end \ No newline at end of file diff --git a/@miSim/plotConnections.m b/@miSim/plotConnections.m index 7321a22..8a33a89 100644 --- a/@miSim/plotConnections.m +++ b/@miSim/plotConnections.m @@ -1,12 +1,9 @@ -function [obj, f] = plotConnections(obj, ind, f) +function obj = plotConnections(obj) arguments (Input) obj (1, 1) {mustBeA(obj, 'miSim')}; - ind (1, :) double = NaN; - f (1, 1) {mustBeA(f, 'matlab.ui.Figure')} = figure; end arguments (Output) obj (1, 1) {mustBeA(obj, 'miSim')}; - f (1, 1) {mustBeA(f, 'matlab.ui.Figure')}; end % Iterate over lower triangle off-diagonal region of the @@ -24,20 +21,20 @@ function [obj, f] = plotConnections(obj, ind, f) X = X'; Y = Y'; Z = Z'; % Plot the connections - if isnan(ind) - hold(f.CurrentAxes, "on"); - o = plot3(f.CurrentAxes, X, Y, Z, 'Color', 'g', 'LineWidth', 2, 'LineStyle', '--'); - hold(f.CurrentAxes, "off"); + if isnan(obj.spatialPlotIndices) + hold(obj.f.CurrentAxes, "on"); + o = plot3(obj.f.CurrentAxes, X, Y, Z, 'Color', 'g', 'LineWidth', 2, 'LineStyle', '--'); + hold(obj.f.CurrentAxes, "off"); else - hold(f.Children(1).Children(ind(1)), "on"); - o = plot3(f.Children(1).Children(ind(1)), X, Y, Z, 'Color', 'g', 'LineWidth', 2, 'LineStyle', '--'); - hold(f.Children(1).Children(ind(1)), "off"); + hold(obj.f.Children(1).Children(obj.spatialPlotIndices(1)), "on"); + o = plot3(obj.f.Children(1).Children(obj.spatialPlotIndices(1)), X, Y, Z, 'Color', 'g', 'LineWidth', 2, 'LineStyle', '--'); + hold(obj.f.Children(1).Children(obj.spatialPlotIndices(1)), "off"); end % Copy to other plots - if size(ind, 2) > 1 - for ii = 2:size(ind, 2) - o = [o, copyobj(o(:, 1), f.Children(1).Children(ind(ii)))]; + if size(obj.spatialPlotIndices, 2) > 1 + for ii = 2:size(obj.spatialPlotIndices, 2) + o = [o, copyobj(o(:, 1), obj.f.Children(1).Children(obj.spatialPlotIndices(ii)))]; end end diff --git a/@miSim/plotGraph.m b/@miSim/plotGraph.m index 6170e91..034a35a 100644 --- a/@miSim/plotGraph.m +++ b/@miSim/plotGraph.m @@ -1,29 +1,26 @@ -function [obj, f] = plotGraph(obj, ind, f) +function obj = plotGraph(obj) arguments (Input) obj (1, 1) {mustBeA(obj, 'miSim')}; - ind (1, :) double = NaN; - f (1, 1) {mustBeA(f, 'matlab.ui.Figure')} = figure; end arguments (Output) obj (1, 1) {mustBeA(obj, 'miSim')}; - f (1, 1) {mustBeA(f, 'matlab.ui.Figure')}; end % Form graph from adjacency matrix G = graph(obj.adjacency, 'omitselfloops'); % Plot graph object - if isnan(ind) - hold(f.CurrentAxes, 'on'); - o = plot(f.CurrentAxes, G, 'LineStyle', '--', 'EdgeColor', 'g', 'NodeColor', 'k', 'LineWidth', 2); - hold(f.CurrentAxes, 'off'); + if isnan(obj.networkGraphIndex) + hold(obj.f.CurrentAxes, 'on'); + o = plot(obj.f.CurrentAxes, G, 'LineStyle', '--', 'EdgeColor', 'g', 'NodeColor', 'k', 'LineWidth', 2); + hold(obj.f.CurrentAxes, 'off'); else - hold(f.Children(1).Children(ind(1)), 'on'); - o = plot(f.Children(1).Children(ind(1)), G, 'LineStyle', '--', 'EdgeColor', 'g', 'NodeColor', 'k', 'LineWidth', 2); - hold(f.Children(1).Children(ind(1)), 'off'); - if size(ind, 2) > 1 + hold(obj.f.Children(1).Children(obj.networkGraphIndex(1)), 'on'); + o = plot(obj.f.Children(1).Children(obj.networkGraphIndex(1)), G, 'LineStyle', '--', 'EdgeColor', 'g', 'NodeColor', 'k', 'LineWidth', 2); + hold(obj.f.Children(1).Children(obj.networkGraphIndex(1)), 'off'); + if size(obj.networkGraphIndex, 2) > 1 for ii = 2:size(ind, 2) - o = [o; copyobj(o(1), f.Children(1).Children(ind(ii)))]; + o = [o; copyobj(o(1), obj.f.Children(1).Children(obj.networkGraphIndex(ii)))]; end end end diff --git a/@miSim/plotPartitions.m b/@miSim/plotPartitions.m index d5063b6..350f57c 100644 --- a/@miSim/plotPartitions.m +++ b/@miSim/plotPartitions.m @@ -1,25 +1,22 @@ -function [obj, f] = plotPartitions(obj, ind, f) +function obj = plotPartitions(obj) arguments (Input) obj (1, 1) {mustBeA(obj, 'miSim')}; - ind (1, :) double = NaN; - f (1, 1) {mustBeA(f, 'matlab.ui.Figure')} = figure; end arguments (Output) obj (1, 1) {mustBeA(obj, 'miSim')}; - f (1, 1) {mustBeA(f, 'matlab.ui.Figure')}; end - if isnan(ind) - hold(f.CurrentAxes, 'on'); - o = imagesc(f.CurrentAxes, obj.partitioning); - hold(f.CurrentAxes, 'off'); + if isnan(obj.partitionGraphIndex) + hold(obj.f.CurrentAxes, 'on'); + o = imagesc(obj.f.CurrentAxes, obj.partitioning); + hold(obj.f.CurrentAxes, 'off'); else - hold(f.Children(1).Children(ind(1)), 'on'); - o = imagesc(f.Children(1).Children(ind(1)), obj.partitioning); - hold(f.Children(1).Children(ind(1)), 'on'); - if size(ind, 2) > 1 + hold(obj.f.Children(1).Children(obj.partitionGraphIndex(1)), 'on'); + o = imagesc(obj.f.Children(1).Children(obj.partitionGraphIndex(1)), obj.partitioning); + hold(obj.f.Children(1).Children(obj.partitionGraphIndex(1)), 'on'); + if size(obj.partitionGraphIndex, 2) > 1 for ii = 2:size(ind, 2) - o = [o, copyobj(o(1), f.Children(1).Children(ind(ii)))]; + o = [o, copyobj(o(1), obj.f.Children(1).Children(obj.partitionGraphIndex(ii)))]; end end end diff --git a/@miSim/run.m b/@miSim/run.m index 9b54400..a15fa7a 100644 --- a/@miSim/run.m +++ b/@miSim/run.m @@ -1,16 +1,11 @@ -function [obj, f] = run(obj, f) +function [obj] = run(obj) arguments (Input) obj (1, 1) {mustBeA(obj, 'miSim')}; - f (1, 1) {mustBeA(f, 'matlab.ui.Figure')} = figure; end arguments (Output) obj (1, 1) {mustBeA(obj, 'miSim')}; - f (1, 1) {mustBeA(f, 'matlab.ui.Figure')}; end - % Create axes if they don't already exist - f = firstPlotSetup(f); - % Set up times to iterate over times = linspace(0, obj.timestep * obj.maxIter, obj.maxIter+1)'; partitioningTimes = times(obj.partitioningFreq:obj.partitioningFreq:size(times, 1)); @@ -37,13 +32,13 @@ function [obj, f] = run(obj, f) end % Update adjacency matrix - obj = obj.updateAdjacency; + obj = obj.updateAdjacency(); % Update plots - [obj, f] = obj.updatePlots(f, updatePartitions); + obj = obj.updatePlots(updatePartitions); % Write frame in to video - I = getframe(f); + I = getframe(obj.f); v.writeVideo(I); end diff --git a/@miSim/updatePlots.m b/@miSim/updatePlots.m index 3ce6419..ef9c596 100644 --- a/@miSim/updatePlots.m +++ b/@miSim/updatePlots.m @@ -1,12 +1,10 @@ -function [obj, f] = updatePlots(obj, f, updatePartitions) +function [obj] = updatePlots(obj, updatePartitions) arguments (Input) obj (1, 1) {mustBeA(obj, 'miSim')}; - f (1, 1) {mustBeA(f, 'matlab.ui.Figure')} = figure; updatePartitions (1, 1) logical = false; end arguments (Output) obj (1, 1) {mustBeA(obj, 'miSim')}; - f (1, 1) {mustBeA(f, 'matlab.ui.Figure')}; end % Update agent positions, collision geometries @@ -20,23 +18,23 @@ function [obj, f] = updatePlots(obj, f, updatePartitions) % Update agent connections plot delete(obj.connectionsPlot); - [obj, f] = obj.plotConnections(obj.spatialPlotIndices, f); + obj = obj.plotConnections(); % Update network graph plot delete(obj.graphPlot); - [obj, f] = obj.plotGraph(obj.networkGraphIndex, f); + obj = obj.plotGraph(); % Update partitioning plot if updatePartitions delete(obj.partitionPlot); - [obj, f] = obj.plotPartitions(obj.partitionGraphIndex, f); + obj = obj.plotPartitions(); end % reset plot limits to fit domain for ii = 1:size(obj.spatialPlotIndices, 2) - xlim(f.Children(1).Children(obj.spatialPlotIndices(ii)), [obj.domain.minCorner(1), obj.domain.maxCorner(1)]); - ylim(f.Children(1).Children(obj.spatialPlotIndices(ii)), [obj.domain.minCorner(2), obj.domain.maxCorner(2)]); - zlim(f.Children(1).Children(obj.spatialPlotIndices(ii)), [obj.domain.minCorner(3), obj.domain.maxCorner(3)]); + xlim(obj.f.Children(1).Children(obj.spatialPlotIndices(ii)), [obj.domain.minCorner(1), obj.domain.maxCorner(1)]); + ylim(obj.f.Children(1).Children(obj.spatialPlotIndices(ii)), [obj.domain.minCorner(2), obj.domain.maxCorner(2)]); + zlim(obj.f.Children(1).Children(obj.spatialPlotIndices(ii)), [obj.domain.minCorner(3), obj.domain.maxCorner(3)]); end drawnow; diff --git a/test/test_miSim.m b/test/test_miSim.m index 428e57f..7dc8d25 100644 --- a/test/test_miSim.m +++ b/test/test_miSim.m @@ -200,7 +200,7 @@ classdef test_miSim < matlab.unittest.TestCase end % Initialize the simulation - [tc.testClass, f] = tc.testClass.initialize(tc.domain, tc.domain.objective, tc.agents, tc.timestep, tc.partitoningFreq, tc.maxIter, tc.obstacles); + tc.testClass = tc.testClass.initialize(tc.domain, tc.domain.objective, tc.agents, tc.timestep, tc.partitoningFreq, tc.maxIter, tc.obstacles); end function misim_run(tc) % randomly create obstacles @@ -330,10 +330,10 @@ classdef test_miSim < matlab.unittest.TestCase end % Initialize the simulation - [tc.testClass, f] = tc.testClass.initialize(tc.domain, tc.domain.objective, tc.agents, tc.timestep, tc.partitoningFreq, tc.maxIter, tc.obstacles); + tc.testClass = tc.testClass.initialize(tc.domain, tc.domain.objective, tc.agents, tc.timestep, tc.partitoningFreq, tc.maxIter, tc.obstacles); % Run simulation loop - [tc.testClass, f] = tc.testClass.run(f); + tc.testClass = tc.testClass.run(f); end function test_basic_partitioning(tc) % place agents a fixed distance +/- X from the domain's center @@ -370,7 +370,7 @@ classdef test_miSim < matlab.unittest.TestCase % tc.agents{3} = tc.agents{3}.initialize(tc.domain.center - [0, d, 0], zeros(1, 3), 0, 0, geometry3, sensor, @gradientAscent, 3*d, 3, sprintf("Agent %d", 3)); % Initialize the simulation - [tc.testClass, f] = tc.testClass.initialize(tc.domain, tc.domain.objective, tc.agents, tc.timestep, tc.partitoningFreq, tc.maxIter); + tc.testClass = tc.testClass.initialize(tc.domain, tc.domain.objective, tc.agents, tc.timestep, tc.partitoningFreq, tc.maxIter); end end