codegen fixes, bug fixes, gets running on testbed environment

This commit is contained in:
2026-02-24 19:05:54 -08:00
parent fb9feac23d
commit bb97502be5
38 changed files with 1732 additions and 263 deletions

View File

@@ -17,8 +17,8 @@ classdef agent
fovGeometry;
% Communication
commsGeometry = spherical;
lesserNeighbors = [];
commsGeometry;
lesserNeighbors = zeros(1, 0);
% Performance
performance = 0;
@@ -34,6 +34,17 @@ classdef agent
end
methods (Access = public)
function obj = agent()
arguments (Input)
end
arguments (Output)
obj (1, 1) agent
end
obj.collisionGeometry = spherical;
obj.sensorModel = sigmoidSensor;
obj.fovGeometry = cone;
obj.commsGeometry = spherical;
end
[obj] = initialize(obj, pos, pan, tilt, collisionGeometry, sensorModel, guidanceModel, comRange, index, label);
[obj] = run(obj, domain, partitioning, t, index, agents);
[partitioning] = partition(obj, agents, objective)

View File

@@ -23,7 +23,9 @@ function obj = initialize(obj, pos, collisionGeometry, sensorModel, comRange, ma
obj.stepDecayRate = obj.initialStepSize / maxIter;
% Initialize performance vector
obj.performance = [0, NaN(1, maxIter), 0];
if coder.target('MATLAB')
obj.performance = [0, NaN(1, maxIter), 0];
end
% Add spherical geometry based on com range
obj.commsGeometry = obj.commsGeometry.initialize(obj.pos, comRange, REGION_TYPE.COMMS, sprintf("%s Comms Geometry", obj.label));

View File

@@ -7,29 +7,33 @@ function [partitioning] = partition(obj, agents, objective)
arguments (Output)
partitioning (:, :) double;
end
% Assess sensing performance of each agent at each sample point
% in the domain
agentPerformances = cellfun(@(x) reshape(x.sensorModel.sensorPerformance(x.pos, [objective.X(:), objective.Y(:), zeros(size(objective.X(:)))]), size(objective.X)), agents, "UniformOutput", false);
agentPerformances{end + 1} = 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);
nAgents = size(agents, 1);
gridM = size(objective.X, 1);
gridN = size(objective.X, 2);
nPoints = gridM * gridN;
% Collect agent indices in the same way as performance
indices = 1:size(agents, 1);
agentInds = squeeze(tensorprod(indices, ones(size(objective.X))));
if size(agentInds, 1) ~= size(agents, 1)
agentInds = reshape(agentInds, [size(agents, 1), size(agentInds)]); % needed for cases with 1 agent where prior squeeze is too agressive
% Assess sensing performance of each agent at each sample point.
% agentPerf is (nPoints x nAgents+1): the extra column is the
% minimum threshold that must be exceeded for any assignment.
agentPerf = zeros(nPoints, nAgents + 1);
for aa = 1:nAgents
p = agents{aa}.sensorModel.sensorPerformance(agents{aa}.pos, ...
[objective.X(:), objective.Y(:), zeros(nPoints, 1)]);
agentPerf(:, aa) = p(:);
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{:});
agentPerf(:, nAgents + 1) = objective.sensorPerformanceMinimum;
% Use highest performing agent's index to form partitions
[m, n, ~] = size(agentInds);
[jj, kk] = ndgrid(1:m, 1:n);
partitioning = agentInds(sub2ind(size(agentInds), jj, kk, idx));
end
% Find which agent has highest performance at each point.
% If the threshold column wins (idx == nAgents+1) the point is unassigned (0).
[~, idx] = max(agentPerf, [], 2);
assignedAgent = zeros(nPoints, 1);
for pp = 1:nPoints
if idx(pp) <= nAgents
assignedAgent(pp) = idx(pp);
end
end
partitioning = reshape(assignedAgent, gridM, gridN);
end

View File

@@ -13,7 +13,7 @@ function obj = run(obj, domain, partitioning, timestepIndex, index, agents)
% Collect objective function values across partition
partitionMask = partitioning == index;
if ~unique(partitionMask)
if ~any(partitionMask(:))
% This agent has no partition, maintain current state
return;
end
@@ -32,10 +32,10 @@ function obj = run(obj, domain, partitioning, timestepIndex, index, agents)
pos = obj.pos + delta * deltaApplicator(ii, 1:3);
% Compute performance values on partition
if ii < 5
if ii < 6
% Compute sensing performance
sensorValues = obj.sensorModel.sensorPerformance(pos, [maskedX, maskedY, zeros(size(maskedX))]); % S_n(omega, P_n) on W_n
% Objective performance does not change for 0, +/- X, Y steps.
% Objective performance does not change for 0, +/- X, +/- Y steps.
% Those values are computed once before the loop and are only
% recomputed when +/- Z steps are applied
else
@@ -64,17 +64,26 @@ function obj = run(obj, domain, partitioning, timestepIndex, index, agents)
end
% Store agent performance at current time and place
obj.performance(timestepIndex + 1) = C_delta(1);
if coder.target('MATLAB')
obj.performance(timestepIndex + 1) = C_delta(1);
end
% Compute gradient by finite central differences
gradC = [(C_delta(2)-C_delta(3))/(2*delta), (C_delta(4)-C_delta(5))/(2*delta), (C_delta(6)-C_delta(7))/(2*delta)];
% Compute scaling factor
targetRate = obj.initialStepSize - obj.stepDecayRate * timestepIndex; % slow down as you get closer
rateFactor = targetRate / norm(gradC);
gradNorm = norm(gradC);
% Compute unconstrained next position
pNext = obj.pos + rateFactor * gradC;
% Compute unconstrained next position.
% Guard against near-zero gradient: when sensor performance is saturated
% or near-zero across the whole partition, rateFactor -> Inf and pNext
% explodes. Stay put instead.
if gradNorm < 1e-10
pNext = obj.pos;
else
pNext = obj.pos + (targetRate / gradNorm) * gradC;
end
% Move to next position
obj.lastPos = obj.pos;