added agent position trail to plot

This commit is contained in:
2026-01-01 16:06:19 -08:00
parent 4735c2b77b
commit c59b96f547
7 changed files with 61 additions and 9 deletions

View File

@@ -28,6 +28,7 @@ function obj = initialize(obj, domain, objective, agents, minAlt, timestep, part
% Define simulation time parameters % Define simulation time parameters
obj.timestep = timestep; obj.timestep = timestep;
obj.timestepIndex = 0;
obj.maxIter = maxIter - 1; obj.maxIter = maxIter - 1;
% Define domain % Define domain
@@ -66,6 +67,10 @@ function obj = initialize(obj, domain, objective, agents, minAlt, timestep, part
% Create initial partitioning % Create initial partitioning
obj = obj.partition(); 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 % Set up plots showing initialized state
obj = obj.plot(); obj = obj.plot();
end end

View File

@@ -4,6 +4,7 @@ classdef miSim
% Simulation parameters % Simulation parameters
properties (SetAccess = private, GetAccess = public) properties (SetAccess = private, GetAccess = public)
timestep = NaN; % delta time interval for simulation iterations 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 partitioningFreq = NaN; % number of simulation timesteps at which the partitioning routine is re-run
maxIter = NaN; % maximum number of simulation iterations maxIter = NaN; % maximum number of simulation iterations
domain = rectangularPrism; domain = rectangularPrism;
@@ -35,9 +36,11 @@ classdef miSim
connectionsPlot; % objects for lines connecting agents in spatial plots connectionsPlot; % objects for lines connecting agents in spatial plots
graphPlot; % objects for abstract network graph plot graphPlot; % objects for abstract network graph plot
partitionPlot; % objects for partition plot partitionPlot; % objects for partition plot
performancePlot; % objects for sensor performance 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 % Indicies for various plot types in the main tiled layout figure
spatialPlotIndices = [6, 4, 3, 2]; spatialPlotIndices = [6, 4, 3, 2];
objectivePlotIndices = [6, 4]; objectivePlotIndices = [6, 4];
@@ -56,6 +59,7 @@ classdef miSim
[obj] = plotConnections(obj); [obj] = plotConnections(obj);
[obj] = plotPartitions(obj); [obj] = plotPartitions(obj);
[obj] = plotGraph(obj); [obj] = plotGraph(obj);
[obj] = plotTrails(obj);
[obj] = updatePlots(obj, updatePartitions); [obj] = updatePlots(obj, updatePartitions);
end end
methods (Access = private) methods (Access = private)

View File

@@ -36,6 +36,9 @@ function obj = plot(obj)
% Plot domain partitioning % Plot domain partitioning
obj = obj.plotPartitions(); obj = obj.plotPartitions();
% Plot agent trails
obj = obj.plotTrails();
% Enforce plot limits % Enforce plot limits
for ii = 1:size(obj.spatialPlotIndices, 2) for ii = 1:size(obj.spatialPlotIndices, 2)
xlim(obj.f.Children(1).Children(obj.spatialPlotIndices(ii)), [obj.domain.minCorner(1), obj.domain.maxCorner(1)]); xlim(obj.f.Children(1).Children(obj.spatialPlotIndices(ii)), [obj.domain.minCorner(1), obj.domain.maxCorner(1)]);

View File

@@ -37,10 +37,7 @@ function obj = plotPerformance(obj)
end end
% Add legend % Add legend
agentStrings = repmat("Agent %d", size(obj.perf, 1) - 1, 1); agentStrings = string(cellfun(@(x) x.label, obj.agents, 'UniformOutput', false));
for ii = 1:size(agentStrings, 1)
agentStrings(ii) = sprintf(agentStrings(ii), ii);
end
agentStrings = ["Total"; agentStrings]; agentStrings = ["Total"; agentStrings];
legend(obj.fPerf.Children(1), agentStrings, 'Location', 'northwest'); legend(obj.fPerf.Children(1), agentStrings, 'Location', 'northwest');

31
@miSim/plotTrails.m Normal file
View File

@@ -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

View File

@@ -15,6 +15,7 @@ function [obj] = run(obj)
for ii = 1:size(obj.times, 1) for ii = 1:size(obj.times, 1)
% Display current sim time % Display current sim time
obj.t = obj.times(ii); obj.t = obj.times(ii);
obj.timestepIndex = ii;
fprintf("Sim Time: %4.2f (%d/%d)\n", obj.t, ii, obj.maxIter + 1); fprintf("Sim Time: %4.2f (%d/%d)\n", obj.t, ii, obj.maxIter + 1);
% Check if it's time for new partitions % Check if it's time for new partitions
@@ -38,6 +39,9 @@ function [obj] = run(obj)
% Finished simulation for this timestep, do accounting % 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 % Update total performance
obj.performance = [obj.performance, sum(cellfun(@(x) x.performance(end), obj.agents))]; obj.performance = [obj.performance, sum(cellfun(@(x) x.performance(end), obj.agents))];

View File

@@ -17,8 +17,8 @@ function [obj] = updatePlots(obj, updatePartitions)
obj.agents{ii}.updatePlots(); obj.agents{ii}.updatePlots();
end end
% The remaining updates might be possible to do in a clever way % The remaining updates might should all be possible to do in a clever
% that moves existing lines instead of clearing and % way that moves existing lines instead of clearing and
% re-plotting, which is much better for performance boost % re-plotting, which is much better for performance boost
% Update agent connections plot % 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)]); 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)]); zlim(obj.f.Children(1).Children(obj.spatialPlotIndices(ii)), [obj.domain.minCorner(3), obj.domain.maxCorner(3)]);
end 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; drawnow;
% Update performance plot % Update performance plot
% Re-normalize performance plot % Re-normalize performance plot
normalizingFactor = 1/max(obj.performance(end)); normalizingFactor = 1/max(obj.performance(end));
obj.performancePlot(1).YData(1:length(obj.performance)) = obj.performance * normalizingFactor; 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) 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).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
end end