From 8dd1e012ad274d9849904ebbe62b9182e7ff16e0 Mon Sep 17 00:00:00 2001 From: Kevin D Date: Sun, 16 Nov 2025 17:46:36 -0800 Subject: [PATCH] started performance plot --- .gitignore | 6 +++- @agent/agent.m | 3 -- @miSim/initialize.m | 10 ++++++- @miSim/miSim.m | 8 +++++- @miSim/partition.m | 10 +++---- @miSim/plot.m | 3 ++ @miSim/plotPerformance.m | 28 +++++++++++++++++++ @miSim/run.m | 12 +++----- @miSim/setupVideoWriter.m | 2 +- @miSim/updatePlots.m | 13 ++++++++- .../vQEWllkHYzJ8MP7NOsUYZ2vAZCAd.xml | 6 ++++ .../vQEWllkHYzJ8MP7NOsUYZ2vAZCAp.xml | 2 ++ test/test_miSim.m | 2 +- 13 files changed, 83 insertions(+), 22 deletions(-) create mode 100644 @miSim/plotPerformance.m create mode 100644 resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/vQEWllkHYzJ8MP7NOsUYZ2vAZCAd.xml create mode 100644 resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/vQEWllkHYzJ8MP7NOsUYZ2vAZCAp.xml diff --git a/.gitignore b/.gitignore index 7beb566..c8fef94 100644 --- a/.gitignore +++ b/.gitignore @@ -40,4 +40,8 @@ codegen/ *.sbproj.bak # Sandbox contents -sandbox/* \ No newline at end of file +sandbox/* + +# Videos +*.mp4 +*.avi diff --git a/@agent/agent.m b/@agent/agent.m index ac9a731..51af2db 100644 --- a/@agent/agent.m +++ b/@agent/agent.m @@ -1,7 +1,4 @@ classdef agent - properties (Access = public) - performance = NaN; % current individual sensor performance on partition - end properties (SetAccess = private, GetAccess = public) % Identifiers index = NaN; diff --git a/@miSim/initialize.m b/@miSim/initialize.m index 4f93527..056136b 100644 --- a/@miSim/initialize.m +++ b/@miSim/initialize.m @@ -15,7 +15,7 @@ function obj = initialize(obj, domain, objective, agents, timestep, partitoningF % Define simulation time parameters obj.timestep = timestep; - obj.maxIter = maxIter; + obj.maxIter = maxIter - 1; % Define domain obj.domain = domain; @@ -33,6 +33,14 @@ function obj = initialize(obj, domain, objective, agents, timestep, partitoningF % Compute adjacency matrix obj = obj.updateAdjacency(); + % Set up times to iterate over + obj.times = linspace(0, obj.timestep * obj.maxIter, obj.maxIter+1)'; + obj.partitioningTimes = obj.times(obj.partitioningFreq:obj.partitioningFreq:size(obj.times, 1)); + + % Prepare performance data store (at t = 0, all have 0 performance) + obj.fPerf = figure; + obj.perf = [zeros(size(obj.agents, 1) + 1, 1), NaN(size(obj.agents, 1) + 1, size(obj.partitioningTimes, 1) - 1)]; + % Create initial partitioning obj = obj.partition(); diff --git a/@miSim/miSim.m b/@miSim/miSim.m index 29bef49..9034478 100644 --- a/@miSim/miSim.m +++ b/@miSim/miSim.m @@ -17,13 +17,19 @@ classdef miSim end properties (Access = private) + % Sim + t = NaN; % current sim time + perf; % sensor performance timeseries array + times; + partitioningTimes; + % 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 + fPerf; % performance plot figure performancePlot; % objects for sensor performance plot % Indicies for various plot types in the main tiled layout figure diff --git a/@miSim/partition.m b/@miSim/partition.m index 1e91285..56e2cb4 100644 --- a/@miSim/partition.m +++ b/@miSim/partition.m @@ -22,15 +22,15 @@ function obj = partition(obj) % Get highest performing agent's index [m,n,~] = size(agentInds); - [i,j] = ndgrid(1:m, 1:n); - obj.partitioning = agentInds(sub2ind(size(agentInds), i, j, idx)); + [jj,kk] = ndgrid(1:m, 1:n); + obj.partitioning = agentInds(sub2ind(size(agentInds), jj, kk, idx)); % Get individual agent sensor performance + nowIdx = [0; obj.partitioningTimes] == obj.t; for ii = 1:size(obj.agents, 1) - obj.agents{ii}.performance = sum(agentPerformances(sub2ind(size(agentInds), i, j, idx)), 'all'); + obj.perf(ii, nowIdx) = sum(agentPerformances(sub2ind(size(agentInds), jj, kk, ii)), 'all'); end % Current total performance - sum(arrayfun(@(x) x.performance, [obj.agents{:}])) - obj.performance = sum(max(agentPerformances(:, :, 1:(end - 1)), [], 3), 'all'); % do not count final "non-assignment" layer in computing cumulative performance + obj.perf(end, nowIdx) = sum(obj.perf(1:(end - 1), nowIdx)); end \ No newline at end of file diff --git a/@miSim/plot.m b/@miSim/plot.m index 07c22dd..88bebe8 100644 --- a/@miSim/plot.m +++ b/@miSim/plot.m @@ -37,4 +37,7 @@ function obj = plot(obj) 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 + + % Plot performance + obj = obj.plotPerformance(); end \ No newline at end of file diff --git a/@miSim/plotPerformance.m b/@miSim/plotPerformance.m new file mode 100644 index 0000000..2e293ca --- /dev/null +++ b/@miSim/plotPerformance.m @@ -0,0 +1,28 @@ +function obj = plotPerformance(obj) + arguments (Input) + obj (1, 1) {mustBeA(obj, 'miSim')}; + end + arguments (Output) + obj (1, 1) {mustBeA(obj, 'miSim')}; + end + + axes(obj.fPerf); + title(obj.fPerf.Children(1), "Sensor Performance"); + xlabel(obj.fPerf.Children(1), 'Time (s)'); + ylabel(obj.fPerf.Children(1), 'Sensor Performance'); + grid(obj.fPerf.Children(1), 'on'); + + % Plot current cumulative performance + hold(obj.fPerf.Children(1), 'on'); + o = plot(obj.fPerf.Children(1), obj.perf(end, :)); + hold(obj.fPerf.Children(1), 'off'); + + % Plot current agent performance + for ii = 1:(size(obj.perf, 1) - 1) + hold(obj.fPerf.Children(1), 'on'); + o = [o; plot(obj.fPerf.Children(1), obj.perf(ii, :))]; + hold(obj.fPerf.Children(1), 'off'); + end + + obj.performancePlot = o; +end \ No newline at end of file diff --git a/@miSim/run.m b/@miSim/run.m index a15fa7a..0615549 100644 --- a/@miSim/run.m +++ b/@miSim/run.m @@ -6,22 +6,18 @@ function [obj] = run(obj) obj (1, 1) {mustBeA(obj, 'miSim')}; end - % 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)); - % Start video writer v = obj.setupVideoWriter(); v.open(); - for ii = 1:size(times, 1) + for ii = 1:size(obj.times, 1) % Display current sim time - t = times(ii); - fprintf("Sim Time: %4.2f (%d/%d)\n", t, ii, obj.maxIter) + obj.t = obj.times(ii); + fprintf("Sim Time: %4.2f (%d/%d)\n", obj.t, ii, obj.maxIter + 1); % Check if it's time for new partitions updatePartitions = false; - if ismember(t, partitioningTimes) + if ismember(obj.t, obj.partitioningTimes) updatePartitions = true; obj = obj.partition(); end diff --git a/@miSim/setupVideoWriter.m b/@miSim/setupVideoWriter.m index f412a81..b7f23d7 100644 --- a/@miSim/setupVideoWriter.m +++ b/@miSim/setupVideoWriter.m @@ -9,7 +9,7 @@ function v = setupVideoWriter(obj) if ispc || ismac v = VideoWriter(fullfile('sandbox', strcat(string(datetime('now'), 'yyyy_MM_dd_HH_mm_ss'), '_miSimHist')), 'MPEG-4'); elseif isunix - v = VideoWriter(fullfile('sandbox', strcat(string(datetime('now'), 'yyyy_MM_dd_HH_mm_ss'), '_miSimHist')), 'Motion JPEG AVI'); + v = VideoWriter(fullfile('.', strcat(string(datetime('now'), 'yyyy_MM_dd_HH_mm_ss'), '_miSimHist')), 'Motion JPEG AVI'); end v.FrameRate = 1 / obj.timestep; diff --git a/@miSim/updatePlots.m b/@miSim/updatePlots.m index ef9c596..f7631c3 100644 --- a/@miSim/updatePlots.m +++ b/@miSim/updatePlots.m @@ -36,6 +36,17 @@ function [obj] = updatePlots(obj, updatePartitions) 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; + + % Update performance plot + if updatePartitions + nowIdx = [0; obj.partitioningTimes] == obj.t; + % set(obj.performancePlot(1), 'YData', obj.perf(end, 1:find(nowIdx))); + obj.performancePlot(1).YData(nowIdx) = obj.perf(end, nowIdx); + for ii = 2:size(obj.performancePlot, 1) + obj.performancePlot(ii).YData(nowIdx) = obj.perf(ii, nowIdx); + end + drawnow; + end + end \ No newline at end of file diff --git a/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/vQEWllkHYzJ8MP7NOsUYZ2vAZCAd.xml b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/vQEWllkHYzJ8MP7NOsUYZ2vAZCAd.xml new file mode 100644 index 0000000..99772b4 --- /dev/null +++ b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/vQEWllkHYzJ8MP7NOsUYZ2vAZCAd.xml @@ -0,0 +1,6 @@ + + + + + \ No newline at end of file diff --git a/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/vQEWllkHYzJ8MP7NOsUYZ2vAZCAp.xml b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/vQEWllkHYzJ8MP7NOsUYZ2vAZCAp.xml new file mode 100644 index 0000000..bf019e3 --- /dev/null +++ b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/vQEWllkHYzJ8MP7NOsUYZ2vAZCAp.xml @@ -0,0 +1,2 @@ + + \ No newline at end of file diff --git a/test/test_miSim.m b/test/test_miSim.m index 7dc8d25..f79614a 100644 --- a/test/test_miSim.m +++ b/test/test_miSim.m @@ -333,7 +333,7 @@ classdef test_miSim < matlab.unittest.TestCase 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 = tc.testClass.run(f); + tc.testClass = tc.testClass.run(); end function test_basic_partitioning(tc) % place agents a fixed distance +/- X from the domain's center