now doing partitioning on every timestep, looks super smooth

This commit is contained in:
2026-01-11 19:09:32 -08:00
parent 2a48b1d469
commit ff02e8a1c6
6 changed files with 28 additions and 68 deletions

View File

@@ -1,4 +1,4 @@
function obj = initialize(obj, domain, objective, agents, minAlt, timestep, partitoningFreq, maxIter, obstacles, makePlots, makeVideo)
function obj = initialize(obj, domain, objective, agents, minAlt, timestep, maxIter, obstacles, makePlots, makeVideo)
arguments (Input)
obj (1, 1) {mustBeA(obj, 'miSim')};
domain (1, 1) {mustBeGeometry};
@@ -6,7 +6,6 @@ function obj = initialize(obj, domain, objective, agents, minAlt, timestep, part
agents (:, 1) cell;
minAlt (1, 1) double = 1;
timestep (:, 1) double = 0.05;
partitoningFreq (:, 1) double = 0.25
maxIter (:, 1) double = 1000;
obstacles (:, 1) cell {mustBeGeometry} = cell(0, 1);
makePlots(1, 1) logical = true;
@@ -33,7 +32,6 @@ function obj = initialize(obj, domain, objective, agents, minAlt, timestep, part
% Define domain
obj.domain = domain;
obj.partitioningFreq = partitoningFreq;
% Add geometries representing obstacles within the domain
obj.obstacles = obstacles;
@@ -73,7 +71,6 @@ function obj = initialize(obj, domain, objective, agents, minAlt, timestep, part
% 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.perf = [zeros(size(obj.agents, 1) + 1, 1), NaN(size(obj.agents, 1) + 1, size(obj.partitioningTimes, 1) - 1)];
@@ -82,7 +79,7 @@ function obj = initialize(obj, domain, objective, agents, minAlt, timestep, part
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);
% Create initial partitioning
obj = obj.partition();
obj.partitioning = obj.agents{1}.partition(obj.agents, obj.domain.objective);
% Initialize variable that will store agent positions for trail plots
obj.posHist = NaN(size(obj.agents, 1), obj.maxIter + 1, 3);

View File

@@ -67,7 +67,7 @@ classdef miSim
[obj] = plotGraph(obj);
[obj] = plotTrails(obj);
[obj] = plotH(obj);
[obj] = updatePlots(obj, updatePartitions);
[obj] = updatePlots(obj);
validate(obj);
end
methods (Access = private)

View File

@@ -1,33 +0,0 @@
function obj = partition(obj)
arguments (Input)
obj (1, 1) {mustBeA(obj, 'miSim')};
end
arguments (Output)
obj (1, 1) {mustBeA(obj, 'miSim')};
end
% 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, [obj.objective.X(:), obj.objective.Y(:), zeros(size(obj.objective.X(:)))]), size(obj.objective.X)), obj.agents, 'UniformOutput', false);
agentPerformances{end + 1} = obj.domain.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{:});
% Get highest performance value at each point
[~, idx] = max(agentPerformances, [], 3);
% Collect agent indices in the same way as performance
indices = 1:size(obj.agents, 1);
agentInds = squeeze(tensorprod(indices, ones(size(obj.objective.X))));
if size(agentInds, 1) ~= size(obj.agents, 1)
agentInds = reshape(agentInds, [size(obj.agents, 1), size(agentInds)]); % needed for cases with 1 agent where prior squeeze is too agressive
end
agentInds = num2cell(agentInds, 2:3);
agentInds = cellfun(@(x) squeeze(x), agentInds, 'UniformOutput', false);
agentInds{end + 1} = zeros(size(agentInds{end})); % index for no assignment
agentInds = cat(3, agentInds{:});
% Use highest performing agent's index to form partitions
[m, n, ~] = size(agentInds);
[jj, kk] = ndgrid(1:m, 1:n);
obj.partitioning = agentInds(sub2ind(size(agentInds), jj, kk, idx));
end

View File

@@ -18,19 +18,18 @@ function [obj] = run(obj)
obj.timestepIndex = ii;
fprintf("Sim Time: %4.2f (%d/%d)\n", obj.t, ii, obj.maxIter + 1);
% Before moving
% Validate current simulation configuration
obj.validate();
% Check if it's time for new partitions
updatePartitions = false;
if ismember(obj.t, obj.partitioningTimes)
updatePartitions = true;
obj = obj.partition();
end
% Update partitioning before moving (this one is strictly for
% plotting purposes, the real partitioning is done by the agents)
obj.partitioning = obj.agents{1}.partition(obj.agents, obj.domain.objective);
% Determine desired communications links
obj = obj.lesserNeighbor();
% Moving
% Iterate over agents to simulate their unconstrained motion
for jj = 1:size(obj.agents, 1)
obj.agents{jj} = obj.agents{jj}.run(obj.domain, obj.partitioning, obj.timestepIndex, jj, obj.agents);
@@ -40,8 +39,7 @@ function [obj] = run(obj)
% CBF constraints solved by QP
obj = constrainMotion(obj);
% Finished simulation for this timestep, do accounting
% After moving
% 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);
@@ -52,7 +50,7 @@ function [obj] = run(obj)
obj = obj.updateAdjacency();
% Update plots
obj = obj.updatePlots(updatePartitions);
obj = obj.updatePlots();
% Write frame in to video
if obj.makeVideo

View File

@@ -1,7 +1,6 @@
function [obj] = updatePlots(obj, updatePartitions)
function [obj] = updatePlots(obj)
arguments (Input)
obj (1, 1) {mustBeA(obj, 'miSim')};
updatePartitions (1, 1) logical = false;
end
arguments (Output)
obj (1, 1) {mustBeA(obj, 'miSim')};
@@ -30,10 +29,8 @@ function [obj] = updatePlots(obj, updatePartitions)
obj = obj.plotGraph();
% Update partitioning plot
if updatePartitions
delete(obj.partitionPlot);
obj = obj.plotPartitions();
end
delete(obj.partitionPlot);
obj = obj.plotPartitions();
% reset plot limits to fit domain
for ii = 1:size(obj.spatialPlotIndices, 2)