From c59b96f547692b911552dab83ee536cbb43c34f2 Mon Sep 17 00:00:00 2001 From: krdee1 Date: Thu, 1 Jan 2026 16:06:19 -0800 Subject: [PATCH] added agent position trail to plot --- @miSim/initialize.m | 5 +++++ @miSim/miSim.m | 6 +++++- @miSim/plot.m | 3 +++ @miSim/plotPerformance.m | 5 +---- @miSim/plotTrails.m | 31 +++++++++++++++++++++++++++++++ @miSim/run.m | 4 ++++ @miSim/updatePlots.m | 16 ++++++++++++---- 7 files changed, 61 insertions(+), 9 deletions(-) create mode 100644 @miSim/plotTrails.m diff --git a/@miSim/initialize.m b/@miSim/initialize.m index f134b04..cd62a73 100644 --- a/@miSim/initialize.m +++ b/@miSim/initialize.m @@ -28,6 +28,7 @@ function obj = initialize(obj, domain, objective, agents, minAlt, timestep, part % Define simulation time parameters obj.timestep = timestep; + obj.timestepIndex = 0; obj.maxIter = maxIter - 1; % Define domain @@ -66,6 +67,10 @@ function obj = initialize(obj, domain, objective, agents, minAlt, timestep, part % Create initial partitioning obj = obj.partition(); + % Initialize variable that will store agent positions for trail plots + obj.posHist = NaN(size(obj.agents, 1), obj.maxIter + 1, 3); + obj.posHist(1:size(obj.agents, 1), 1, 1:3) = reshape(cell2mat(cellfun(@(x) x.pos, obj.agents, 'UniformOutput', false)), size(obj.agents, 1), 1, 3); + % Set up plots showing initialized state obj = obj.plot(); end \ No newline at end of file diff --git a/@miSim/miSim.m b/@miSim/miSim.m index 3bf1cee..42f0191 100644 --- a/@miSim/miSim.m +++ b/@miSim/miSim.m @@ -4,6 +4,7 @@ classdef miSim % Simulation parameters properties (SetAccess = private, GetAccess = public) timestep = NaN; % delta time interval for simulation iterations + timestepIndex = NaN; % index of the current timestep (useful for time-indexed arrays) partitioningFreq = NaN; % number of simulation timesteps at which the partitioning routine is re-run maxIter = NaN; % maximum number of simulation iterations domain = rectangularPrism; @@ -35,9 +36,11 @@ classdef miSim connectionsPlot; % objects for lines connecting agents in spatial plots graphPlot; % objects for abstract network graph plot partitionPlot; % objects for partition plot - performancePlot; % objects for sensor performance plot + posHist; % data for trail plot + trailPlot; % objects for agent trail plot + % Indicies for various plot types in the main tiled layout figure spatialPlotIndices = [6, 4, 3, 2]; objectivePlotIndices = [6, 4]; @@ -56,6 +59,7 @@ classdef miSim [obj] = plotConnections(obj); [obj] = plotPartitions(obj); [obj] = plotGraph(obj); + [obj] = plotTrails(obj); [obj] = updatePlots(obj, updatePartitions); end methods (Access = private) diff --git a/@miSim/plot.m b/@miSim/plot.m index f51fb65..4782a16 100644 --- a/@miSim/plot.m +++ b/@miSim/plot.m @@ -36,6 +36,9 @@ function obj = plot(obj) % Plot domain partitioning obj = obj.plotPartitions(); + % Plot agent trails + obj = obj.plotTrails(); + % Enforce plot limits for ii = 1:size(obj.spatialPlotIndices, 2) xlim(obj.f.Children(1).Children(obj.spatialPlotIndices(ii)), [obj.domain.minCorner(1), obj.domain.maxCorner(1)]); diff --git a/@miSim/plotPerformance.m b/@miSim/plotPerformance.m index c5d77d6..5cd1673 100644 --- a/@miSim/plotPerformance.m +++ b/@miSim/plotPerformance.m @@ -37,10 +37,7 @@ function obj = plotPerformance(obj) end % Add legend - agentStrings = repmat("Agent %d", size(obj.perf, 1) - 1, 1); - for ii = 1:size(agentStrings, 1) - agentStrings(ii) = sprintf(agentStrings(ii), ii); - end + agentStrings = string(cellfun(@(x) x.label, obj.agents, 'UniformOutput', false)); agentStrings = ["Total"; agentStrings]; legend(obj.fPerf.Children(1), agentStrings, 'Location', 'northwest'); diff --git a/@miSim/plotTrails.m b/@miSim/plotTrails.m new file mode 100644 index 0000000..d3c2532 --- /dev/null +++ b/@miSim/plotTrails.m @@ -0,0 +1,31 @@ +function obj = plotTrails(obj) + arguments (Input) + obj (1, 1) {mustBeA(obj, 'miSim')} + end + arguments (Output) + obj (1, 1) {mustBeA(obj, 'miSim')} + end + + % fast exit when plotting is disabled + if ~obj.makePlots + return; + end + + % Plot full range of position history on each spatial plot axes + o = []; + for ii = 1:(size(obj.posHist, 1)) + hold(obj.f.Children(1).Children(obj.spatialPlotIndices(1)), 'on'); + o = [o; plot3(obj.f.Children(1).Children(obj.spatialPlotIndices(1)), obj.posHist(ii, 1:obj.maxIter, 1), obj.posHist(ii, 1:obj.maxIter, 2), obj.posHist(ii, 1:obj.maxIter, 3), 'Color', 'k', 'LineWidth', 1)]; + hold(obj.f.Children(1).Children(obj.spatialPlotIndices(1)), 'off'); + end + + % Copy trails to other figures? + obj.trailPlot = o; + + % Add legend? + % TODO legend? + % TODO unique colors for agent trails (same as performance plot?) + % Could be agent-specific colors (stored as agent property) + keyboard + +end \ No newline at end of file diff --git a/@miSim/run.m b/@miSim/run.m index 8c3892c..8116326 100644 --- a/@miSim/run.m +++ b/@miSim/run.m @@ -15,6 +15,7 @@ function [obj] = run(obj) for ii = 1:size(obj.times, 1) % Display current sim time obj.t = obj.times(ii); + obj.timestepIndex = ii; fprintf("Sim Time: %4.2f (%d/%d)\n", obj.t, ii, obj.maxIter + 1); % Check if it's time for new partitions @@ -38,6 +39,9 @@ function [obj] = run(obj) % Finished simulation for this timestep, do accounting + % Update agent position history array + obj.posHist(1:size(obj.agents, 1), obj.timestepIndex + 1, 1:3) = reshape(cell2mat(cellfun(@(x) x.pos, obj.agents, 'UniformOutput', false)), size(obj.agents, 1), 1, 3); + % Update total performance obj.performance = [obj.performance, sum(cellfun(@(x) x.performance(end), obj.agents))]; diff --git a/@miSim/updatePlots.m b/@miSim/updatePlots.m index 209688b..017b3d5 100644 --- a/@miSim/updatePlots.m +++ b/@miSim/updatePlots.m @@ -17,8 +17,8 @@ function [obj] = updatePlots(obj, updatePartitions) obj.agents{ii}.updatePlots(); end - % The remaining updates might be possible to do in a clever way - % that moves existing lines instead of clearing and + % The remaining updates might should all be possible to do in a clever + % way that moves existing lines instead of clearing and % re-plotting, which is much better for performance boost % Update agent connections plot @@ -41,15 +41,23 @@ 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 + + % Update agent trails + for ii = 1:size(obj.agents, 1) + obj.trailPlot(ii).XData(obj.timestepIndex) = obj.posHist(ii, obj.timestepIndex, 1); + obj.trailPlot(ii).YData(obj.timestepIndex) = obj.posHist(ii, obj.timestepIndex, 2); + obj.trailPlot(ii).ZData(obj.timestepIndex) = obj.posHist(ii, obj.timestepIndex, 3); + end + drawnow; % Update performance plot % Re-normalize performance plot normalizingFactor = 1/max(obj.performance(end)); obj.performancePlot(1).YData(1:length(obj.performance)) = obj.performance * normalizingFactor; - obj.performancePlot(1).XData(find(isnan(obj.performancePlot(1).XData), 1, 'first')) = obj.t; + obj.performancePlot(1).XData(obj.timestepIndex) = obj.t; for ii = 2:(size(obj.agents, 1) + 1) obj.performancePlot(ii).YData(1:length(obj.performance)) = obj.agents{ii - 1}.performance * normalizingFactor; - obj.performancePlot(ii).XData(find(isnan(obj.performancePlot(ii).XData), 1, 'first')) = obj.t; + obj.performancePlot(ii).XData(obj.timestepIndex) = obj.t; end end \ No newline at end of file