diff --git a/@agent/agent.m b/@agent/agent.m
new file mode 100644
index 0000000..51af2db
--- /dev/null
+++ b/@agent/agent.m
@@ -0,0 +1,40 @@
+classdef agent
+ properties (SetAccess = private, GetAccess = public)
+ % Identifiers
+ index = NaN;
+ label = "";
+
+ % Sensor
+ sensorModel;
+ sensingLength = 0.05; % length parameter used by sensing function
+
+ % Guidance
+ guidanceModel;
+
+ % State
+ lastPos = NaN(1, 3); % position from previous timestep
+ pos = NaN(1, 3); % current position
+ vel = NaN(1, 3); % current velocity
+ pan = NaN; % pan angle
+ tilt = NaN; % tilt angle
+
+ % Collision
+ collisionGeometry;
+
+ % FOV cone
+ fovGeometry;
+
+ % Communication
+ comRange = NaN;
+
+ % Plotting
+ scatterPoints;
+ end
+
+ methods (Access = public)
+ [obj] = initialize(obj, pos, vel, pan, tilt, collisionGeometry, sensorModel, guidanceModel, comRange, index, label);
+ [obj] = run(obj, sensingObjective, domain, partitioning);
+ [obj, f] = plot(obj, ind, f);
+ updatePlots(obj);
+ end
+end
\ No newline at end of file
diff --git a/@agent/initialize.m b/@agent/initialize.m
new file mode 100644
index 0000000..5e8f00c
--- /dev/null
+++ b/@agent/initialize.m
@@ -0,0 +1,33 @@
+function obj = initialize(obj, pos, vel, pan, tilt, collisionGeometry, sensorModel, guidanceModel, comRange, index, label)
+ arguments (Input)
+ obj (1, 1) {mustBeA(obj, 'agent')};
+ pos (1, 3) double;
+ vel (1, 3) double;
+ pan (1, 1) double;
+ tilt (1, 1) double;
+ collisionGeometry (1, 1) {mustBeGeometry};
+ sensorModel (1, 1) {mustBeSensor}
+ guidanceModel (1, 1) {mustBeA(guidanceModel, 'function_handle')};
+ comRange (1, 1) double = NaN;
+ index (1, 1) double = NaN;
+ label (1, 1) string = "";
+ end
+ arguments (Output)
+ obj (1, 1) {mustBeA(obj, 'agent')};
+ end
+
+ obj.pos = pos;
+ obj.vel = vel;
+ obj.pan = pan;
+ obj.tilt = tilt;
+ obj.collisionGeometry = collisionGeometry;
+ obj.sensorModel = sensorModel;
+ obj.guidanceModel = guidanceModel;
+ obj.comRange = comRange;
+ obj.index = index;
+ obj.label = label;
+
+ % Initialize FOV cone
+ obj.fovGeometry = cone;
+ obj.fovGeometry = obj.fovGeometry.initialize([obj.pos(1:2), 0], tan(obj.sensorModel.alphaTilt) * obj.pos(3), obj.pos(3), REGION_TYPE.FOV, sprintf("%s FOV", obj.label));
+end
\ No newline at end of file
diff --git a/@agent/plot.m b/@agent/plot.m
new file mode 100644
index 0000000..1b92e7f
--- /dev/null
+++ b/@agent/plot.m
@@ -0,0 +1,35 @@
+function [obj, f] = plot(obj, ind, f)
+ arguments (Input)
+ obj (1, 1) {mustBeA(obj, 'agent')};
+ ind (1, :) double = NaN;
+ f (1, 1) {mustBeA(f, 'matlab.ui.Figure')} = figure;
+ end
+ arguments (Output)
+ obj (1, 1) {mustBeA(obj, 'agent')};
+ f (1, 1) {mustBeA(f, 'matlab.ui.Figure')};
+ end
+
+ % Create axes if they don't already exist
+ f = firstPlotSetup(f);
+
+ % Plot points representing the agent position
+ hold(f.Children(1).Children(end), "on");
+ o = scatter3(f.Children(1).Children(end), obj.pos(1), obj.pos(2), obj.pos(3), 'filled', 'ko', 'SizeData', 25);
+ hold(f.Children(1).Children(end), "off");
+
+ % Check if this is a tiled layout figure
+ if strcmp(f.Children(1).Type, 'tiledlayout')
+ % Add to other perspectives
+ o = [o; copyobj(o(1), f.Children(1).Children(2))];
+ o = [o; copyobj(o(1), f.Children(1).Children(3))];
+ o = [o; copyobj(o(1), f.Children(1).Children(4))];
+ end
+
+ obj.scatterPoints = o;
+
+ % Plot collision geometry
+ [obj.collisionGeometry, f] = obj.collisionGeometry.plotWireframe(ind, f);
+
+ % Plot FOV geometry
+ [obj.fovGeometry, f] = obj.fovGeometry.plot(ind, f);
+end
\ No newline at end of file
diff --git a/@agent/run.m b/@agent/run.m
new file mode 100644
index 0000000..fb901b3
--- /dev/null
+++ b/@agent/run.m
@@ -0,0 +1,28 @@
+function obj = run(obj, sensingObjective, domain, partitioning)
+ arguments (Input)
+ obj (1, 1) {mustBeA(obj, 'agent')};
+ sensingObjective (1, 1) {mustBeA(sensingObjective, 'sensingObjective')};
+ domain (1, 1) {mustBeGeometry};
+ partitioning (:, :) double;
+ end
+ arguments (Output)
+ obj (1, 1) {mustBeA(obj, 'agent')};
+ end
+
+ % Do sensing
+ [sensedValues, sensedPositions] = obj.sensorModel.sense(obj, sensingObjective, domain, partitioning);
+
+ % Determine next planned position
+ nextPos = obj.guidanceModel(sensedValues, sensedPositions, obj.pos);
+
+ % Move to next position
+ % (dynamics not modeled at this time)
+ obj.lastPos = obj.pos;
+ obj.pos = nextPos;
+
+ % Calculate movement
+ d = obj.pos - obj.collisionGeometry.center;
+
+ % Reinitialize collision geometry in the new position
+ obj.collisionGeometry = obj.collisionGeometry.initialize([obj.collisionGeometry.minCorner; obj.collisionGeometry.maxCorner] + d, obj.collisionGeometry.tag, obj.collisionGeometry.label);
+end
\ No newline at end of file
diff --git a/@agent/updatePlots.m b/@agent/updatePlots.m
new file mode 100644
index 0000000..4900e73
--- /dev/null
+++ b/@agent/updatePlots.m
@@ -0,0 +1,35 @@
+function updatePlots(obj)
+ arguments (Input)
+ obj (1, 1) {mustBeA(obj, 'agent')};
+ end
+ arguments (Output)
+ end
+
+ % Scatterplot point positions
+ for ii = 1:size(obj.scatterPoints, 1)
+ obj.scatterPoints(ii).XData = obj.pos(1);
+ obj.scatterPoints(ii).YData = obj.pos(2);
+ obj.scatterPoints(ii).ZData = obj.pos(3);
+ end
+
+ % Find change in agent position since last timestep
+ deltaPos = obj.pos - obj.lastPos;
+
+ % Collision geometry edges
+ for jj = 1:size(obj.collisionGeometry.lines, 2)
+ % Update plotting
+ for ii = 1:size(obj.collisionGeometry.lines(:, jj), 1)
+ obj.collisionGeometry.lines(ii, jj).XData = obj.collisionGeometry.lines(ii, jj).XData + deltaPos(1);
+ obj.collisionGeometry.lines(ii, jj).YData = obj.collisionGeometry.lines(ii, jj).YData + deltaPos(2);
+ obj.collisionGeometry.lines(ii, jj).ZData = obj.collisionGeometry.lines(ii, jj).ZData + deltaPos(3);
+ end
+ end
+
+ % Update FOV geometry surfaces
+ for jj = 1:size(obj.fovGeometry.surface, 2)
+ % Update each plot
+ obj.fovGeometry.surface(jj).XData = obj.fovGeometry.surface(jj).XData + deltaPos(1);
+ obj.fovGeometry.surface(jj).YData = obj.fovGeometry.surface(jj).YData + deltaPos(2);
+ obj.fovGeometry.surface(jj).ZData = obj.fovGeometry.surface(jj).ZData + deltaPos(3);
+ end
+end
\ No newline at end of file
diff --git a/@miSim/initialize.m b/@miSim/initialize.m
new file mode 100644
index 0000000..1669885
--- /dev/null
+++ b/@miSim/initialize.m
@@ -0,0 +1,42 @@
+function [obj, f] = initialize(obj, domain, objective, agents, timestep, partitoningFreq, maxIter, obstacles)
+ arguments (Input)
+ obj (1, 1) {mustBeA(obj, 'miSim')};
+ domain (1, 1) {mustBeGeometry};
+ objective (1, 1) {mustBeA(objective, 'sensingObjective')};
+ agents (:, 1) cell;
+ timestep (:, 1) double = 0.05;
+ partitoningFreq (:, 1) double = 0.25
+ maxIter (:, 1) double = 1000;
+ obstacles (:, 1) cell {mustBeGeometry} = cell(0, 1);
+ end
+ arguments (Output)
+ obj (1, 1) {mustBeA(obj, 'miSim')};
+ f (1, 1) {mustBeA(f, 'matlab.ui.Figure')};
+ end
+
+ % Define simulation time parameters
+ obj.timestep = timestep;
+ obj.maxIter = maxIter;
+
+ % Define domain
+ obj.domain = domain;
+ obj.partitioningFreq = partitoningFreq;
+
+ % Add geometries representing obstacles within the domain
+ obj.obstacles = obstacles;
+
+ % Define objective
+ obj.objective = objective;
+
+ % Define agents
+ obj.agents = agents;
+
+ % Compute adjacency matrix
+ obj = obj.updateAdjacency();
+
+ % Create initial partitioning
+ obj = obj.partition();
+
+ % Set up plots showing initialized state
+ [obj, f] = obj.plot();
+end
\ No newline at end of file
diff --git a/@miSim/miSim.m b/@miSim/miSim.m
new file mode 100644
index 0000000..552e771
--- /dev/null
+++ b/@miSim/miSim.m
@@ -0,0 +1,44 @@
+classdef miSim
+ % multiagent interconnection simulation
+
+ % Simulation parameters
+ properties (SetAccess = private, GetAccess = public)
+ timestep = NaN; % delta time interval for simulation iterations
+ partitioningFreq = NaN; % number of simulation timesteps at which the partitioning routine is re-run
+ maxIter = NaN; % maximum number of simulation iterations
+ domain = rectangularPrism;
+ objective = sensingObjective;
+ obstacles = cell(0, 1); % geometries that define obstacles within the domain
+ agents = cell(0, 1); % agents that move within the domain
+ adjacency = NaN; % Adjacency matrix representing communications network graph
+ partitioning = NaN;
+ end
+
+ properties (Access = private)
+ % Plot objects
+ connectionsPlot; % objects for lines connecting agents in spatial plots
+ graphPlot; % objects for abstract network graph plot
+ partitionPlot; % objects for partition plot
+
+ % Indicies for various plot types in the main tiled layout figure
+ spatialPlotIndices = [6, 4, 3, 2];
+ objectivePlotIndices = [6, 4];
+ networkGraphIndex = 5;
+ partitionGraphIndex = 1;
+ end
+
+ methods (Access = public)
+ [obj, f] = initialize(obj, domain, objective, agents, timestep, partitoningFreq, maxIter, obstacles);
+ [obj, f] = run(obj, f);
+ [obj] = partition(obj);
+ [obj] = updateAdjacency(obj);
+ [obj, f] = plot(obj);
+ [obj, f] = plotConnections(obj, ind, f);
+ [obj, f] = plotPartitions(obj, ind, f);
+ [obj, f] = plotGraph(obj, ind, f);
+ [obj, f] = updatePlots(obj, f, updatePartitions);
+ end
+ methods (Access = private)
+ [v] = setupVideoWriter(obj);
+ end
+end
\ No newline at end of file
diff --git a/@miSim/partition.m b/@miSim/partition.m
new file mode 100644
index 0000000..9383ea9
--- /dev/null
+++ b/@miSim/partition.m
@@ -0,0 +1,25 @@
+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 = cat(3, agentPerformances{:});
+
+ % Get highest performance value at each point
+ [~, idx] = max(agentPerformances, [], 3);
+
+ % Collect agent indices in the same way
+ agentInds = cellfun(@(x) x.index * ones(size(obj.objective.X)), obj.agents, 'UniformOutput', false);
+ agentInds = cat(3, agentInds{:});
+
+ % 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));
+end
\ No newline at end of file
diff --git a/@miSim/plot.m b/@miSim/plot.m
new file mode 100644
index 0000000..243b67f
--- /dev/null
+++ b/@miSim/plot.m
@@ -0,0 +1,41 @@
+function [obj, f] = plot(obj)
+ arguments (Input)
+ obj (1, 1) {mustBeA(obj, 'miSim')};
+ end
+ arguments (Output)
+ obj (1, 1) {mustBeA(obj, 'miSim')};
+ f (1, 1) {mustBeA(f, 'matlab.ui.Figure')};
+ end
+
+ % Plot domain
+ [obj.domain, f] = obj.domain.plotWireframe(obj.spatialPlotIndices);
+
+ % Plot obstacles
+ for ii = 1:size(obj.obstacles, 1)
+ [obj.obstacles{ii}, f] = obj.obstacles{ii}.plotWireframe(obj.spatialPlotIndices, f);
+ end
+
+ % Plot objective gradient
+ f = obj.objective.plot(obj.objectivePlotIndices, f);
+
+ % Plot agents and their collision geometries
+ for ii = 1:size(obj.agents, 1)
+ [obj.agents{ii}, f] = obj.agents{ii}.plot(obj.spatialPlotIndices, f);
+ end
+
+ % Plot communication links
+ [obj, f] = obj.plotConnections(obj.spatialPlotIndices, f);
+
+ % Plot abstract network graph
+ [obj, f] = obj.plotGraph(obj.networkGraphIndex, f);
+
+ % Plot domain partitioning
+ [obj, f] = obj.plotPartitions(obj.partitionGraphIndex, f);
+
+ % Enforce plot limits
+ for ii = 1:size(obj.spatialPlotIndices, 2)
+ xlim(f.Children(1).Children(obj.spatialPlotIndices(ii)), [obj.domain.minCorner(1), obj.domain.maxCorner(1)]);
+ ylim(f.Children(1).Children(obj.spatialPlotIndices(ii)), [obj.domain.minCorner(2), obj.domain.maxCorner(2)]);
+ zlim(f.Children(1).Children(obj.spatialPlotIndices(ii)), [obj.domain.minCorner(3), obj.domain.maxCorner(3)]);
+ end
+end
\ No newline at end of file
diff --git a/@miSim/plotConnections.m b/@miSim/plotConnections.m
new file mode 100644
index 0000000..7321a22
--- /dev/null
+++ b/@miSim/plotConnections.m
@@ -0,0 +1,45 @@
+function [obj, f] = plotConnections(obj, ind, f)
+ arguments (Input)
+ obj (1, 1) {mustBeA(obj, 'miSim')};
+ ind (1, :) double = NaN;
+ f (1, 1) {mustBeA(f, 'matlab.ui.Figure')} = figure;
+ end
+ arguments (Output)
+ obj (1, 1) {mustBeA(obj, 'miSim')};
+ f (1, 1) {mustBeA(f, 'matlab.ui.Figure')};
+ end
+
+ % Iterate over lower triangle off-diagonal region of the
+ % adjacency matrix to plot communications links between agents
+ X = []; Y = []; Z = [];
+ for ii = 2:size(obj.adjacency, 1)
+ for jj = 1:(ii - 1)
+ if obj.adjacency(ii, jj)
+ X = [X; obj.agents{ii}.pos(1), obj.agents{jj}.pos(1)];
+ Y = [Y; obj.agents{ii}.pos(2), obj.agents{jj}.pos(2)];
+ Z = [Z; obj.agents{ii}.pos(3), obj.agents{jj}.pos(3)];
+ end
+ end
+ end
+ X = X'; Y = Y'; Z = Z';
+
+ % Plot the connections
+ if isnan(ind)
+ hold(f.CurrentAxes, "on");
+ o = plot3(f.CurrentAxes, X, Y, Z, 'Color', 'g', 'LineWidth', 2, 'LineStyle', '--');
+ hold(f.CurrentAxes, "off");
+ else
+ hold(f.Children(1).Children(ind(1)), "on");
+ o = plot3(f.Children(1).Children(ind(1)), X, Y, Z, 'Color', 'g', 'LineWidth', 2, 'LineStyle', '--');
+ hold(f.Children(1).Children(ind(1)), "off");
+ end
+
+ % Copy to other plots
+ if size(ind, 2) > 1
+ for ii = 2:size(ind, 2)
+ o = [o, copyobj(o(:, 1), f.Children(1).Children(ind(ii)))];
+ end
+ end
+
+ obj.connectionsPlot = o;
+end
\ No newline at end of file
diff --git a/@miSim/plotGraph.m b/@miSim/plotGraph.m
new file mode 100644
index 0000000..6170e91
--- /dev/null
+++ b/@miSim/plotGraph.m
@@ -0,0 +1,31 @@
+function [obj, f] = plotGraph(obj, ind, f)
+ arguments (Input)
+ obj (1, 1) {mustBeA(obj, 'miSim')};
+ ind (1, :) double = NaN;
+ f (1, 1) {mustBeA(f, 'matlab.ui.Figure')} = figure;
+ end
+ arguments (Output)
+ obj (1, 1) {mustBeA(obj, 'miSim')};
+ f (1, 1) {mustBeA(f, 'matlab.ui.Figure')};
+ end
+
+ % Form graph from adjacency matrix
+ G = graph(obj.adjacency, 'omitselfloops');
+
+ % Plot graph object
+ if isnan(ind)
+ hold(f.CurrentAxes, 'on');
+ o = plot(f.CurrentAxes, G, 'LineStyle', '--', 'EdgeColor', 'g', 'NodeColor', 'k', 'LineWidth', 2);
+ hold(f.CurrentAxes, 'off');
+ else
+ hold(f.Children(1).Children(ind(1)), 'on');
+ o = plot(f.Children(1).Children(ind(1)), G, 'LineStyle', '--', 'EdgeColor', 'g', 'NodeColor', 'k', 'LineWidth', 2);
+ hold(f.Children(1).Children(ind(1)), 'off');
+ if size(ind, 2) > 1
+ for ii = 2:size(ind, 2)
+ o = [o; copyobj(o(1), f.Children(1).Children(ind(ii)))];
+ end
+ end
+ end
+ obj.graphPlot = o;
+end
\ No newline at end of file
diff --git a/@miSim/plotPartitions.m b/@miSim/plotPartitions.m
new file mode 100644
index 0000000..d5063b6
--- /dev/null
+++ b/@miSim/plotPartitions.m
@@ -0,0 +1,27 @@
+function [obj, f] = plotPartitions(obj, ind, f)
+ arguments (Input)
+ obj (1, 1) {mustBeA(obj, 'miSim')};
+ ind (1, :) double = NaN;
+ f (1, 1) {mustBeA(f, 'matlab.ui.Figure')} = figure;
+ end
+ arguments (Output)
+ obj (1, 1) {mustBeA(obj, 'miSim')};
+ f (1, 1) {mustBeA(f, 'matlab.ui.Figure')};
+ end
+
+ if isnan(ind)
+ hold(f.CurrentAxes, 'on');
+ o = imagesc(f.CurrentAxes, obj.partitioning);
+ hold(f.CurrentAxes, 'off');
+ else
+ hold(f.Children(1).Children(ind(1)), 'on');
+ o = imagesc(f.Children(1).Children(ind(1)), obj.partitioning);
+ hold(f.Children(1).Children(ind(1)), 'on');
+ if size(ind, 2) > 1
+ for ii = 2:size(ind, 2)
+ o = [o, copyobj(o(1), f.Children(1).Children(ind(ii)))];
+ end
+ end
+ end
+ obj.partitionPlot = o;
+end
\ No newline at end of file
diff --git a/@miSim/run.m b/@miSim/run.m
new file mode 100644
index 0000000..9b54400
--- /dev/null
+++ b/@miSim/run.m
@@ -0,0 +1,52 @@
+function [obj, f] = run(obj, f)
+ arguments (Input)
+ obj (1, 1) {mustBeA(obj, 'miSim')};
+ f (1, 1) {mustBeA(f, 'matlab.ui.Figure')} = figure;
+ end
+ arguments (Output)
+ obj (1, 1) {mustBeA(obj, 'miSim')};
+ f (1, 1) {mustBeA(f, 'matlab.ui.Figure')};
+ end
+
+ % Create axes if they don't already exist
+ f = firstPlotSetup(f);
+
+ % 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)
+ % Display current sim time
+ t = times(ii);
+ fprintf("Sim Time: %4.2f (%d/%d)\n", t, ii, obj.maxIter)
+
+ % Check if it's time for new partitions
+ updatePartitions = false;
+ if ismember(t, partitioningTimes)
+ updatePartitions = true;
+ obj = obj.partition();
+ end
+
+ % Iterate over agents to simulate their motion
+ for jj = 1:size(obj.agents, 1)
+ obj.agents{jj} = obj.agents{jj}.run(obj.objective, obj.domain, obj.partitioning);
+ end
+
+ % Update adjacency matrix
+ obj = obj.updateAdjacency;
+
+ % Update plots
+ [obj, f] = obj.updatePlots(f, updatePartitions);
+
+ % Write frame in to video
+ I = getframe(f);
+ v.writeVideo(I);
+ end
+
+ % Close video file
+ v.close();
+end
\ No newline at end of file
diff --git a/setupVideoWriter.m b/@miSim/setupVideoWriter.m
similarity index 79%
rename from setupVideoWriter.m
rename to @miSim/setupVideoWriter.m
index 0a464b7..f412a81 100644
--- a/setupVideoWriter.m
+++ b/@miSim/setupVideoWriter.m
@@ -1,6 +1,6 @@
-function v = setupVideoWriter(timestep)
+function v = setupVideoWriter(obj)
arguments (Input)
- timestep (1, 1) double;
+ obj (1, 1) {mustBeA(obj, 'miSim')};
end
arguments (Output)
v (1, 1) {mustBeA(v, 'VideoWriter')};
@@ -12,6 +12,6 @@ function v = setupVideoWriter(timestep)
v = VideoWriter(fullfile('sandbox', strcat(string(datetime('now'), 'yyyy_MM_dd_HH_mm_ss'), '_miSimHist')), 'Motion JPEG AVI');
end
- v.FrameRate = 1/timestep;
+ v.FrameRate = 1 / obj.timestep;
v.Quality = 90;
end
\ No newline at end of file
diff --git a/@miSim/updateAdjacency.m b/@miSim/updateAdjacency.m
new file mode 100644
index 0000000..09be91b
--- /dev/null
+++ b/@miSim/updateAdjacency.m
@@ -0,0 +1,32 @@
+function obj = updateAdjacency(obj)
+ arguments (Input)
+ obj (1, 1) {mustBeA(obj, 'miSim')};
+ end
+ arguments (Output)
+ obj (1, 1) {mustBeA(obj, 'miSim')};
+ end
+
+ % Initialize assuming only self-connections
+ A = logical(eye(size(obj.agents, 1)));
+
+ % Check lower triangle off-diagonal connections
+ for ii = 2:size(A, 1)
+ for jj = 1:(ii - 1)
+ if norm(obj.agents{ii}.pos - obj.agents{jj}.pos) <= min([obj.agents{ii}.comRange, obj.agents{jj}.comRange])
+ % Make sure that obstacles don't obstruct the line
+ % of sight, breaking the connection
+ for kk = 1:size(obj.obstacles, 1)
+ if ~obj.obstacles{kk}.containsLine(obj.agents{ii}.pos, obj.agents{jj}.pos)
+ A(ii, jj) = true;
+ end
+ end
+ % need extra handling for cases with no obstacles
+ if isempty(obj.obstacles)
+ A(ii, jj) = true;
+ end
+ end
+ end
+ end
+
+ obj.adjacency = A | A';
+end
\ No newline at end of file
diff --git a/@miSim/updatePlots.m b/@miSim/updatePlots.m
new file mode 100644
index 0000000..3ce6419
--- /dev/null
+++ b/@miSim/updatePlots.m
@@ -0,0 +1,43 @@
+function [obj, f] = updatePlots(obj, f, updatePartitions)
+ arguments (Input)
+ obj (1, 1) {mustBeA(obj, 'miSim')};
+ f (1, 1) {mustBeA(f, 'matlab.ui.Figure')} = figure;
+ updatePartitions (1, 1) logical = false;
+ end
+ arguments (Output)
+ obj (1, 1) {mustBeA(obj, 'miSim')};
+ f (1, 1) {mustBeA(f, 'matlab.ui.Figure')};
+ end
+
+ % Update agent positions, collision geometries
+ for ii = 1:size(obj.agents, 1)
+ 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
+ % re-plotting, which is much better for performance boost
+
+ % Update agent connections plot
+ delete(obj.connectionsPlot);
+ [obj, f] = obj.plotConnections(obj.spatialPlotIndices, f);
+
+ % Update network graph plot
+ delete(obj.graphPlot);
+ [obj, f] = obj.plotGraph(obj.networkGraphIndex, f);
+
+ % Update partitioning plot
+ if updatePartitions
+ delete(obj.partitionPlot);
+ [obj, f] = obj.plotPartitions(obj.partitionGraphIndex, f);
+ end
+
+ % reset plot limits to fit domain
+ for ii = 1:size(obj.spatialPlotIndices, 2)
+ xlim(f.Children(1).Children(obj.spatialPlotIndices(ii)), [obj.domain.minCorner(1), obj.domain.maxCorner(1)]);
+ ylim(f.Children(1).Children(obj.spatialPlotIndices(ii)), [obj.domain.minCorner(2), obj.domain.maxCorner(2)]);
+ zlim(f.Children(1).Children(obj.spatialPlotIndices(ii)), [obj.domain.minCorner(3), obj.domain.maxCorner(3)]);
+ end
+
+ drawnow;
+end
\ No newline at end of file
diff --git a/@sensingObjective/initialize.m b/@sensingObjective/initialize.m
new file mode 100644
index 0000000..1d51fb0
--- /dev/null
+++ b/@sensingObjective/initialize.m
@@ -0,0 +1,34 @@
+function obj = initialize(obj, objectiveFunction, footprint, groundAlt, discretizationStep)
+ arguments (Input)
+ obj (1,1) {mustBeA(obj, 'sensingObjective')};
+ objectiveFunction (1, 1) {mustBeA(objectiveFunction, 'function_handle')};
+ footprint (:, 2) double;
+ groundAlt (1, 1) double = 0;
+ discretizationStep (1, 1) double = 1;
+ end
+ arguments (Output)
+ obj (1,1) {mustBeA(obj, 'sensingObjective')};
+ end
+
+ obj.groundAlt = groundAlt;
+
+ % Extract footprint limits
+ xMin = min(footprint(:, 1));
+ xMax = max(footprint(:, 1));
+ yMin = min(footprint(:, 2));
+ yMax = max(footprint(:, 2));
+
+ xGrid = unique([xMin:discretizationStep:xMax, xMax]);
+ yGrid = unique([yMin:discretizationStep:yMax, yMax]);
+
+ % Store grid points for plotting later
+ [obj.X, obj.Y] = meshgrid(xGrid, yGrid);
+
+ % Evaluate function over grid points
+ obj.objectiveFunction = objectiveFunction;
+ obj.values = reshape(obj.objectiveFunction(obj.X, obj.Y), size(obj.X));
+
+ % store ground position
+ idx = obj.values == max(obj.values, [], "all");
+ obj.groundPos = [obj.X(idx), obj.Y(idx)];
+end
\ No newline at end of file
diff --git a/@sensingObjective/plot.m b/@sensingObjective/plot.m
new file mode 100644
index 0000000..b9adbc0
--- /dev/null
+++ b/@sensingObjective/plot.m
@@ -0,0 +1,36 @@
+function f = plot(obj, ind, f)
+ arguments (Input)
+ obj (1,1) {mustBeA(obj, 'sensingObjective')};
+ ind (1, :) double = NaN;
+ f (1,1) {mustBeA(f, 'matlab.ui.Figure')} = figure;
+ end
+ arguments (Output)
+ f (1,1) {mustBeA(f, 'matlab.ui.Figure')};
+ end
+
+ % Create axes if they don't already exist
+ f = firstPlotSetup(f);
+
+ % Plot gradient on the "floor" of the domain
+ if isnan(ind)
+ hold(f.CurrentAxes, "on");
+ o = surf(f.CurrentAxes, obj.X, obj.Y, repmat(obj.groundAlt, size(obj.X)), obj.values ./ max(obj.values, [], "all"), 'EdgeColor', 'none');
+ o.HitTest = 'off';
+ o.PickableParts = 'none';
+ hold(f.CurrentAxes, "off");
+
+ else
+ hold(f.Children(1).Children(ind(1)), "on");
+ o = surf(f.Children(1).Children(ind(1)), obj.X, obj.Y, repmat(obj.groundAlt, size(obj.X)), obj.values ./ max(obj.values, [], "all"), 'EdgeColor', 'none');
+ o.HitTest = 'off';
+ o.PickableParts = 'none';
+ hold(f.Children(1).Children(ind(1)), "off");
+ end
+
+ % Add to other perspectives
+ if size(ind, 2) > 1
+ for ii = 2:size(ind, 2)
+ copyobj(o, f.Children(1).Children(ind(ii)));
+ end
+ end
+end
\ No newline at end of file
diff --git a/@sensingObjective/sensingObjective.m b/@sensingObjective/sensingObjective.m
new file mode 100644
index 0000000..fbe865a
--- /dev/null
+++ b/@sensingObjective/sensingObjective.m
@@ -0,0 +1,18 @@
+classdef sensingObjective
+ % Sensing objective definition parent class
+ properties (SetAccess = private, GetAccess = public)
+ label = "";
+ groundAlt = 0;
+ groundPos = [0, 0];
+ discretizationStep = 1;
+ objectiveFunction = @(x, y) 0; % define objective functions over a grid in this manner
+ X = [];
+ Y = [];
+ values = [];
+ end
+
+ methods (Access = public)
+ [obj] = initialize(obj, objectiveFunction, footprint, groundAlt, discretizationStep);
+ [f ] = plot(obj, ind, f);
+ end
+end
\ No newline at end of file
diff --git a/agent.m b/agent.m
deleted file mode 100644
index 4ededba..0000000
--- a/agent.m
+++ /dev/null
@@ -1,167 +0,0 @@
-classdef agent
- properties (SetAccess = private, GetAccess = public)
- % Identifiers
- index = NaN;
- label = "";
-
- % Sensor
- sensorModel;
- sensingLength = 0.05; % length parameter used by sensing function
-
- % Guidance
- guidanceModel;
-
- % State
- lastPos = NaN(1, 3); % position from previous timestep
- pos = NaN(1, 3); % current position
- vel = NaN(1, 3); % current velocity
- pan = NaN; % pan angle
- tilt = NaN; % tilt angle
-
- % Collision
- collisionGeometry;
-
- % FOV cone
- fovGeometry;
-
- % Communication
- comRange = NaN;
-
- % Plotting
- scatterPoints;
- end
-
- methods (Access = public)
- function obj = initialize(obj, pos, vel, pan, tilt, collisionGeometry, sensorModel, guidanceModel, comRange, index, label)
- arguments (Input)
- obj (1, 1) {mustBeA(obj, 'agent')};
- pos (1, 3) double;
- vel (1, 3) double;
- pan (1, 1) double;
- tilt (1, 1) double;
- collisionGeometry (1, 1) {mustBeGeometry};
- sensorModel (1, 1) {mustBeSensor}
- guidanceModel (1, 1) {mustBeA(guidanceModel, 'function_handle')};
- comRange (1, 1) double = NaN;
- index (1, 1) double = NaN;
- label (1, 1) string = "";
- end
- arguments (Output)
- obj (1, 1) {mustBeA(obj, 'agent')};
- end
-
- obj.pos = pos;
- obj.vel = vel;
- obj.pan = pan;
- obj.tilt = tilt;
- obj.collisionGeometry = collisionGeometry;
- obj.sensorModel = sensorModel;
- obj.guidanceModel = guidanceModel;
- obj.comRange = comRange;
- obj.index = index;
- obj.label = label;
-
- % Initialize FOV cone
- obj.fovGeometry = cone;
- obj.fovGeometry = obj.fovGeometry.initialize([obj.pos(1:2), 0], tan(obj.sensorModel.alphaTilt) * obj.pos(3), obj.pos(3), REGION_TYPE.FOV, sprintf("%s FOV", obj.label));
- end
- function obj = run(obj, sensingObjective, domain, partitioning)
- arguments (Input)
- obj (1, 1) {mustBeA(obj, 'agent')};
- sensingObjective (1, 1) {mustBeA(sensingObjective, 'sensingObjective')};
- domain (1, 1) {mustBeGeometry};
- partitioning (:, :) double;
- end
- arguments (Output)
- obj (1, 1) {mustBeA(obj, 'agent')};
- end
-
- % Do sensing
- [sensedValues, sensedPositions] = obj.sensorModel.sense(obj, sensingObjective, domain, partitioning);
-
- % Determine next planned position
- nextPos = obj.guidanceModel(sensedValues, sensedPositions, obj.pos);
-
- % Move to next position
- % (dynamics not modeled at this time)
- obj.lastPos = obj.pos;
- obj.pos = nextPos;
-
- % Calculate movement
- d = obj.pos - obj.collisionGeometry.center;
-
- % Reinitialize collision geometry in the new position
- obj.collisionGeometry = obj.collisionGeometry.initialize([obj.collisionGeometry.minCorner; obj.collisionGeometry.maxCorner] + d, obj.collisionGeometry.tag, obj.collisionGeometry.label);
- end
- function updatePlots(obj)
- arguments (Input)
- obj (1, 1) {mustBeA(obj, 'agent')};
- end
- arguments (Output)
- end
-
- % Scatterplot point positions
- for ii = 1:size(obj.scatterPoints, 1)
- obj.scatterPoints(ii).XData = obj.pos(1);
- obj.scatterPoints(ii).YData = obj.pos(2);
- obj.scatterPoints(ii).ZData = obj.pos(3);
- end
-
- % Find change in agent position since last timestep
- deltaPos = obj.pos - obj.lastPos;
-
- % Collision geometry edges
- for jj = 1:size(obj.collisionGeometry.lines, 2)
- % Update plotting
- for ii = 1:size(obj.collisionGeometry.lines(:, jj), 1)
- obj.collisionGeometry.lines(ii, jj).XData = obj.collisionGeometry.lines(ii, jj).XData + deltaPos(1);
- obj.collisionGeometry.lines(ii, jj).YData = obj.collisionGeometry.lines(ii, jj).YData + deltaPos(2);
- obj.collisionGeometry.lines(ii, jj).ZData = obj.collisionGeometry.lines(ii, jj).ZData + deltaPos(3);
- end
- end
-
- % Update FOV geometry surfaces
- for jj = 1:size(obj.fovGeometry.surface, 2)
- % Update each plot
- obj.fovGeometry.surface(jj).XData = obj.fovGeometry.surface(jj).XData + deltaPos(1);
- obj.fovGeometry.surface(jj).YData = obj.fovGeometry.surface(jj).YData + deltaPos(2);
- obj.fovGeometry.surface(jj).ZData = obj.fovGeometry.surface(jj).ZData + deltaPos(3);
- end
- end
- function [obj, f] = plot(obj, ind, f)
- arguments (Input)
- obj (1, 1) {mustBeA(obj, 'agent')};
- ind (1, :) double = NaN;
- f (1, 1) {mustBeA(f, 'matlab.ui.Figure')} = figure;
- end
- arguments (Output)
- obj (1, 1) {mustBeA(obj, 'agent')};
- f (1, 1) {mustBeA(f, 'matlab.ui.Figure')};
- end
-
- % Create axes if they don't already exist
- f = firstPlotSetup(f);
-
- % Plot points representing the agent position
- hold(f.Children(1).Children(end), "on");
- o = scatter3(f.Children(1).Children(end), obj.pos(1), obj.pos(2), obj.pos(3), 'filled', 'ko', 'SizeData', 25);
- hold(f.Children(1).Children(end), "off");
-
- % Check if this is a tiled layout figure
- if strcmp(f.Children(1).Type, 'tiledlayout')
- % Add to other perspectives
- o = [o; copyobj(o(1), f.Children(1).Children(2))];
- o = [o; copyobj(o(1), f.Children(1).Children(3))];
- o = [o; copyobj(o(1), f.Children(1).Children(4))];
- end
-
- obj.scatterPoints = o;
-
- % Plot collision geometry
- [obj.collisionGeometry, f] = obj.collisionGeometry.plotWireframe(ind, f);
-
- % Plot FOV geometry
- [obj.fovGeometry, f] = obj.fovGeometry.plot(ind, f);
- end
- end
-end
\ No newline at end of file
diff --git a/geometries/@cone/cone.m b/geometries/@cone/cone.m
new file mode 100644
index 0000000..7ab0d47
--- /dev/null
+++ b/geometries/@cone/cone.m
@@ -0,0 +1,22 @@
+classdef cone
+ % Conical geometry
+ properties (SetAccess = private, GetAccess = public)
+ % Meta
+ tag = REGION_TYPE.INVALID;
+ label = "";
+
+ % Spatial
+ center = NaN;
+ radius = NaN;
+ height = NaN;
+
+ % Plotting
+ surface;
+ n = 32;
+ end
+
+ methods (Access = public)
+ [obj ] = initialize(obj, center, radius, height, tag, label);
+ [obj, f] = plot(obj, ind, f);
+ end
+end
\ No newline at end of file
diff --git a/geometries/@cone/initialize.m b/geometries/@cone/initialize.m
new file mode 100644
index 0000000..b3e25c1
--- /dev/null
+++ b/geometries/@cone/initialize.m
@@ -0,0 +1,19 @@
+function obj = initialize(obj, center, radius, height, tag, label)
+ arguments (Input)
+ obj (1, 1) {mustBeA(obj, 'cone')};
+ center (1, 3) double;
+ radius (1, 1) double;
+ height (1, 1) double;
+ tag (1, 1) REGION_TYPE = REGION_TYPE.INVALID;
+ label (1, 1) string = "";
+ end
+ arguments (Output)
+ obj (1, 1) {mustBeA(obj, 'cone')};
+ end
+
+ obj.center = center;
+ obj.radius = radius;
+ obj.height = height;
+ obj.tag = tag;
+ obj.label = label;
+end
\ No newline at end of file
diff --git a/geometries/@cone/plot.m b/geometries/@cone/plot.m
new file mode 100644
index 0000000..ad38d26
--- /dev/null
+++ b/geometries/@cone/plot.m
@@ -0,0 +1,43 @@
+function [obj, f] = plot(obj, ind, f)
+ arguments (Input)
+ obj (1, 1) {mustBeA(obj, 'cone')};
+ ind (1, :) double = NaN;
+ f (1, 1) {mustBeA(f, 'matlab.ui.Figure')} = figure;
+ end
+ arguments (Output)
+ obj (1, 1) {mustBeA(obj, 'cone')};
+ f (1, 1) {mustBeA(f, 'matlab.ui.Figure')};
+ end
+
+ % Create axes if they don't already exist
+ f = firstPlotSetup(f);
+
+ % Plot cone
+ [X, Y, Z] = cylinder([obj.radius, 0], obj.n);
+
+ % Scale to match height
+ Z = Z * obj.height;
+
+ % Move to center location
+ X = X + obj.center(1);
+ Y = Y + obj.center(2);
+ Z = Z + obj.center(3);
+
+ % Plot
+ if isnan(ind)
+ o = surf(f.CurrentAxes, X, Y, Z);
+ else
+ hold(f.Children(1).Children(ind(1)), "on");
+ o = surf(f.Children(1).Children(ind(1)), X, Y, Z, ones([size(Z), 1]) .* reshape(obj.tag.color, 1, 1, 3), 'FaceAlpha', 0.25, 'EdgeColor', 'none');
+ hold(f.Children(1).Children(ind(1)), "off");
+ end
+
+ % Copy to other requested tiles
+ if numel(ind) > 1
+ for ii = 2:size(ind, 2)
+ o = [o, copyobj(o(:, 1), f.Children(1).Children(ind(ii)))];
+ end
+ end
+
+ obj.surface = o;
+end
\ No newline at end of file
diff --git a/geometries/@rectangularPrism/contains.m b/geometries/@rectangularPrism/contains.m
new file mode 100644
index 0000000..363294d
--- /dev/null
+++ b/geometries/@rectangularPrism/contains.m
@@ -0,0 +1,10 @@
+function c = contains(obj, pos)
+ arguments (Input)
+ obj (1, 1) {mustBeA(obj, 'rectangularPrism')};
+ pos (:, 3) double;
+ end
+ arguments (Output)
+ c (:, 1) logical
+ end
+ c = all(pos >= repmat(obj.minCorner, size(pos, 1), 1), 2) & all(pos <= repmat(obj.maxCorner, size(pos, 1), 1), 2);
+end
\ No newline at end of file
diff --git a/geometries/@rectangularPrism/containsLine.m b/geometries/@rectangularPrism/containsLine.m
new file mode 100644
index 0000000..2e2194f
--- /dev/null
+++ b/geometries/@rectangularPrism/containsLine.m
@@ -0,0 +1,41 @@
+function c = containsLine(obj, pos1, pos2)
+ arguments (Input)
+ obj (1, 1) {mustBeA(obj, 'rectangularPrism')};
+ pos1 (1, 3) double;
+ pos2 (1, 3) double;
+ end
+ arguments (Output)
+ c (1, 1) logical
+ end
+
+ d = pos2 - pos1;
+
+ % edge case where the line is parallel to the geometry
+ if abs(d) < 1e-12
+ % check if it happens to start or end inside or outside of
+ % the geometry
+ if obj.contains(pos1) || obj.contains(pos2)
+ c = true;
+ else
+ c = false;
+ end
+ return;
+ end
+
+ tmin = -inf;
+ tmax = inf;
+
+ % Standard case
+ for ii = 1:3
+ t1 = (obj.minCorner(ii) - pos1(ii)) / d(ii);
+ t2 = (obj.maxCorner(ii) - pos2(ii)) / d(ii);
+ tmin = max(tmin, min(t1, t2));
+ tmax = min(tmax, max(t1, t2));
+ if tmin > tmax
+ c = false;
+ return;
+ end
+ end
+
+ c = (tmax >= 0) && (tmin <= 1);
+ end
\ No newline at end of file
diff --git a/geometries/@rectangularPrism/distance.m b/geometries/@rectangularPrism/distance.m
new file mode 100644
index 0000000..80caad6
--- /dev/null
+++ b/geometries/@rectangularPrism/distance.m
@@ -0,0 +1,32 @@
+function d = distance(obj, pos)
+ arguments (Input)
+ obj (1, 1) {mustBeA(obj, 'rectangularPrism')};
+ pos (:, 3) double;
+ end
+ arguments (Output)
+ d (:, 1) double
+ end
+ if obj.contains(pos)
+ % Queried point is inside geometry
+ % find minimum distance to any face
+ d = min([pos(1) - obj.minCorner(1), ...
+ pos(2) - obj.minCorner(2), ...
+ pos(3) - obj.minCorner(3), ...
+ obj.maxCorner(1) - pos(1), ...
+ obj.maxCorner(2) - pos(2), ...
+ obj.maxCorner(3) - pos(3)]);
+ else
+ % Queried point is outside geometry
+ cPos = NaN(1, 3);
+ for ii = 1:3
+ if pos(ii) < obj.minCorner(ii)
+ cPos(ii) = obj.minCorner(ii);
+ elseif pos(ii) > obj.maxCorner(ii)
+ cPos(ii) = obj.maxCorner(ii);
+ else
+ cPos(ii) = pos(ii);
+ end
+ end
+ d = norm(cPos - pos);
+ end
+end
\ No newline at end of file
diff --git a/geometries/@rectangularPrism/initialize.m b/geometries/@rectangularPrism/initialize.m
new file mode 100644
index 0000000..a09d510
--- /dev/null
+++ b/geometries/@rectangularPrism/initialize.m
@@ -0,0 +1,40 @@
+function obj = initialize(obj, bounds, tag, label)
+ arguments (Input)
+ obj (1, 1) {mustBeA(obj, 'rectangularPrism')};
+ bounds (2, 3) double;
+ tag (1, 1) REGION_TYPE = REGION_TYPE.INVALID;
+ label (1, 1) string = "";
+ end
+ arguments (Output)
+ obj (1, 1) {mustBeA(obj, 'rectangularPrism')};
+ end
+
+ obj.tag = tag;
+ obj.label = label;
+
+ %% Define geometry bounds by LL corner and UR corner
+ obj.minCorner = bounds(1, 1:3);
+ obj.maxCorner = bounds(2, 1:3);
+
+ % Compute L, W, H
+ obj.dimensions = [obj.maxCorner(1) - obj.minCorner(1), obj.maxCorner(2) - obj.minCorner(2), obj.maxCorner(3) - obj.minCorner(3)];
+
+ % Compute center
+ obj.center = obj.minCorner + obj.dimensions ./ 2;
+
+ % Compute vertices
+ obj.vertices = [obj.minCorner;
+ obj.maxCorner(1), obj.minCorner(2:3);
+ obj.maxCorner(1:2), obj.minCorner(3);
+ obj.minCorner(1), obj.maxCorner(2), obj.minCorner(3);
+ obj.minCorner(1:2), obj.maxCorner(3);
+ obj.maxCorner(1), obj.minCorner(2), obj.maxCorner(3);
+ obj.minCorner(1), obj.maxCorner(2:3)
+ obj.maxCorner;];
+
+ % Compute footprint
+ obj.footprint = [obj.minCorner(1:2); ...
+ [obj.minCorner(1), obj.maxCorner(2)]; ...
+ [obj.maxCorner(1), obj.minCorner(2)]; ...
+ obj.maxCorner(1:2)];
+end
\ No newline at end of file
diff --git a/geometries/@rectangularPrism/plotWireframe.m b/geometries/@rectangularPrism/plotWireframe.m
new file mode 100644
index 0000000..d54304e
--- /dev/null
+++ b/geometries/@rectangularPrism/plotWireframe.m
@@ -0,0 +1,37 @@
+function [obj, f] = plotWireframe(obj, ind, f)
+ arguments (Input)
+ obj (1, 1) {mustBeA(obj, 'rectangularPrism')};
+ ind (1, :) double = NaN;
+ f (1, 1) {mustBeA(f, 'matlab.ui.Figure')} = figure;
+ end
+ arguments (Output)
+ obj (1, 1) {mustBeA(obj, 'rectangularPrism')};
+ f (1, 1) {mustBeA(f, 'matlab.ui.Figure')};
+ end
+
+ % Create axes if they don't already exist
+ f = firstPlotSetup(f);
+
+ % Create plotting inputs from vertices and edges
+ X = [obj.vertices(obj.edges(:,1),1), obj.vertices(obj.edges(:,2),1)]';
+ Y = [obj.vertices(obj.edges(:,1),2), obj.vertices(obj.edges(:,2),2)]';
+ Z = [obj.vertices(obj.edges(:,1),3), obj.vertices(obj.edges(:,2),3)]';
+
+ % Plot the boundaries of the geometry into 3D view
+ if isnan(ind)
+ o = plot3(f.CurrentAxes, X, Y, Z, '-', 'Color', obj.tag.color, 'LineWidth', 2);
+ else
+ hold(f.Children(1).Children(ind(1)), "on");
+ o = plot3(f.Children(1).Children(ind(1)), X, Y, Z, '-', 'Color', obj.tag.color, 'LineWidth', 2);
+ hold(f.Children(1).Children(ind(1)), "off");
+ end
+
+ % Copy to other requested tiles
+ if numel(ind) > 1
+ for ii = 2:size(ind, 2)
+ o = [o, copyobj(o(:, 1), f.Children(1).Children(ind(ii)))];
+ end
+ end
+
+ obj.lines = o;
+end
\ No newline at end of file
diff --git a/geometries/@rectangularPrism/random.m b/geometries/@rectangularPrism/random.m
new file mode 100644
index 0000000..a41ebd3
--- /dev/null
+++ b/geometries/@rectangularPrism/random.m
@@ -0,0 +1,9 @@
+function r = random(obj)
+ arguments (Input)
+ obj (1, 1) {mustBeA(obj, 'rectangularPrism')};
+ end
+ arguments (Output)
+ r (1, 3) double
+ end
+ r = (obj.vertices(1, 1:3) + rand(1, 3) .* obj.vertices(8, 1:3) - obj.vertices(1, 1:3))';
+end
\ No newline at end of file
diff --git a/geometries/@rectangularPrism/rectangularPrism.m b/geometries/@rectangularPrism/rectangularPrism.m
new file mode 100644
index 0000000..f0928e1
--- /dev/null
+++ b/geometries/@rectangularPrism/rectangularPrism.m
@@ -0,0 +1,33 @@
+classdef rectangularPrism
+ % Rectangular prism geometry
+ properties (SetAccess = private, GetAccess = public)
+ % Meta
+ tag = REGION_TYPE.INVALID;
+ label = "";
+
+ % Spatial
+ minCorner = NaN(1, 3);
+ maxCorner = NaN(1, 3);
+ dimensions = NaN(1, 3);
+ center = NaN;
+ footprint = NaN(4, 2);
+
+ % Graph
+ vertices = NaN(8, 3);
+ edges = [1 2; 2 3; 3 4; 4 1; % bottom square
+ 5 6; 6 8; 8 7; 7 5; % top square
+ 1 5; 2 6; 3 8; 4 7]; % vertical edges
+
+ % Plotting
+ lines;
+ end
+
+ methods (Access = public)
+ [obj ] = initialize(obj, bounds, tag, label);
+ [r ] = random(obj);
+ [c ] = contains(obj, pos);
+ [d ] = distance(obj, pos);
+ [c ] = containsLine(obj, pos1, pos2);
+ [obj, f] = plotWireframe(obj, ind, f);
+ end
+end
\ No newline at end of file
diff --git a/geometries/cone.m b/geometries/cone.m
deleted file mode 100644
index 52bba95..0000000
--- a/geometries/cone.m
+++ /dev/null
@@ -1,82 +0,0 @@
-classdef cone
- % Conical geometry
- properties (SetAccess = private, GetAccess = public)
- % Meta
- tag = REGION_TYPE.INVALID;
- label = "";
-
- % Spatial
- center = NaN;
- radius = NaN;
- height = NaN;
-
- % Plotting
- surface;
- n = 32;
- end
-
- methods
- function obj = initialize(obj, center, radius, height, tag, label)
- arguments (Input)
- obj (1, 1) {mustBeA(obj, 'cone')};
- center (1, 3) double;
- radius (1, 1) double;
- height (1, 1) double;
- tag (1, 1) REGION_TYPE = REGION_TYPE.INVALID;
- label (1, 1) string = "";
- end
- arguments (Output)
- obj (1, 1) {mustBeA(obj, 'cone')};
- end
-
- obj.center = center;
- obj.radius = radius;
- obj.height = height;
- obj.tag = tag;
- obj.label = label;
- end
- function [obj, f] = plot(obj, ind, f)
- arguments (Input)
- obj (1, 1) {mustBeA(obj, 'cone')};
- ind (1, :) double = NaN;
- f (1, 1) {mustBeA(f, 'matlab.ui.Figure')} = figure;
- end
- arguments (Output)
- obj (1, 1) {mustBeA(obj, 'cone')};
- f (1, 1) {mustBeA(f, 'matlab.ui.Figure')};
- end
-
- % Create axes if they don't already exist
- f = firstPlotSetup(f);
-
- % Plot cone
- [X, Y, Z] = cylinder([obj.radius, 0], obj.n);
-
- % Scale to match height
- Z = Z * obj.height;
-
- % Move to center location
- X = X + obj.center(1);
- Y = Y + obj.center(2);
- Z = Z + obj.center(3);
-
- % Plot
- if isnan(ind)
- o = surf(f.CurrentAxes, X, Y, Z);
- else
- hold(f.Children(1).Children(ind(1)), "on");
- o = surf(f.Children(1).Children(ind(1)), X, Y, Z, ones([size(Z), 1]) .* reshape(obj.tag.color, 1, 1, 3), 'FaceAlpha', 0.25, 'EdgeColor', 'none');
- hold(f.Children(1).Children(ind(1)), "off");
- end
-
- % Copy to other requested tiles
- if numel(ind) > 1
- for ii = 2:size(ind, 2)
- o = [o, copyobj(o(:, 1), f.Children(1).Children(ind(ii)))];
- end
- end
-
- obj.surface = o;
- end
- end
-end
\ No newline at end of file
diff --git a/geometries/rectangularPrism.m b/geometries/rectangularPrism.m
deleted file mode 100644
index 414bd3e..0000000
--- a/geometries/rectangularPrism.m
+++ /dev/null
@@ -1,204 +0,0 @@
-classdef rectangularPrism
- % Rectangular prism geometry
- properties (SetAccess = private, GetAccess = public)
- % Meta
- tag = REGION_TYPE.INVALID;
- label = "";
-
- % Spatial
- minCorner = NaN(1, 3);
- maxCorner = NaN(1, 3);
- dimensions = NaN(1, 3);
- center = NaN;
- footprint = NaN(4, 2);
-
- % Graph
- vertices = NaN(8, 3);
- edges = [1 2; 2 3; 3 4; 4 1; % bottom square
- 5 6; 6 8; 8 7; 7 5; % top square
- 1 5; 2 6; 3 8; 4 7]; % vertical edges
-
- % Plotting
- lines;
- end
-
- methods (Access = public)
- function obj = initialize(obj, bounds, tag, label)
- arguments (Input)
- obj (1, 1) {mustBeA(obj, 'rectangularPrism')};
- bounds (2, 3) double;
- tag (1, 1) REGION_TYPE = REGION_TYPE.INVALID;
- label (1, 1) string = "";
- end
- arguments (Output)
- obj (1, 1) {mustBeA(obj, 'rectangularPrism')};
- end
-
- obj.tag = tag;
- obj.label = label;
-
- %% Define geometry bounds by LL corner and UR corner
- obj.minCorner = bounds(1, 1:3);
- obj.maxCorner = bounds(2, 1:3);
-
- % Compute L, W, H
- obj.dimensions = [obj.maxCorner(1) - obj.minCorner(1), obj.maxCorner(2) - obj.minCorner(2), obj.maxCorner(3) - obj.minCorner(3)];
-
- % Compute center
- obj.center = obj.minCorner + obj.dimensions ./ 2;
-
- % Compute vertices
- obj.vertices = [obj.minCorner;
- obj.maxCorner(1), obj.minCorner(2:3);
- obj.maxCorner(1:2), obj.minCorner(3);
- obj.minCorner(1), obj.maxCorner(2), obj.minCorner(3);
- obj.minCorner(1:2), obj.maxCorner(3);
- obj.maxCorner(1), obj.minCorner(2), obj.maxCorner(3);
- obj.minCorner(1), obj.maxCorner(2:3)
- obj.maxCorner;];
-
- % Compute footprint
- obj.footprint = [obj.minCorner(1:2); ...
- [obj.minCorner(1), obj.maxCorner(2)]; ...
- [obj.maxCorner(1), obj.minCorner(2)]; ...
- obj.maxCorner(1:2)];
- end
- function r = random(obj)
- arguments (Input)
- obj (1, 1) {mustBeA(obj, 'rectangularPrism')};
- end
- arguments (Output)
- r (1, 3) double
- end
- r = (obj.vertices(1, 1:3) + rand(1, 3) .* obj.vertices(8, 1:3) - obj.vertices(1, 1:3))';
- end
- function d = distance(obj, pos)
- arguments (Input)
- obj (1, 1) {mustBeA(obj, 'rectangularPrism')};
- pos (:, 3) double;
- end
- arguments (Output)
- d (:, 1) double
- end
- assert(~obj.contains(pos), "Cannot determine distance for a point inside of the geometry");
-
- cPos = NaN(1, 3);
- for ii = 1:3
- if pos(ii) < obj.minCorner(ii)
- cPos(ii) = obj.minCorner(ii);
- elseif pos(ii) > obj.maxCorner(ii)
- cPos(ii) = obj.maxCorner(ii);
- else
- cPos(ii) = pos(ii);
- end
- end
- d = norm(cPos - pos);
- end
- function d = interiorDistance(obj, pos)
- arguments (Input)
- obj (1, 1) {mustBeA(obj, 'rectangularPrism')};
- pos (:, 3) double;
- end
- arguments (Output)
- d (:, 1) double
- end
- assert(obj.contains(pos), "Cannot determine interior distance for a point outside of the geometry");
-
- % find minimum distance to any face
- d = min([pos(1) - obj.minCorner(1), ...
- pos(2) - obj.minCorner(2), ...
- pos(3) - obj.minCorner(3), ...
- obj.maxCorner(1) - pos(1), ...
- obj.maxCorner(2) - pos(2), ...
- obj.maxCorner(3) - pos(3)]);
- end
- function c = contains(obj, pos)
- arguments (Input)
- obj (1, 1) {mustBeA(obj, 'rectangularPrism')};
- pos (:, 3) double;
- end
- arguments (Output)
- c (:, 1) logical
- end
- c = all(pos >= repmat(obj.minCorner, size(pos, 1), 1), 2) & all(pos <= repmat(obj.maxCorner, size(pos, 1), 1), 2);
- end
- function c = containsLine(obj, pos1, pos2)
- arguments (Input)
- obj (1, 1) {mustBeA(obj, 'rectangularPrism')};
- pos1 (1, 3) double;
- pos2 (1, 3) double;
- end
- arguments (Output)
- c (1, 1) logical
- end
-
- d = pos2 - pos1;
-
- % edge case where the line is parallel to the geometry
- if abs(d) < 1e-12
- % check if it happens to start or end inside or outside of
- % the geometry
- if obj.contains(pos1) || obj.contains(pos2)
- c = true;
- else
- c = false;
- end
- return;
- end
-
- tmin = -inf;
- tmax = inf;
-
- % Standard case
- for ii = 1:3
- t1 = (obj.minCorner(ii) - pos1(ii)) / d(ii);
- t2 = (obj.maxCorner(ii) - pos2(ii)) / d(ii);
- tmin = max(tmin, min(t1, t2));
- tmax = min(tmax, max(t1, t2));
- if tmin > tmax
- c = false;
- return;
- end
- end
-
- c = (tmax >= 0) && (tmin <= 1);
- end
- function [obj, f] = plotWireframe(obj, ind, f)
- arguments (Input)
- obj (1, 1) {mustBeA(obj, 'rectangularPrism')};
- ind (1, :) double = NaN;
- f (1, 1) {mustBeA(f, 'matlab.ui.Figure')} = figure;
- end
- arguments (Output)
- obj (1, 1) {mustBeA(obj, 'rectangularPrism')};
- f (1, 1) {mustBeA(f, 'matlab.ui.Figure')};
- end
-
- % Create axes if they don't already exist
- f = firstPlotSetup(f);
-
- % Create plotting inputs from vertices and edges
- X = [obj.vertices(obj.edges(:,1),1), obj.vertices(obj.edges(:,2),1)]';
- Y = [obj.vertices(obj.edges(:,1),2), obj.vertices(obj.edges(:,2),2)]';
- Z = [obj.vertices(obj.edges(:,1),3), obj.vertices(obj.edges(:,2),3)]';
-
- % Plot the boundaries of the geometry into 3D view
- if isnan(ind)
- o = plot3(f.CurrentAxes, X, Y, Z, '-', 'Color', obj.tag.color, 'LineWidth', 2);
- else
- hold(f.Children(1).Children(ind(1)), "on");
- o = plot3(f.Children(1).Children(ind(1)), X, Y, Z, '-', 'Color', obj.tag.color, 'LineWidth', 2);
- hold(f.Children(1).Children(ind(1)), "off");
- end
-
- % Copy to other requested tiles
- if numel(ind) > 1
- for ii = 2:size(ind, 2)
- o = [o, copyobj(o(:, 1), f.Children(1).Children(ind(ii)))];
- end
- end
-
- obj.lines = o;
- end
- end
-end
\ No newline at end of file
diff --git a/miSim.m b/miSim.m
deleted file mode 100644
index d7206be..0000000
--- a/miSim.m
+++ /dev/null
@@ -1,386 +0,0 @@
-classdef miSim
- % multiagent interconnection simulation
-
- % Simulation parameters
- properties (SetAccess = private, GetAccess = public)
- timestep = NaN; % delta time interval for simulation iterations
- partitioningFreq = NaN; % number of simulation timesteps at which the partitioning routine is re-run
- maxIter = NaN; % maximum number of simulation iterations
- domain = rectangularPrism;
- objective = sensingObjective;
- obstacles = cell(0, 1); % geometries that define obstacles within the domain
- agents = cell(0, 1); % agents that move within the domain
- adjacency = NaN; % Adjacency matrix representing communications network graph
- partitioning = NaN;
- end
-
- properties (Access = private)
- % Plot objects
- connectionsPlot; % objects for lines connecting agents in spatial plots
- graphPlot; % objects for abstract network graph plot
- partitionPlot; % objects for partition plot
-
- % Indicies for various plot types in the main tiled layout figure
- spatialPlotIndices = [6, 4, 3, 2];
- objectivePlotIndices = [6, 4];
- networkGraphIndex = 5;
- partitionGraphIndex = 1;
- end
-
- methods (Access = public)
- function [obj, f] = initialize(obj, domain, objective, agents, timestep, partitoningFreq, maxIter, obstacles)
- arguments (Input)
- obj (1, 1) {mustBeA(obj, 'miSim')};
- domain (1, 1) {mustBeGeometry};
- objective (1, 1) {mustBeA(objective, 'sensingObjective')};
- agents (:, 1) cell;
- timestep (:, 1) double = 0.05;
- partitoningFreq (:, 1) double = 0.25
- maxIter (:, 1) double = 1000;
- obstacles (:, 1) cell {mustBeGeometry} = cell(0, 1);
- end
- arguments (Output)
- obj (1, 1) {mustBeA(obj, 'miSim')};
- f (1, 1) {mustBeA(f, 'matlab.ui.Figure')};
- end
-
- % Define simulation time parameters
- obj.timestep = timestep;
- obj.maxIter = maxIter;
-
- % Define domain
- obj.domain = domain;
- obj.partitioningFreq = partitoningFreq;
-
- % Add geometries representing obstacles within the domain
- obj.obstacles = obstacles;
-
- % Define objective
- obj.objective = objective;
-
- % Define agents
- obj.agents = agents;
-
- % Compute adjacency matrix
- obj = obj.updateAdjacency();
-
- % Create initial partitioning
- obj = obj.partition();
-
- % Set up initial plot
- % Set up axes arrangement
- % Plot domain
- [obj.domain, f] = obj.domain.plotWireframe(obj.spatialPlotIndices);
-
- % Plot obstacles
- for ii = 1:size(obj.obstacles, 1)
- [obj.obstacles{ii}, f] = obj.obstacles{ii}.plotWireframe(obj.spatialPlotIndices, f);
- end
-
- % Plot objective gradient
- f = obj.objective.plot(obj.objectivePlotIndices, f);
-
- % Plot agents and their collision geometries
- for ii = 1:size(obj.agents, 1)
- [obj.agents{ii}, f] = obj.agents{ii}.plot(obj.spatialPlotIndices, f);
- end
-
- % Plot communication links
- [obj, f] = obj.plotConnections(obj.spatialPlotIndices, f);
-
- % Plot abstract network graph
- [obj, f] = obj.plotGraph(obj.networkGraphIndex, f);
-
- % Plot domain partitioning
- [obj, f] = obj.plotPartitions(obj.partitionGraphIndex, f);
-
- % Enforce plot limits
- for ii = 1:size(obj.spatialPlotIndices, 2)
- xlim(f.Children(1).Children(obj.spatialPlotIndices(ii)), [obj.domain.minCorner(1), obj.domain.maxCorner(1)]);
- ylim(f.Children(1).Children(obj.spatialPlotIndices(ii)), [obj.domain.minCorner(2), obj.domain.maxCorner(2)]);
- zlim(f.Children(1).Children(obj.spatialPlotIndices(ii)), [obj.domain.minCorner(3), obj.domain.maxCorner(3)]);
- end
- end
- function [obj, f] = run(obj, f)
- arguments (Input)
- obj (1, 1) {mustBeA(obj, 'miSim')};
- f (1, 1) {mustBeA(f, 'matlab.ui.Figure')} = figure;
- end
- arguments (Output)
- obj (1, 1) {mustBeA(obj, 'miSim')};
- f (1, 1) {mustBeA(f, 'matlab.ui.Figure')};
- end
-
- % Create axes if they don't already exist
- f = firstPlotSetup(f);
-
- % 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 = setupVideoWriter(obj.timestep);
- v.open();
-
- for ii = 1:size(times, 1)
- % Display current sim time
- t = times(ii);
- fprintf("Sim Time: %4.2f (%d/%d)\n", t, ii, obj.maxIter)
-
- % Check if it's time for new partitions
- updatePartitions = false;
- if ismember(t, partitioningTimes)
- updatePartitions = true;
- obj = obj.partition();
- end
-
- % Iterate over agents to simulate their motion
- for jj = 1:size(obj.agents, 1)
- obj.agents{jj} = obj.agents{jj}.run(obj.objective, obj.domain, obj.partitioning);
- end
-
- % Update adjacency matrix
- obj = obj.updateAdjacency;
-
- % Update plots
- [obj, f] = obj.updatePlots(f, updatePartitions);
-
- % Write frame in to video
- I = getframe(f);
- v.writeVideo(I);
- end
-
- % Close video file
- v.close();
- end
- 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 = cat(3, agentPerformances{:});
-
- % Get highest performance value at each point
- [~, idx] = max(agentPerformances, [], 3);
-
- % Collect agent indices in the same way
- agentInds = cellfun(@(x) x.index * ones(size(obj.objective.X)), obj.agents, 'UniformOutput', false);
- agentInds = cat(3, agentInds{:});
-
- % 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));
- end
- function [obj, f] = updatePlots(obj, f, updatePartitions)
- arguments (Input)
- obj (1, 1) {mustBeA(obj, 'miSim')};
- f (1, 1) {mustBeA(f, 'matlab.ui.Figure')} = figure;
- updatePartitions (1, 1) logical = false;
- end
- arguments (Output)
- obj (1, 1) {mustBeA(obj, 'miSim')};
- f (1, 1) {mustBeA(f, 'matlab.ui.Figure')};
- end
-
- % Update agent positions, collision geometries
- for ii = 1:size(obj.agents, 1)
- 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
- % re-plotting, which is much better for performance boost
-
- % Update agent connections plot
- delete(obj.connectionsPlot);
- [obj, f] = obj.plotConnections(obj.spatialPlotIndices, f);
-
- % Update network graph plot
- delete(obj.graphPlot);
- [obj, f] = obj.plotGraph(obj.networkGraphIndex, f);
-
- % Update partitioning plot
- if updatePartitions
- delete(obj.partitionPlot);
- [obj, f] = obj.plotPartitions(obj.partitionGraphIndex, f);
- end
-
- % reset plot limits to fit domain
- for ii = 1:size(obj.spatialPlotIndices, 2)
- xlim(f.Children(1).Children(obj.spatialPlotIndices(ii)), [obj.domain.minCorner(1), obj.domain.maxCorner(1)]);
- ylim(f.Children(1).Children(obj.spatialPlotIndices(ii)), [obj.domain.minCorner(2), obj.domain.maxCorner(2)]);
- zlim(f.Children(1).Children(obj.spatialPlotIndices(ii)), [obj.domain.minCorner(3), obj.domain.maxCorner(3)]);
- end
-
- drawnow;
- end
- function obj = updateAdjacency(obj)
- arguments (Input)
- obj (1, 1) {mustBeA(obj, 'miSim')};
- end
- arguments (Output)
- obj (1, 1) {mustBeA(obj, 'miSim')};
- end
-
- % Initialize assuming only self-connections
- A = logical(eye(size(obj.agents, 1)));
-
- % Check lower triangle off-diagonal connections
- for ii = 2:size(A, 1)
- for jj = 1:(ii - 1)
- if norm(obj.agents{ii}.pos - obj.agents{jj}.pos) <= min([obj.agents{ii}.comRange, obj.agents{jj}.comRange])
- % Make sure that obstacles don't obstruct the line
- % of sight, breaking the connection
- for kk = 1:size(obj.obstacles, 1)
- if ~obj.obstacles{kk}.containsLine(obj.agents{ii}.pos, obj.agents{jj}.pos)
- A(ii, jj) = true;
- end
- end
- % need extra handling for cases with no obstacles
- if isempty(obj.obstacles)
- A(ii, jj) = true;
- end
- end
- end
- end
-
- obj.adjacency = A | A';
- end
- function [obj, f] = plotConnections(obj, ind, f)
- arguments (Input)
- obj (1, 1) {mustBeA(obj, 'miSim')};
- ind (1, :) double = NaN;
- f (1, 1) {mustBeA(f, 'matlab.ui.Figure')} = figure;
- end
- arguments (Output)
- obj (1, 1) {mustBeA(obj, 'miSim')};
- f (1, 1) {mustBeA(f, 'matlab.ui.Figure')};
- end
-
- % Iterate over lower triangle off-diagonal region of the
- % adjacency matrix to plot communications links between agents
- X = []; Y = []; Z = [];
- for ii = 2:size(obj.adjacency, 1)
- for jj = 1:(ii - 1)
- if obj.adjacency(ii, jj)
- X = [X; obj.agents{ii}.pos(1), obj.agents{jj}.pos(1)];
- Y = [Y; obj.agents{ii}.pos(2), obj.agents{jj}.pos(2)];
- Z = [Z; obj.agents{ii}.pos(3), obj.agents{jj}.pos(3)];
- end
- end
- end
- X = X'; Y = Y'; Z = Z';
-
- % Plot the connections
- if isnan(ind)
- hold(f.CurrentAxes, "on");
- o = plot3(f.CurrentAxes, X, Y, Z, 'Color', 'g', 'LineWidth', 2, 'LineStyle', '--');
- hold(f.CurrentAxes, "off");
- else
- hold(f.Children(1).Children(ind(1)), "on");
- o = plot3(f.Children(1).Children(ind(1)), X, Y, Z, 'Color', 'g', 'LineWidth', 2, 'LineStyle', '--');
- hold(f.Children(1).Children(ind(1)), "off");
- end
-
- % Copy to other plots
- if size(ind, 2) > 1
- for ii = 2:size(ind, 2)
- o = [o, copyobj(o(:, 1), f.Children(1).Children(ind(ii)))];
- end
- end
-
- obj.connectionsPlot = o;
- end
- function [obj, f] = plotPartitions(obj, ind, f)
- arguments (Input)
- obj (1, 1) {mustBeA(obj, 'miSim')};
- ind (1, :) double = NaN;
- f (1, 1) {mustBeA(f, 'matlab.ui.Figure')} = figure;
- end
- arguments (Output)
- obj (1, 1) {mustBeA(obj, 'miSim')};
- f (1, 1) {mustBeA(f, 'matlab.ui.Figure')};
- end
-
- if isnan(ind)
- hold(f.CurrentAxes, 'on');
- o = imagesc(f.CurrentAxes, obj.partitioning);
- hold(f.CurrentAxes, 'off');
- else
- hold(f.Children(1).Children(ind(1)), 'on');
- o = imagesc(f.Children(1).Children(ind(1)), obj.partitioning);
- hold(f.Children(1).Children(ind(1)), 'on');
- if size(ind, 2) > 1
- for ii = 2:size(ind, 2)
- o = [o, copyobj(o(1), f.Children(1).Children(ind(ii)))];
- end
- end
- end
- obj.partitionPlot = o;
-
- end
- function [obj, f] = plotGraph(obj, ind, f)
- arguments (Input)
- obj (1, 1) {mustBeA(obj, 'miSim')};
- ind (1, :) double = NaN;
- f (1, 1) {mustBeA(f, 'matlab.ui.Figure')} = figure;
- end
- arguments (Output)
- obj (1, 1) {mustBeA(obj, 'miSim')};
- f (1, 1) {mustBeA(f, 'matlab.ui.Figure')};
- end
-
- % Form graph from adjacency matrix
- G = graph(obj.adjacency, 'omitselfloops');
-
- % Plot graph object
- if isnan(ind)
- hold(f.CurrentAxes, 'on');
- o = plot(f.CurrentAxes, G, 'LineStyle', '--', 'EdgeColor', 'g', 'NodeColor', 'k', 'LineWidth', 2);
- hold(f.CurrentAxes, 'off');
- else
- hold(f.Children(1).Children(ind(1)), 'on');
- o = plot(f.Children(1).Children(ind(1)), G, 'LineStyle', '--', 'EdgeColor', 'g', 'NodeColor', 'k', 'LineWidth', 2);
- hold(f.Children(1).Children(ind(1)), 'off');
- if size(ind, 2) > 1
- for ii = 2:size(ind, 2)
- o = [o; copyobj(o(1), f.Children(1).Children(ind(ii)))];
- end
- end
- end
- obj.graphPlot = o;
- end
- end
-
- methods (Access = private)
- function validateInitialization(obj)
- % Assert obstacles do not intersect with the domain
-
- % Assert obstacles do not intersect with each other
-
- % Assert the objective has only one maxima within the domain
-
- % Assert the objective's sole maximum is not inaccessible due
- % to the placement of an obstacle
-
- end
- function validateLoop(obj)
- % Assert that agents are safely inside the domain
-
- % Assert that agents are not in proximity to obstacles
-
- % Assert that agents are not in proximity to each other
-
- % Assert that agents form a connected graph
-
-
- end
- end
-end
\ No newline at end of file
diff --git a/resources/project/IkDHDbHimostG0Ka3Qk97pof68k/3f4CTErydQ2TqIMJrHErKW1HTm8d.xml b/resources/project/5Gd2vBPGMN40pl5okl2ZJVqegNM/3amwjBK9JwYqOJZDEZryZqv41zsd.xml
similarity index 100%
rename from resources/project/IkDHDbHimostG0Ka3Qk97pof68k/3f4CTErydQ2TqIMJrHErKW1HTm8d.xml
rename to resources/project/5Gd2vBPGMN40pl5okl2ZJVqegNM/3amwjBK9JwYqOJZDEZryZqv41zsd.xml
diff --git a/resources/project/IkDHDbHimostG0Ka3Qk97pof68k/3f4CTErydQ2TqIMJrHErKW1HTm8p.xml b/resources/project/5Gd2vBPGMN40pl5okl2ZJVqegNM/3amwjBK9JwYqOJZDEZryZqv41zsp.xml
similarity index 100%
rename from resources/project/IkDHDbHimostG0Ka3Qk97pof68k/3f4CTErydQ2TqIMJrHErKW1HTm8p.xml
rename to resources/project/5Gd2vBPGMN40pl5okl2ZJVqegNM/3amwjBK9JwYqOJZDEZryZqv41zsp.xml
diff --git a/resources/project/IkDHDbHimostG0Ka3Qk97pof68k/bkRZvUTstiBe1YFWETJX1U9n5uQd.xml b/resources/project/5Gd2vBPGMN40pl5okl2ZJVqegNM/JcBVwaqXrEik_Qqy5CpGUTyyDM8d.xml
similarity index 100%
rename from resources/project/IkDHDbHimostG0Ka3Qk97pof68k/bkRZvUTstiBe1YFWETJX1U9n5uQd.xml
rename to resources/project/5Gd2vBPGMN40pl5okl2ZJVqegNM/JcBVwaqXrEik_Qqy5CpGUTyyDM8d.xml
diff --git a/resources/project/IkDHDbHimostG0Ka3Qk97pof68k/bkRZvUTstiBe1YFWETJX1U9n5uQp.xml b/resources/project/5Gd2vBPGMN40pl5okl2ZJVqegNM/JcBVwaqXrEik_Qqy5CpGUTyyDM8p.xml
similarity index 100%
rename from resources/project/IkDHDbHimostG0Ka3Qk97pof68k/bkRZvUTstiBe1YFWETJX1U9n5uQp.xml
rename to resources/project/5Gd2vBPGMN40pl5okl2ZJVqegNM/JcBVwaqXrEik_Qqy5CpGUTyyDM8p.xml
diff --git a/resources/project/IkDHDbHimostG0Ka3Qk97pof68k/eU5R_sxHD3gVw76yiaPpbMUKFIkd.xml b/resources/project/5Gd2vBPGMN40pl5okl2ZJVqegNM/gZWQ_GaNEEy28d0iAoPpVyZFQrwd.xml
similarity index 100%
rename from resources/project/IkDHDbHimostG0Ka3Qk97pof68k/eU5R_sxHD3gVw76yiaPpbMUKFIkd.xml
rename to resources/project/5Gd2vBPGMN40pl5okl2ZJVqegNM/gZWQ_GaNEEy28d0iAoPpVyZFQrwd.xml
diff --git a/resources/project/IkDHDbHimostG0Ka3Qk97pof68k/yxu_W2T0waL9FartpZB5JfpFMUUp.xml b/resources/project/5Gd2vBPGMN40pl5okl2ZJVqegNM/gZWQ_GaNEEy28d0iAoPpVyZFQrwp.xml
similarity index 100%
rename from resources/project/IkDHDbHimostG0Ka3Qk97pof68k/yxu_W2T0waL9FartpZB5JfpFMUUp.xml
rename to resources/project/5Gd2vBPGMN40pl5okl2ZJVqegNM/gZWQ_GaNEEy28d0iAoPpVyZFQrwp.xml
diff --git a/resources/project/IkDHDbHimostG0Ka3Qk97pof68k/xLI7SQj40yDbM71LQ8pVZ0dWmrgd.xml b/resources/project/9I1NhbvmbTiuVshItfSCHZiDxxI/Ac1TeO2zDmhnJ4WPcHxz_JGUcAAd.xml
similarity index 100%
rename from resources/project/IkDHDbHimostG0Ka3Qk97pof68k/xLI7SQj40yDbM71LQ8pVZ0dWmrgd.xml
rename to resources/project/9I1NhbvmbTiuVshItfSCHZiDxxI/Ac1TeO2zDmhnJ4WPcHxz_JGUcAAd.xml
diff --git a/resources/project/9I1NhbvmbTiuVshItfSCHZiDxxI/Ac1TeO2zDmhnJ4WPcHxz_JGUcAAp.xml b/resources/project/9I1NhbvmbTiuVshItfSCHZiDxxI/Ac1TeO2zDmhnJ4WPcHxz_JGUcAAp.xml
new file mode 100644
index 0000000..919c37e
--- /dev/null
+++ b/resources/project/9I1NhbvmbTiuVshItfSCHZiDxxI/Ac1TeO2zDmhnJ4WPcHxz_JGUcAAp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/M3axfhPiVFfHfWnq8PF7Q8OtKAU/2C0ooPmXaSISA_J0x7PMu2uZ660d.xml b/resources/project/9I1NhbvmbTiuVshItfSCHZiDxxI/Dqu7zYrAehYF43bzPjgGlZpWKucd.xml
similarity index 100%
rename from resources/project/M3axfhPiVFfHfWnq8PF7Q8OtKAU/2C0ooPmXaSISA_J0x7PMu2uZ660d.xml
rename to resources/project/9I1NhbvmbTiuVshItfSCHZiDxxI/Dqu7zYrAehYF43bzPjgGlZpWKucd.xml
diff --git a/resources/project/M3axfhPiVFfHfWnq8PF7Q8OtKAU/2C0ooPmXaSISA_J0x7PMu2uZ660p.xml b/resources/project/9I1NhbvmbTiuVshItfSCHZiDxxI/Dqu7zYrAehYF43bzPjgGlZpWKucp.xml
similarity index 100%
rename from resources/project/M3axfhPiVFfHfWnq8PF7Q8OtKAU/2C0ooPmXaSISA_J0x7PMu2uZ660p.xml
rename to resources/project/9I1NhbvmbTiuVshItfSCHZiDxxI/Dqu7zYrAehYF43bzPjgGlZpWKucp.xml
diff --git a/resources/project/IkDHDbHimostG0Ka3Qk97pof68k/yxu_W2T0waL9FartpZB5JfpFMUUd.xml b/resources/project/9I1NhbvmbTiuVshItfSCHZiDxxI/F1_77bY6s29xV3hf65cyjVDQctId.xml
similarity index 100%
rename from resources/project/IkDHDbHimostG0Ka3Qk97pof68k/yxu_W2T0waL9FartpZB5JfpFMUUd.xml
rename to resources/project/9I1NhbvmbTiuVshItfSCHZiDxxI/F1_77bY6s29xV3hf65cyjVDQctId.xml
diff --git a/resources/project/uhUDZwLuHiPGihzjzILZj0glbh8/gMC6J87GUhmyVw-U2Udmy4HIhA4p.xml b/resources/project/9I1NhbvmbTiuVshItfSCHZiDxxI/F1_77bY6s29xV3hf65cyjVDQctIp.xml
similarity index 100%
rename from resources/project/uhUDZwLuHiPGihzjzILZj0glbh8/gMC6J87GUhmyVw-U2Udmy4HIhA4p.xml
rename to resources/project/9I1NhbvmbTiuVshItfSCHZiDxxI/F1_77bY6s29xV3hf65cyjVDQctIp.xml
diff --git a/resources/project/M3axfhPiVFfHfWnq8PF7Q8OtKAU/6yzCMKkTsLiObJh9i87v9JChC2Yd.xml b/resources/project/9I1NhbvmbTiuVshItfSCHZiDxxI/S3VkGQGVBBKgX9-li9IBBbRh6Jcd.xml
similarity index 100%
rename from resources/project/M3axfhPiVFfHfWnq8PF7Q8OtKAU/6yzCMKkTsLiObJh9i87v9JChC2Yd.xml
rename to resources/project/9I1NhbvmbTiuVshItfSCHZiDxxI/S3VkGQGVBBKgX9-li9IBBbRh6Jcd.xml
diff --git a/resources/project/9I1NhbvmbTiuVshItfSCHZiDxxI/S3VkGQGVBBKgX9-li9IBBbRh6Jcp.xml b/resources/project/9I1NhbvmbTiuVshItfSCHZiDxxI/S3VkGQGVBBKgX9-li9IBBbRh6Jcp.xml
new file mode 100644
index 0000000..844d632
--- /dev/null
+++ b/resources/project/9I1NhbvmbTiuVshItfSCHZiDxxI/S3VkGQGVBBKgX9-li9IBBbRh6Jcp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/M3axfhPiVFfHfWnq8PF7Q8OtKAU/G6lGXsTbuwZ-AEQ27UXCqCsFttEd.xml b/resources/project/9I1NhbvmbTiuVshItfSCHZiDxxI/l6NIqYudBCIzq4wYJm1naLreh70d.xml
similarity index 100%
rename from resources/project/M3axfhPiVFfHfWnq8PF7Q8OtKAU/G6lGXsTbuwZ-AEQ27UXCqCsFttEd.xml
rename to resources/project/9I1NhbvmbTiuVshItfSCHZiDxxI/l6NIqYudBCIzq4wYJm1naLreh70d.xml
diff --git a/resources/project/9I1NhbvmbTiuVshItfSCHZiDxxI/l6NIqYudBCIzq4wYJm1naLreh70p.xml b/resources/project/9I1NhbvmbTiuVshItfSCHZiDxxI/l6NIqYudBCIzq4wYJm1naLreh70p.xml
new file mode 100644
index 0000000..1b3fd95
--- /dev/null
+++ b/resources/project/9I1NhbvmbTiuVshItfSCHZiDxxI/l6NIqYudBCIzq4wYJm1naLreh70p.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/M3axfhPiVFfHfWnq8PF7Q8OtKAU/IkDHDbHimostG0Ka3Qk97pof68kd.xml b/resources/project/E2mMq2X73DyjKhlQAouGqrsyLgg/21tPnJuFct8IF0xfcC8JtR_tiLYd.xml
similarity index 100%
rename from resources/project/M3axfhPiVFfHfWnq8PF7Q8OtKAU/IkDHDbHimostG0Ka3Qk97pof68kd.xml
rename to resources/project/E2mMq2X73DyjKhlQAouGqrsyLgg/21tPnJuFct8IF0xfcC8JtR_tiLYd.xml
diff --git a/resources/project/E2mMq2X73DyjKhlQAouGqrsyLgg/21tPnJuFct8IF0xfcC8JtR_tiLYp.xml b/resources/project/E2mMq2X73DyjKhlQAouGqrsyLgg/21tPnJuFct8IF0xfcC8JtR_tiLYp.xml
new file mode 100644
index 0000000..01cb34e
--- /dev/null
+++ b/resources/project/E2mMq2X73DyjKhlQAouGqrsyLgg/21tPnJuFct8IF0xfcC8JtR_tiLYp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/M3axfhPiVFfHfWnq8PF7Q8OtKAUd.xml b/resources/project/E2mMq2X73DyjKhlQAouGqrsyLgg/TdZ3RWRwXT8LuGLEIsWOhzCcLzcd.xml
similarity index 100%
rename from resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/M3axfhPiVFfHfWnq8PF7Q8OtKAUd.xml
rename to resources/project/E2mMq2X73DyjKhlQAouGqrsyLgg/TdZ3RWRwXT8LuGLEIsWOhzCcLzcd.xml
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/M3axfhPiVFfHfWnq8PF7Q8OtKAUp.xml b/resources/project/E2mMq2X73DyjKhlQAouGqrsyLgg/TdZ3RWRwXT8LuGLEIsWOhzCcLzcp.xml
similarity index 100%
rename from resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/M3axfhPiVFfHfWnq8PF7Q8OtKAUp.xml
rename to resources/project/E2mMq2X73DyjKhlQAouGqrsyLgg/TdZ3RWRwXT8LuGLEIsWOhzCcLzcp.xml
diff --git a/resources/project/M3axfhPiVFfHfWnq8PF7Q8OtKAU/gE3UtRAYb2Mvi_5_27MbNbrZKNcd.xml b/resources/project/E2mMq2X73DyjKhlQAouGqrsyLgg/mI2CFAFGipkBXPK8ngfcqPy9t1Yd.xml
similarity index 100%
rename from resources/project/M3axfhPiVFfHfWnq8PF7Q8OtKAU/gE3UtRAYb2Mvi_5_27MbNbrZKNcd.xml
rename to resources/project/E2mMq2X73DyjKhlQAouGqrsyLgg/mI2CFAFGipkBXPK8ngfcqPy9t1Yd.xml
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/IkPyncn3ZGRxjBV47QmicBzm2kUp.xml b/resources/project/E2mMq2X73DyjKhlQAouGqrsyLgg/mI2CFAFGipkBXPK8ngfcqPy9t1Yp.xml
similarity index 100%
rename from resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/IkPyncn3ZGRxjBV47QmicBzm2kUp.xml
rename to resources/project/E2mMq2X73DyjKhlQAouGqrsyLgg/mI2CFAFGipkBXPK8ngfcqPy9t1Yp.xml
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/CCiVFlEZGOWF8RpyKjlFUC_OrW4d.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/CCiVFlEZGOWF8RpyKjlFUC_OrW4d.xml
new file mode 100644
index 0000000..3a68b38
--- /dev/null
+++ b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/CCiVFlEZGOWF8RpyKjlFUC_OrW4d.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/CCiVFlEZGOWF8RpyKjlFUC_OrW4p.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/CCiVFlEZGOWF8RpyKjlFUC_OrW4p.xml
new file mode 100644
index 0000000..d7873ab
--- /dev/null
+++ b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/CCiVFlEZGOWF8RpyKjlFUC_OrW4p.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/QAWdSKdcuP9OGm_S2NybPkCBTOYd.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/QAWdSKdcuP9OGm_S2NybPkCBTOYd.xml
new file mode 100644
index 0000000..b735f78
--- /dev/null
+++ b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/QAWdSKdcuP9OGm_S2NybPkCBTOYd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/QAWdSKdcuP9OGm_S2NybPkCBTOYp.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/QAWdSKdcuP9OGm_S2NybPkCBTOYp.xml
new file mode 100644
index 0000000..b502832
--- /dev/null
+++ b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/QAWdSKdcuP9OGm_S2NybPkCBTOYp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/QCjAM-pfjkxuIc0-mouM97I9zHEd.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/QCjAM-pfjkxuIc0-mouM97I9zHEd.xml
new file mode 100644
index 0000000..46a6ccd
--- /dev/null
+++ b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/QCjAM-pfjkxuIc0-mouM97I9zHEd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/QCjAM-pfjkxuIc0-mouM97I9zHEp.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/QCjAM-pfjkxuIc0-mouM97I9zHEp.xml
new file mode 100644
index 0000000..50aaeab
--- /dev/null
+++ b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/QCjAM-pfjkxuIc0-mouM97I9zHEp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/bC9JguT7xdg6hTVY9GqmttWOU6Ud.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/bC9JguT7xdg6hTVY9GqmttWOU6Ud.xml
deleted file mode 100644
index d28e2cf..0000000
--- a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/bC9JguT7xdg6hTVY9GqmttWOU6Ud.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/bC9JguT7xdg6hTVY9GqmttWOU6Up.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/bC9JguT7xdg6hTVY9GqmttWOU6Up.xml
deleted file mode 100644
index 8a52762..0000000
--- a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/bC9JguT7xdg6hTVY9GqmttWOU6Up.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/jjRWXxv1fmTGw_ntc54vNxAyLDMd.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/jjRWXxv1fmTGw_ntc54vNxAyLDMd.xml
deleted file mode 100644
index 2bd39f9..0000000
--- a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/jjRWXxv1fmTGw_ntc54vNxAyLDMd.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/jjRWXxv1fmTGw_ntc54vNxAyLDMp.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/jjRWXxv1fmTGw_ntc54vNxAyLDMp.xml
deleted file mode 100644
index 442ec92..0000000
--- a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/jjRWXxv1fmTGw_ntc54vNxAyLDMp.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/s5udZfVFP9-PGBZPOy6PEk_nJDEd.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/s5udZfVFP9-PGBZPOy6PEk_nJDEd.xml
new file mode 100644
index 0000000..acb0082
--- /dev/null
+++ b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/s5udZfVFP9-PGBZPOy6PEk_nJDEd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/s5udZfVFP9-PGBZPOy6PEk_nJDEp.xml b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/s5udZfVFP9-PGBZPOy6PEk_nJDEp.xml
new file mode 100644
index 0000000..2967e3a
--- /dev/null
+++ b/resources/project/EEtUlUb-dLAdf0KpMVivaUlztwA/s5udZfVFP9-PGBZPOy6PEk_nJDEp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/FI0gxbH-PhwjE_riDQGHPyYMHks/5Lk_HLOyBtA13ybsC7_0l8N5sPcd.xml b/resources/project/FI0gxbH-PhwjE_riDQGHPyYMHks/5Lk_HLOyBtA13ybsC7_0l8N5sPcd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/FI0gxbH-PhwjE_riDQGHPyYMHks/5Lk_HLOyBtA13ybsC7_0l8N5sPcd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/FI0gxbH-PhwjE_riDQGHPyYMHks/5Lk_HLOyBtA13ybsC7_0l8N5sPcp.xml b/resources/project/FI0gxbH-PhwjE_riDQGHPyYMHks/5Lk_HLOyBtA13ybsC7_0l8N5sPcp.xml
new file mode 100644
index 0000000..01cb34e
--- /dev/null
+++ b/resources/project/FI0gxbH-PhwjE_riDQGHPyYMHks/5Lk_HLOyBtA13ybsC7_0l8N5sPcp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/M3axfhPiVFfHfWnq8PF7Q8OtKAU/mjV-hfj-qf8MzZBB6uhFVn0raaUd.xml b/resources/project/FI0gxbH-PhwjE_riDQGHPyYMHks/l3KmQJPRLDdioib0N4ZzRTdiyYQd.xml
similarity index 100%
rename from resources/project/M3axfhPiVFfHfWnq8PF7Q8OtKAU/mjV-hfj-qf8MzZBB6uhFVn0raaUd.xml
rename to resources/project/FI0gxbH-PhwjE_riDQGHPyYMHks/l3KmQJPRLDdioib0N4ZzRTdiyYQd.xml
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/DnSrh-_-SnAVM_QmOB_8JskdVJUp.xml b/resources/project/FI0gxbH-PhwjE_riDQGHPyYMHks/l3KmQJPRLDdioib0N4ZzRTdiyYQp.xml
similarity index 100%
rename from resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/DnSrh-_-SnAVM_QmOB_8JskdVJUp.xml
rename to resources/project/FI0gxbH-PhwjE_riDQGHPyYMHks/l3KmQJPRLDdioib0N4ZzRTdiyYQp.xml
diff --git a/resources/project/NRbCR7m2f1_2pHz6LyHrTz7eFpc/NmnqsjHeF9rAhG9A30BKV_vI7tId.xml b/resources/project/IZmCOv6JD31mVpLELAk0ipkk3_g/Y80bFtWukuhQhZV-YQoZVwUsSd4d.xml
similarity index 100%
rename from resources/project/NRbCR7m2f1_2pHz6LyHrTz7eFpc/NmnqsjHeF9rAhG9A30BKV_vI7tId.xml
rename to resources/project/IZmCOv6JD31mVpLELAk0ipkk3_g/Y80bFtWukuhQhZV-YQoZVwUsSd4d.xml
diff --git a/resources/project/NRbCR7m2f1_2pHz6LyHrTz7eFpc/pWmr-S3Aa4bo9IjolP0M5UKtHGIp.xml b/resources/project/IZmCOv6JD31mVpLELAk0ipkk3_g/Y80bFtWukuhQhZV-YQoZVwUsSd4p.xml
similarity index 100%
rename from resources/project/NRbCR7m2f1_2pHz6LyHrTz7eFpc/pWmr-S3Aa4bo9IjolP0M5UKtHGIp.xml
rename to resources/project/IZmCOv6JD31mVpLELAk0ipkk3_g/Y80bFtWukuhQhZV-YQoZVwUsSd4p.xml
diff --git a/resources/project/NRbCR7m2f1_2pHz6LyHrTz7eFpc/pWmr-S3Aa4bo9IjolP0M5UKtHGId.xml b/resources/project/IZmCOv6JD31mVpLELAk0ipkk3_g/_6kRedv97kNBifq-YxMdKYmJtCwd.xml
similarity index 100%
rename from resources/project/NRbCR7m2f1_2pHz6LyHrTz7eFpc/pWmr-S3Aa4bo9IjolP0M5UKtHGId.xml
rename to resources/project/IZmCOv6JD31mVpLELAk0ipkk3_g/_6kRedv97kNBifq-YxMdKYmJtCwd.xml
diff --git a/resources/project/IZmCOv6JD31mVpLELAk0ipkk3_g/_6kRedv97kNBifq-YxMdKYmJtCwp.xml b/resources/project/IZmCOv6JD31mVpLELAk0ipkk3_g/_6kRedv97kNBifq-YxMdKYmJtCwp.xml
new file mode 100644
index 0000000..e9ea0b9
--- /dev/null
+++ b/resources/project/IZmCOv6JD31mVpLELAk0ipkk3_g/_6kRedv97kNBifq-YxMdKYmJtCwp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/DnSrh-_-SnAVM_QmOB_8JskdVJUd.xml b/resources/project/IZmCOv6JD31mVpLELAk0ipkk3_g/vvaT0-TqiGnaRLajwambyiLQ2Wwd.xml
similarity index 100%
rename from resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/DnSrh-_-SnAVM_QmOB_8JskdVJUd.xml
rename to resources/project/IZmCOv6JD31mVpLELAk0ipkk3_g/vvaT0-TqiGnaRLajwambyiLQ2Wwd.xml
diff --git a/resources/project/IZmCOv6JD31mVpLELAk0ipkk3_g/vvaT0-TqiGnaRLajwambyiLQ2Wwp.xml b/resources/project/IZmCOv6JD31mVpLELAk0ipkk3_g/vvaT0-TqiGnaRLajwambyiLQ2Wwp.xml
new file mode 100644
index 0000000..844d632
--- /dev/null
+++ b/resources/project/IZmCOv6JD31mVpLELAk0ipkk3_g/vvaT0-TqiGnaRLajwambyiLQ2Wwp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/IZmCOv6JD31mVpLELAk0ipkk3_g/zR-9c0e4RmoTUjy3irYLxJytP9cd.xml b/resources/project/IZmCOv6JD31mVpLELAk0ipkk3_g/zR-9c0e4RmoTUjy3irYLxJytP9cd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/IZmCOv6JD31mVpLELAk0ipkk3_g/zR-9c0e4RmoTUjy3irYLxJytP9cd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/IZmCOv6JD31mVpLELAk0ipkk3_g/zR-9c0e4RmoTUjy3irYLxJytP9cp.xml b/resources/project/IZmCOv6JD31mVpLELAk0ipkk3_g/zR-9c0e4RmoTUjy3irYLxJytP9cp.xml
new file mode 100644
index 0000000..01cb34e
--- /dev/null
+++ b/resources/project/IZmCOv6JD31mVpLELAk0ipkk3_g/zR-9c0e4RmoTUjy3irYLxJytP9cp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/IkDHDbHimostG0Ka3Qk97pof68k/eU5R_sxHD3gVw76yiaPpbMUKFIkp.xml b/resources/project/IkDHDbHimostG0Ka3Qk97pof68k/eU5R_sxHD3gVw76yiaPpbMUKFIkp.xml
deleted file mode 100644
index 8e00d26..0000000
--- a/resources/project/IkDHDbHimostG0Ka3Qk97pof68k/eU5R_sxHD3gVw76yiaPpbMUKFIkp.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/resources/project/IkDHDbHimostG0Ka3Qk97pof68k/xLI7SQj40yDbM71LQ8pVZ0dWmrgp.xml b/resources/project/IkDHDbHimostG0Ka3Qk97pof68k/xLI7SQj40yDbM71LQ8pVZ0dWmrgp.xml
deleted file mode 100644
index aa77220..0000000
--- a/resources/project/IkDHDbHimostG0Ka3Qk97pof68k/xLI7SQj40yDbM71LQ8pVZ0dWmrgp.xml
+++ /dev/null
@@ -1,2 +0,0 @@
-
-
\ No newline at end of file
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/G4ZDRUCYKeWyePBmClgd0b2gv90d.xml b/resources/project/LMc5a8ETDcRip3rYsQxn56S6obM/2JKMt-jJFCbC-SMT4nST0in4PQEd.xml
similarity index 100%
rename from resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/G4ZDRUCYKeWyePBmClgd0b2gv90d.xml
rename to resources/project/LMc5a8ETDcRip3rYsQxn56S6obM/2JKMt-jJFCbC-SMT4nST0in4PQEd.xml
diff --git a/resources/project/LMc5a8ETDcRip3rYsQxn56S6obM/2JKMt-jJFCbC-SMT4nST0in4PQEp.xml b/resources/project/LMc5a8ETDcRip3rYsQxn56S6obM/2JKMt-jJFCbC-SMT4nST0in4PQEp.xml
new file mode 100644
index 0000000..1b3fd95
--- /dev/null
+++ b/resources/project/LMc5a8ETDcRip3rYsQxn56S6obM/2JKMt-jJFCbC-SMT4nST0in4PQEp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/LMc5a8ETDcRip3rYsQxn56S6obM/3Ynm0xo_SnHtytV6kUUwOl53TZsd.xml b/resources/project/LMc5a8ETDcRip3rYsQxn56S6obM/3Ynm0xo_SnHtytV6kUUwOl53TZsd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/LMc5a8ETDcRip3rYsQxn56S6obM/3Ynm0xo_SnHtytV6kUUwOl53TZsd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/LMc5a8ETDcRip3rYsQxn56S6obM/3Ynm0xo_SnHtytV6kUUwOl53TZsp.xml b/resources/project/LMc5a8ETDcRip3rYsQxn56S6obM/3Ynm0xo_SnHtytV6kUUwOl53TZsp.xml
new file mode 100644
index 0000000..01cb34e
--- /dev/null
+++ b/resources/project/LMc5a8ETDcRip3rYsQxn56S6obM/3Ynm0xo_SnHtytV6kUUwOl53TZsp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/IkPyncn3ZGRxjBV47QmicBzm2kUd.xml b/resources/project/LMc5a8ETDcRip3rYsQxn56S6obM/430zy1Ki2Voh4Zh3tuAWqbgRPF8d.xml
similarity index 100%
rename from resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/IkPyncn3ZGRxjBV47QmicBzm2kUd.xml
rename to resources/project/LMc5a8ETDcRip3rYsQxn56S6obM/430zy1Ki2Voh4Zh3tuAWqbgRPF8d.xml
diff --git a/resources/project/LMc5a8ETDcRip3rYsQxn56S6obM/430zy1Ki2Voh4Zh3tuAWqbgRPF8p.xml b/resources/project/LMc5a8ETDcRip3rYsQxn56S6obM/430zy1Ki2Voh4Zh3tuAWqbgRPF8p.xml
new file mode 100644
index 0000000..844d632
--- /dev/null
+++ b/resources/project/LMc5a8ETDcRip3rYsQxn56S6obM/430zy1Ki2Voh4Zh3tuAWqbgRPF8p.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/raP7OV2lamoMNbKeDBUa13s5Imwd.xml b/resources/project/LMc5a8ETDcRip3rYsQxn56S6obM/PPOY66CYBPYXvf5ZNLF4sLYz8psd.xml
similarity index 100%
rename from resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/raP7OV2lamoMNbKeDBUa13s5Imwd.xml
rename to resources/project/LMc5a8ETDcRip3rYsQxn56S6obM/PPOY66CYBPYXvf5ZNLF4sLYz8psd.xml
diff --git a/resources/project/LMc5a8ETDcRip3rYsQxn56S6obM/PPOY66CYBPYXvf5ZNLF4sLYz8psp.xml b/resources/project/LMc5a8ETDcRip3rYsQxn56S6obM/PPOY66CYBPYXvf5ZNLF4sLYz8psp.xml
new file mode 100644
index 0000000..919c37e
--- /dev/null
+++ b/resources/project/LMc5a8ETDcRip3rYsQxn56S6obM/PPOY66CYBPYXvf5ZNLF4sLYz8psp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/u_8f8riMl9bapFIdVg6GQo796t8d.xml b/resources/project/LMc5a8ETDcRip3rYsQxn56S6obM/fUOdXDI-eV2v8tmNwci5z5hbCmQd.xml
similarity index 100%
rename from resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/u_8f8riMl9bapFIdVg6GQo796t8d.xml
rename to resources/project/LMc5a8ETDcRip3rYsQxn56S6obM/fUOdXDI-eV2v8tmNwci5z5hbCmQd.xml
diff --git a/resources/project/uhUDZwLuHiPGihzjzILZj0glbh8/H1DNOJ2xfieNyGozuRxm3sAKlR4p.xml b/resources/project/LMc5a8ETDcRip3rYsQxn56S6obM/fUOdXDI-eV2v8tmNwci5z5hbCmQp.xml
similarity index 100%
rename from resources/project/uhUDZwLuHiPGihzjzILZj0glbh8/H1DNOJ2xfieNyGozuRxm3sAKlR4p.xml
rename to resources/project/LMc5a8ETDcRip3rYsQxn56S6obM/fUOdXDI-eV2v8tmNwci5z5hbCmQp.xml
diff --git a/resources/project/NRbCR7m2f1_2pHz6LyHrTz7eFpc/IZmCOv6JD31mVpLELAk0ipkk3_gd.xml b/resources/project/NRbCR7m2f1_2pHz6LyHrTz7eFpc/IZmCOv6JD31mVpLELAk0ipkk3_gd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/NRbCR7m2f1_2pHz6LyHrTz7eFpc/IZmCOv6JD31mVpLELAk0ipkk3_gd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/NRbCR7m2f1_2pHz6LyHrTz7eFpc/IZmCOv6JD31mVpLELAk0ipkk3_gp.xml b/resources/project/NRbCR7m2f1_2pHz6LyHrTz7eFpc/IZmCOv6JD31mVpLELAk0ipkk3_gp.xml
new file mode 100644
index 0000000..ea150ee
--- /dev/null
+++ b/resources/project/NRbCR7m2f1_2pHz6LyHrTz7eFpc/IZmCOv6JD31mVpLELAk0ipkk3_gp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/NRbCR7m2f1_2pHz6LyHrTz7eFpc/tBBDcBPWdBTCTMSBG9IGJ_TsICkd.xml b/resources/project/NRbCR7m2f1_2pHz6LyHrTz7eFpc/tBBDcBPWdBTCTMSBG9IGJ_TsICkd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/NRbCR7m2f1_2pHz6LyHrTz7eFpc/tBBDcBPWdBTCTMSBG9IGJ_TsICkd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/NRbCR7m2f1_2pHz6LyHrTz7eFpc/tBBDcBPWdBTCTMSBG9IGJ_TsICkp.xml b/resources/project/NRbCR7m2f1_2pHz6LyHrTz7eFpc/tBBDcBPWdBTCTMSBG9IGJ_TsICkp.xml
new file mode 100644
index 0000000..9b1f0e9
--- /dev/null
+++ b/resources/project/NRbCR7m2f1_2pHz6LyHrTz7eFpc/tBBDcBPWdBTCTMSBG9IGJ_TsICkp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/wdgofbR4UWdlJ0HwKeczjlphIxQd.xml b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/0lSq9ZcW6wGcu05HTGCManxXSWgd.xml
similarity index 100%
rename from resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/wdgofbR4UWdlJ0HwKeczjlphIxQd.xml
rename to resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/0lSq9ZcW6wGcu05HTGCManxXSWgd.xml
diff --git a/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/0lSq9ZcW6wGcu05HTGCManxXSWgp.xml b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/0lSq9ZcW6wGcu05HTGCManxXSWgp.xml
new file mode 100644
index 0000000..bd6d46b
--- /dev/null
+++ b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/0lSq9ZcW6wGcu05HTGCManxXSWgp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/4XyMCGilNSTkYZYCWT4IaoSxyRQd.xml b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/4XyMCGilNSTkYZYCWT4IaoSxyRQd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/4XyMCGilNSTkYZYCWT4IaoSxyRQd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/4XyMCGilNSTkYZYCWT4IaoSxyRQp.xml b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/4XyMCGilNSTkYZYCWT4IaoSxyRQp.xml
new file mode 100644
index 0000000..01cb34e
--- /dev/null
+++ b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/4XyMCGilNSTkYZYCWT4IaoSxyRQp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/uhUDZwLuHiPGihzjzILZj0glbh8/H1DNOJ2xfieNyGozuRxm3sAKlR4d.xml b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/GHz2jBC1pAV-A1XT3CoAG36nIAwd.xml
similarity index 100%
rename from resources/project/uhUDZwLuHiPGihzjzILZj0glbh8/H1DNOJ2xfieNyGozuRxm3sAKlR4d.xml
rename to resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/GHz2jBC1pAV-A1XT3CoAG36nIAwd.xml
diff --git a/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/GHz2jBC1pAV-A1XT3CoAG36nIAwp.xml b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/GHz2jBC1pAV-A1XT3CoAG36nIAwp.xml
new file mode 100644
index 0000000..155f4c5
--- /dev/null
+++ b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/GHz2jBC1pAV-A1XT3CoAG36nIAwp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/uhUDZwLuHiPGihzjzILZj0glbh8/gMC6J87GUhmyVw-U2Udmy4HIhA4d.xml b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/J92EAi8o6avZ-YwqXJcBXXpuHf8d.xml
similarity index 100%
rename from resources/project/uhUDZwLuHiPGihzjzILZj0glbh8/gMC6J87GUhmyVw-U2Udmy4HIhA4d.xml
rename to resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/J92EAi8o6avZ-YwqXJcBXXpuHf8d.xml
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/G4ZDRUCYKeWyePBmClgd0b2gv90p.xml b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/J92EAi8o6avZ-YwqXJcBXXpuHf8p.xml
similarity index 100%
rename from resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/G4ZDRUCYKeWyePBmClgd0b2gv90p.xml
rename to resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/J92EAi8o6avZ-YwqXJcBXXpuHf8p.xml
diff --git a/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/KnSqc2QQVtqpmkuTxZwS8ypWZesd.xml b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/KnSqc2QQVtqpmkuTxZwS8ypWZesd.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/KnSqc2QQVtqpmkuTxZwS8ypWZesd.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/KnSqc2QQVtqpmkuTxZwS8ypWZesp.xml b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/KnSqc2QQVtqpmkuTxZwS8ypWZesp.xml
new file mode 100644
index 0000000..fa915a2
--- /dev/null
+++ b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/KnSqc2QQVtqpmkuTxZwS8ypWZesp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/S5qjXNcWDF4RSOo6BBwCYV6o8rQd.xml b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/S5qjXNcWDF4RSOo6BBwCYV6o8rQd.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/S5qjXNcWDF4RSOo6BBwCYV6o8rQd.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/wdgofbR4UWdlJ0HwKeczjlphIxQp.xml b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/S5qjXNcWDF4RSOo6BBwCYV6o8rQp.xml
similarity index 100%
rename from resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/wdgofbR4UWdlJ0HwKeczjlphIxQp.xml
rename to resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/S5qjXNcWDF4RSOo6BBwCYV6o8rQp.xml
diff --git a/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/bkmoNrBwYYHCyCuPxB3AjMVO36Qd.xml b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/bkmoNrBwYYHCyCuPxB3AjMVO36Qd.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/bkmoNrBwYYHCyCuPxB3AjMVO36Qd.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/bkmoNrBwYYHCyCuPxB3AjMVO36Qp.xml b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/bkmoNrBwYYHCyCuPxB3AjMVO36Qp.xml
new file mode 100644
index 0000000..d15dbd9
--- /dev/null
+++ b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/bkmoNrBwYYHCyCuPxB3AjMVO36Qp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/f0RkSaUnOeV8lDfnKFJ8u9hIZUUd.xml b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/f0RkSaUnOeV8lDfnKFJ8u9hIZUUd.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/f0RkSaUnOeV8lDfnKFJ8u9hIZUUd.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/f0RkSaUnOeV8lDfnKFJ8u9hIZUUp.xml b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/f0RkSaUnOeV8lDfnKFJ8u9hIZUUp.xml
new file mode 100644
index 0000000..7c8e137
--- /dev/null
+++ b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/f0RkSaUnOeV8lDfnKFJ8u9hIZUUp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/oCy9E8Fla0m4lQK4mxXPUemiiOMd.xml b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/oCy9E8Fla0m4lQK4mxXPUemiiOMd.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/oCy9E8Fla0m4lQK4mxXPUemiiOMd.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/oCy9E8Fla0m4lQK4mxXPUemiiOMp.xml b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/oCy9E8Fla0m4lQK4mxXPUemiiOMp.xml
new file mode 100644
index 0000000..2173525
--- /dev/null
+++ b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/oCy9E8Fla0m4lQK4mxXPUemiiOMp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/tgPwY-KyNq5u9lexKP-wS_hIsJUd.xml b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/tgPwY-KyNq5u9lexKP-wS_hIsJUd.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/tgPwY-KyNq5u9lexKP-wS_hIsJUd.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/tgPwY-KyNq5u9lexKP-wS_hIsJUp.xml b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/tgPwY-KyNq5u9lexKP-wS_hIsJUp.xml
new file mode 100644
index 0000000..c88fd52
--- /dev/null
+++ b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/tgPwY-KyNq5u9lexKP-wS_hIsJUp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/tzy_kgNdWvLpRYdTN_zTdyXacDkd.xml b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/tzy_kgNdWvLpRYdTN_zTdyXacDkd.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/tzy_kgNdWvLpRYdTN_zTdyXacDkd.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/tzy_kgNdWvLpRYdTN_zTdyXacDkp.xml b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/tzy_kgNdWvLpRYdTN_zTdyXacDkp.xml
new file mode 100644
index 0000000..e9ea0b9
--- /dev/null
+++ b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/tzy_kgNdWvLpRYdTN_zTdyXacDkp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/zxW4DTgKotcrlXdV5uTWtjHgG3Ed.xml b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/zxW4DTgKotcrlXdV5uTWtjHgG3Ed.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/zxW4DTgKotcrlXdV5uTWtjHgG3Ed.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/zxW4DTgKotcrlXdV5uTWtjHgG3Ep.xml b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/zxW4DTgKotcrlXdV5uTWtjHgG3Ep.xml
new file mode 100644
index 0000000..844d632
--- /dev/null
+++ b/resources/project/SIL3u_W39LwE7HHYsarfFmr9gVQ/zxW4DTgKotcrlXdV5uTWtjHgG3Ep.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/5Gd2vBPGMN40pl5okl2ZJVqegNMd.xml b/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/5Gd2vBPGMN40pl5okl2ZJVqegNMd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/5Gd2vBPGMN40pl5okl2ZJVqegNMd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/M3axfhPiVFfHfWnq8PF7Q8OtKAU/IkDHDbHimostG0Ka3Qk97pof68kp.xml b/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/5Gd2vBPGMN40pl5okl2ZJVqegNMp.xml
similarity index 100%
rename from resources/project/M3axfhPiVFfHfWnq8PF7Q8OtKAU/IkDHDbHimostG0Ka3Qk97pof68kp.xml
rename to resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/5Gd2vBPGMN40pl5okl2ZJVqegNMp.xml
diff --git a/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/F2jVWl2JEJhI5Pu9LhndwtOghFEd.xml b/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/F2jVWl2JEJhI5Pu9LhndwtOghFEd.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/F2jVWl2JEJhI5Pu9LhndwtOghFEd.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/F2jVWl2JEJhI5Pu9LhndwtOghFEp.xml b/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/F2jVWl2JEJhI5Pu9LhndwtOghFEp.xml
new file mode 100644
index 0000000..0880a8f
--- /dev/null
+++ b/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/F2jVWl2JEJhI5Pu9LhndwtOghFEp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/HZFKL0YU3keXLndwxPZTD9XMwu8d.xml b/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/HZFKL0YU3keXLndwxPZTD9XMwu8d.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/HZFKL0YU3keXLndwxPZTD9XMwu8d.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/M3axfhPiVFfHfWnq8PF7Q8OtKAU/G6lGXsTbuwZ-AEQ27UXCqCsFttEp.xml b/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/HZFKL0YU3keXLndwxPZTD9XMwu8p.xml
similarity index 100%
rename from resources/project/M3axfhPiVFfHfWnq8PF7Q8OtKAU/G6lGXsTbuwZ-AEQ27UXCqCsFttEp.xml
rename to resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/HZFKL0YU3keXLndwxPZTD9XMwu8p.xml
diff --git a/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/M8CmKz5ilvfTqNr4hc7sdxvHFr4d.xml b/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/M8CmKz5ilvfTqNr4hc7sdxvHFr4d.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/M8CmKz5ilvfTqNr4hc7sdxvHFr4d.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/M3axfhPiVFfHfWnq8PF7Q8OtKAU/6yzCMKkTsLiObJh9i87v9JChC2Yp.xml b/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/M8CmKz5ilvfTqNr4hc7sdxvHFr4p.xml
similarity index 100%
rename from resources/project/M3axfhPiVFfHfWnq8PF7Q8OtKAU/6yzCMKkTsLiObJh9i87v9JChC2Yp.xml
rename to resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/M8CmKz5ilvfTqNr4hc7sdxvHFr4p.xml
diff --git a/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/UP5Pw9z0RSU8VeujaHR0Gb8XJqId.xml b/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/UP5Pw9z0RSU8VeujaHR0Gb8XJqId.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/UP5Pw9z0RSU8VeujaHR0Gb8XJqId.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/M3axfhPiVFfHfWnq8PF7Q8OtKAU/mjV-hfj-qf8MzZBB6uhFVn0raaUp.xml b/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/UP5Pw9z0RSU8VeujaHR0Gb8XJqIp.xml
similarity index 100%
rename from resources/project/M3axfhPiVFfHfWnq8PF7Q8OtKAU/mjV-hfj-qf8MzZBB6uhFVn0raaUp.xml
rename to resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/UP5Pw9z0RSU8VeujaHR0Gb8XJqIp.xml
diff --git a/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/ZSIXyJwNXhOxVvPD7MaWFZn4C9Yd.xml b/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/ZSIXyJwNXhOxVvPD7MaWFZn4C9Yd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/ZSIXyJwNXhOxVvPD7MaWFZn4C9Yd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/ZSIXyJwNXhOxVvPD7MaWFZn4C9Yp.xml b/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/ZSIXyJwNXhOxVvPD7MaWFZn4C9Yp.xml
new file mode 100644
index 0000000..01cb34e
--- /dev/null
+++ b/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/ZSIXyJwNXhOxVvPD7MaWFZn4C9Yp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/ZpeEkzea4UyiU4xJYjimFCy8nC0d.xml b/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/ZpeEkzea4UyiU4xJYjimFCy8nC0d.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/ZpeEkzea4UyiU4xJYjimFCy8nC0d.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/M3axfhPiVFfHfWnq8PF7Q8OtKAU/gE3UtRAYb2Mvi_5_27MbNbrZKNcp.xml b/resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/ZpeEkzea4UyiU4xJYjimFCy8nC0p.xml
similarity index 100%
rename from resources/project/M3axfhPiVFfHfWnq8PF7Q8OtKAU/gE3UtRAYb2Mvi_5_27MbNbrZKNcp.xml
rename to resources/project/TdZ3RWRwXT8LuGLEIsWOhzCcLzc/ZpeEkzea4UyiU4xJYjimFCy8nC0p.xml
diff --git a/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/8MPd8pAZSUgBScEedIRQxiuUDAcd.xml b/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/8MPd8pAZSUgBScEedIRQxiuUDAcd.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/8MPd8pAZSUgBScEedIRQxiuUDAcd.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/raP7OV2lamoMNbKeDBUa13s5Imwp.xml b/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/8MPd8pAZSUgBScEedIRQxiuUDAcp.xml
similarity index 100%
rename from resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/raP7OV2lamoMNbKeDBUa13s5Imwp.xml
rename to resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/8MPd8pAZSUgBScEedIRQxiuUDAcp.xml
diff --git a/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/98PkEmwuOuiGV_bxeF7EQPx74fgd.xml b/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/98PkEmwuOuiGV_bxeF7EQPx74fgd.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/98PkEmwuOuiGV_bxeF7EQPx74fgd.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/98PkEmwuOuiGV_bxeF7EQPx74fgp.xml b/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/98PkEmwuOuiGV_bxeF7EQPx74fgp.xml
new file mode 100644
index 0000000..fa915a2
--- /dev/null
+++ b/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/98PkEmwuOuiGV_bxeF7EQPx74fgp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/I3z_nB8Axn7Gvle608fk5v5Ln8od.xml b/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/I3z_nB8Axn7Gvle608fk5v5Ln8od.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/I3z_nB8Axn7Gvle608fk5v5Ln8od.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/I3z_nB8Axn7Gvle608fk5v5Ln8op.xml b/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/I3z_nB8Axn7Gvle608fk5v5Ln8op.xml
new file mode 100644
index 0000000..e9ea0b9
--- /dev/null
+++ b/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/I3z_nB8Axn7Gvle608fk5v5Ln8op.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/PXxtj0wo_ob6SinqFTmOCKjfA38d.xml b/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/PXxtj0wo_ob6SinqFTmOCKjfA38d.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/PXxtj0wo_ob6SinqFTmOCKjfA38d.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/PXxtj0wo_ob6SinqFTmOCKjfA38p.xml b/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/PXxtj0wo_ob6SinqFTmOCKjfA38p.xml
new file mode 100644
index 0000000..01cb34e
--- /dev/null
+++ b/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/PXxtj0wo_ob6SinqFTmOCKjfA38p.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/TlnnT-Pq-WH4QBao_ByeEoWqtmMd.xml b/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/TlnnT-Pq-WH4QBao_ByeEoWqtmMd.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/TlnnT-Pq-WH4QBao_ByeEoWqtmMd.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/TlnnT-Pq-WH4QBao_ByeEoWqtmMp.xml b/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/TlnnT-Pq-WH4QBao_ByeEoWqtmMp.xml
new file mode 100644
index 0000000..155f4c5
--- /dev/null
+++ b/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/TlnnT-Pq-WH4QBao_ByeEoWqtmMp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/xIFtzLYxUWhFZliDXTE8xWnMOksd.xml b/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/xIFtzLYxUWhFZliDXTE8xWnMOksd.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/xIFtzLYxUWhFZliDXTE8xWnMOksd.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/xIFtzLYxUWhFZliDXTE8xWnMOksp.xml b/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/xIFtzLYxUWhFZliDXTE8xWnMOksp.xml
new file mode 100644
index 0000000..844d632
--- /dev/null
+++ b/resources/project/hjJloWDVwJVRCwGO0y5r9iO7IDk/xIFtzLYxUWhFZliDXTE8xWnMOksp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/qFRcMsci5bTUnTBevgtb2pITyQU/PqSoYPqIvTpSDTPHpeqhFTupFlcd.xml b/resources/project/qFRcMsci5bTUnTBevgtb2pITyQU/PqSoYPqIvTpSDTPHpeqhFTupFlcd.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/qFRcMsci5bTUnTBevgtb2pITyQU/PqSoYPqIvTpSDTPHpeqhFTupFlcd.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/qFRcMsci5bTUnTBevgtb2pITyQU/PqSoYPqIvTpSDTPHpeqhFTupFlcp.xml b/resources/project/qFRcMsci5bTUnTBevgtb2pITyQU/PqSoYPqIvTpSDTPHpeqhFTupFlcp.xml
new file mode 100644
index 0000000..844d632
--- /dev/null
+++ b/resources/project/qFRcMsci5bTUnTBevgtb2pITyQU/PqSoYPqIvTpSDTPHpeqhFTupFlcp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/qFRcMsci5bTUnTBevgtb2pITyQU/QVlZfneBwOtik9W8xTb2FChz-9Ud.xml b/resources/project/qFRcMsci5bTUnTBevgtb2pITyQU/QVlZfneBwOtik9W8xTb2FChz-9Ud.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/qFRcMsci5bTUnTBevgtb2pITyQU/QVlZfneBwOtik9W8xTb2FChz-9Ud.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/qFRcMsci5bTUnTBevgtb2pITyQU/QVlZfneBwOtik9W8xTb2FChz-9Up.xml b/resources/project/qFRcMsci5bTUnTBevgtb2pITyQU/QVlZfneBwOtik9W8xTb2FChz-9Up.xml
new file mode 100644
index 0000000..e9ea0b9
--- /dev/null
+++ b/resources/project/qFRcMsci5bTUnTBevgtb2pITyQU/QVlZfneBwOtik9W8xTb2FChz-9Up.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/qFRcMsci5bTUnTBevgtb2pITyQU/WyqGg5GYVbZvpUJlgpK2qgs9p_Qd.xml b/resources/project/qFRcMsci5bTUnTBevgtb2pITyQU/WyqGg5GYVbZvpUJlgpK2qgs9p_Qd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/qFRcMsci5bTUnTBevgtb2pITyQU/WyqGg5GYVbZvpUJlgpK2qgs9p_Qd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/qFRcMsci5bTUnTBevgtb2pITyQU/WyqGg5GYVbZvpUJlgpK2qgs9p_Qp.xml b/resources/project/qFRcMsci5bTUnTBevgtb2pITyQU/WyqGg5GYVbZvpUJlgpK2qgs9p_Qp.xml
new file mode 100644
index 0000000..01cb34e
--- /dev/null
+++ b/resources/project/qFRcMsci5bTUnTBevgtb2pITyQU/WyqGg5GYVbZvpUJlgpK2qgs9p_Qp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/qFRcMsci5bTUnTBevgtb2pITyQU/k1LHXoHEntiP5npj4OUEzFef0D0d.xml b/resources/project/qFRcMsci5bTUnTBevgtb2pITyQU/k1LHXoHEntiP5npj4OUEzFef0D0d.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/qFRcMsci5bTUnTBevgtb2pITyQU/k1LHXoHEntiP5npj4OUEzFef0D0d.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/u_8f8riMl9bapFIdVg6GQo796t8p.xml b/resources/project/qFRcMsci5bTUnTBevgtb2pITyQU/k1LHXoHEntiP5npj4OUEzFef0D0p.xml
similarity index 100%
rename from resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/u_8f8riMl9bapFIdVg6GQo796t8p.xml
rename to resources/project/qFRcMsci5bTUnTBevgtb2pITyQU/k1LHXoHEntiP5npj4OUEzFef0D0p.xml
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/E2mMq2X73DyjKhlQAouGqrsyLggd.xml b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/E2mMq2X73DyjKhlQAouGqrsyLggd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/E2mMq2X73DyjKhlQAouGqrsyLggd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/E2mMq2X73DyjKhlQAouGqrsyLggp.xml b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/E2mMq2X73DyjKhlQAouGqrsyLggp.xml
new file mode 100644
index 0000000..220f482
--- /dev/null
+++ b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/E2mMq2X73DyjKhlQAouGqrsyLggp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/FI0gxbH-PhwjE_riDQGHPyYMHksd.xml b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/FI0gxbH-PhwjE_riDQGHPyYMHksd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/FI0gxbH-PhwjE_riDQGHPyYMHksd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/FI0gxbH-PhwjE_riDQGHPyYMHksp.xml b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/FI0gxbH-PhwjE_riDQGHPyYMHksp.xml
new file mode 100644
index 0000000..bbe3722
--- /dev/null
+++ b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/FI0gxbH-PhwjE_riDQGHPyYMHksp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/SIL3u_W39LwE7HHYsarfFmr9gVQd.xml b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/SIL3u_W39LwE7HHYsarfFmr9gVQd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/SIL3u_W39LwE7HHYsarfFmr9gVQd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/SIL3u_W39LwE7HHYsarfFmr9gVQp.xml b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/SIL3u_W39LwE7HHYsarfFmr9gVQp.xml
new file mode 100644
index 0000000..8b6c356
--- /dev/null
+++ b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/SIL3u_W39LwE7HHYsarfFmr9gVQp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/hjJloWDVwJVRCwGO0y5r9iO7IDkd.xml b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/hjJloWDVwJVRCwGO0y5r9iO7IDkd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/hjJloWDVwJVRCwGO0y5r9iO7IDkd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/hjJloWDVwJVRCwGO0y5r9iO7IDkp.xml b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/hjJloWDVwJVRCwGO0y5r9iO7IDkp.xml
new file mode 100644
index 0000000..dd7e540
--- /dev/null
+++ b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/hjJloWDVwJVRCwGO0y5r9iO7IDkp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/qFRcMsci5bTUnTBevgtb2pITyQUd.xml b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/qFRcMsci5bTUnTBevgtb2pITyQUd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/qFRcMsci5bTUnTBevgtb2pITyQUd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/qFRcMsci5bTUnTBevgtb2pITyQUp.xml b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/qFRcMsci5bTUnTBevgtb2pITyQUp.xml
new file mode 100644
index 0000000..9210ff5
--- /dev/null
+++ b/resources/project/qaw0eS1zuuY1ar9TdPn1GMfrjbQ/qFRcMsci5bTUnTBevgtb2pITyQUp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/3jMunGDz3Fi7SRBu6cO_TfwwGvMd.xml b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/3jMunGDz3Fi7SRBu6cO_TfwwGvMd.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/3jMunGDz3Fi7SRBu6cO_TfwwGvMd.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/3jMunGDz3Fi7SRBu6cO_TfwwGvMp.xml b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/3jMunGDz3Fi7SRBu6cO_TfwwGvMp.xml
new file mode 100644
index 0000000..7ae9478
--- /dev/null
+++ b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/3jMunGDz3Fi7SRBu6cO_TfwwGvMp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/4Kdp3lDC1jW-ppVJPTsagDuC9Vcd.xml b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/4Kdp3lDC1jW-ppVJPTsagDuC9Vcd.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/4Kdp3lDC1jW-ppVJPTsagDuC9Vcd.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/4Kdp3lDC1jW-ppVJPTsagDuC9Vcp.xml b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/4Kdp3lDC1jW-ppVJPTsagDuC9Vcp.xml
new file mode 100644
index 0000000..fd703d9
--- /dev/null
+++ b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/4Kdp3lDC1jW-ppVJPTsagDuC9Vcp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/I-PKA8KS6agvfCPtEcX2cyhHpuQd.xml b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/I-PKA8KS6agvfCPtEcX2cyhHpuQd.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/I-PKA8KS6agvfCPtEcX2cyhHpuQd.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/NRbCR7m2f1_2pHz6LyHrTz7eFpc/NmnqsjHeF9rAhG9A30BKV_vI7tIp.xml b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/I-PKA8KS6agvfCPtEcX2cyhHpuQp.xml
similarity index 100%
rename from resources/project/NRbCR7m2f1_2pHz6LyHrTz7eFpc/NmnqsjHeF9rAhG9A30BKV_vI7tIp.xml
rename to resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/I-PKA8KS6agvfCPtEcX2cyhHpuQp.xml
diff --git a/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/NMo2l98scxoe2E_y1yh_Dt_bM6Qd.xml b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/NMo2l98scxoe2E_y1yh_Dt_bM6Qd.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/NMo2l98scxoe2E_y1yh_Dt_bM6Qd.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/NMo2l98scxoe2E_y1yh_Dt_bM6Qp.xml b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/NMo2l98scxoe2E_y1yh_Dt_bM6Qp.xml
new file mode 100644
index 0000000..de71410
--- /dev/null
+++ b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/NMo2l98scxoe2E_y1yh_Dt_bM6Qp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/dwr61zYPysrYty_j-OqW4Gx-4Akd.xml b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/dwr61zYPysrYty_j-OqW4Gx-4Akd.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/dwr61zYPysrYty_j-OqW4Gx-4Akd.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/dwr61zYPysrYty_j-OqW4Gx-4Akp.xml b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/dwr61zYPysrYty_j-OqW4Gx-4Akp.xml
new file mode 100644
index 0000000..bdaf37d
--- /dev/null
+++ b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/dwr61zYPysrYty_j-OqW4Gx-4Akp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/lFKW3WT6AJF2AoC67X9OsSF1uX4d.xml b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/lFKW3WT6AJF2AoC67X9OsSF1uX4d.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/lFKW3WT6AJF2AoC67X9OsSF1uX4d.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/lFKW3WT6AJF2AoC67X9OsSF1uX4p.xml b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/lFKW3WT6AJF2AoC67X9OsSF1uX4p.xml
new file mode 100644
index 0000000..844d632
--- /dev/null
+++ b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/lFKW3WT6AJF2AoC67X9OsSF1uX4p.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/oGsKvxjkC8sD8EXwFRxU-rf-Jb8d.xml b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/oGsKvxjkC8sD8EXwFRxU-rf-Jb8d.xml
new file mode 100644
index 0000000..99772b4
--- /dev/null
+++ b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/oGsKvxjkC8sD8EXwFRxU-rf-Jb8d.xml
@@ -0,0 +1,6 @@
+
+
+
+
+
+
\ No newline at end of file
diff --git a/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/oGsKvxjkC8sD8EXwFRxU-rf-Jb8p.xml b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/oGsKvxjkC8sD8EXwFRxU-rf-Jb8p.xml
new file mode 100644
index 0000000..b5d4f51
--- /dev/null
+++ b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/oGsKvxjkC8sD8EXwFRxU-rf-Jb8p.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/y0au_RWAZtoIPZaEsuAYoZxR4j4d.xml b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/y0au_RWAZtoIPZaEsuAYoZxR4j4d.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/y0au_RWAZtoIPZaEsuAYoZxR4j4d.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/y0au_RWAZtoIPZaEsuAYoZxR4j4p.xml b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/y0au_RWAZtoIPZaEsuAYoZxR4j4p.xml
new file mode 100644
index 0000000..01cb34e
--- /dev/null
+++ b/resources/project/tBBDcBPWdBTCTMSBG9IGJ_TsICk/y0au_RWAZtoIPZaEsuAYoZxR4j4p.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/uhUDZwLuHiPGihzjzILZj0glbh8/9I1NhbvmbTiuVshItfSCHZiDxxId.xml b/resources/project/uhUDZwLuHiPGihzjzILZj0glbh8/9I1NhbvmbTiuVshItfSCHZiDxxId.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/uhUDZwLuHiPGihzjzILZj0glbh8/9I1NhbvmbTiuVshItfSCHZiDxxId.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/uhUDZwLuHiPGihzjzILZj0glbh8/9I1NhbvmbTiuVshItfSCHZiDxxIp.xml b/resources/project/uhUDZwLuHiPGihzjzILZj0glbh8/9I1NhbvmbTiuVshItfSCHZiDxxIp.xml
new file mode 100644
index 0000000..2f0264c
--- /dev/null
+++ b/resources/project/uhUDZwLuHiPGihzjzILZj0glbh8/9I1NhbvmbTiuVshItfSCHZiDxxIp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/uhUDZwLuHiPGihzjzILZj0glbh8/LMc5a8ETDcRip3rYsQxn56S6obMd.xml b/resources/project/uhUDZwLuHiPGihzjzILZj0glbh8/LMc5a8ETDcRip3rYsQxn56S6obMd.xml
new file mode 100644
index 0000000..4356a6a
--- /dev/null
+++ b/resources/project/uhUDZwLuHiPGihzjzILZj0glbh8/LMc5a8ETDcRip3rYsQxn56S6obMd.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/resources/project/uhUDZwLuHiPGihzjzILZj0glbh8/LMc5a8ETDcRip3rYsQxn56S6obMp.xml b/resources/project/uhUDZwLuHiPGihzjzILZj0glbh8/LMc5a8ETDcRip3rYsQxn56S6obMp.xml
new file mode 100644
index 0000000..00ec4cc
--- /dev/null
+++ b/resources/project/uhUDZwLuHiPGihzjzILZj0glbh8/LMc5a8ETDcRip3rYsQxn56S6obMp.xml
@@ -0,0 +1,2 @@
+
+
\ No newline at end of file
diff --git a/sensingModels/@fixedCardinalSensor/fixedCardinalSensor.m b/sensingModels/@fixedCardinalSensor/fixedCardinalSensor.m
new file mode 100644
index 0000000..374d38a
--- /dev/null
+++ b/sensingModels/@fixedCardinalSensor/fixedCardinalSensor.m
@@ -0,0 +1,13 @@
+classdef fixedCardinalSensor
+ % Senses in the +/-x, +/- y directions at some specified fixed length
+ properties
+ alphaTilt = NaN;
+ r = 0.1; % fixed sensing length
+ end
+
+ methods (Access = public)
+ [obj] = initialize(obj, r);
+ [neighborValues, neighborPos] = sense(obj, agent, sensingObjective, domain, partitioning);
+ [value] = sensorPerformance(obj, agentPos, agentPan, agentTilt, targetPos);
+ end
+end
\ No newline at end of file
diff --git a/sensingModels/@fixedCardinalSensor/initialize.m b/sensingModels/@fixedCardinalSensor/initialize.m
new file mode 100644
index 0000000..c65b583
--- /dev/null
+++ b/sensingModels/@fixedCardinalSensor/initialize.m
@@ -0,0 +1,10 @@
+function obj = initialize(obj, r)
+ arguments(Input)
+ obj (1, 1) {mustBeA(obj, 'fixedCardinalSensor')};
+ r (1, 1) double;
+ end
+ arguments(Output)
+ obj (1, 1) {mustBeA(obj, 'fixedCardinalSensor')};
+ end
+ obj.r = r;
+end
\ No newline at end of file
diff --git a/sensingModels/@fixedCardinalSensor/sense.m b/sensingModels/@fixedCardinalSensor/sense.m
new file mode 100644
index 0000000..5369a22
--- /dev/null
+++ b/sensingModels/@fixedCardinalSensor/sense.m
@@ -0,0 +1,45 @@
+function [neighborValues, neighborPos] = sense(obj, agent, sensingObjective, domain, partitioning)
+ arguments (Input)
+ obj (1, 1) {mustBeA(obj, 'fixedCardinalSensor')};
+ agent (1, 1) {mustBeA(agent, 'agent')};
+ sensingObjective (1, 1) {mustBeA(sensingObjective, 'sensingObjective')};
+ domain (1, 1) {mustBeGeometry};
+ partitioning (:, :) double = NaN;
+ end
+ arguments (Output)
+ neighborValues (4, 1) double;
+ neighborPos (4, 3) double;
+ end
+
+ % Set alphaTilt to produce an FOV cone with radius 'r' on the ground
+ obj.alphaTilt = atan2(obj.r, agent.pos(3));
+
+ % Evaluate objective at position offsets +/-[r, 0, 0] and +/-[0, r, 0]
+ currentPos = agent.pos(1:2);
+ neighborPos = [currentPos(1) + obj.r, currentPos(2); ... % (+x)
+ currentPos(1), currentPos(2) + obj.r; ... % (+y)
+ currentPos(1) - obj.r, currentPos(2); ... % (-x)
+ currentPos(1), currentPos(2) - obj.r; ... % (-y)
+ ];
+
+ % Check for neighbor positions that fall outside of the domain
+ outOfBounds = false(size(neighborPos, 1), 1);
+ for ii = 1:size(neighborPos, 1)
+ if ~domain.contains([neighborPos(ii, :), 0])
+ outOfBounds(ii) = true;
+ end
+ end
+
+ % Replace out of bounds positions with inoffensive in-bounds positions
+ neighborPos(outOfBounds, 1:3) = repmat(agent.pos, sum(outOfBounds), 1);
+
+ % Sense values at selected positions
+ neighborValues = [sensingObjective.objectiveFunction(neighborPos(1, 1), neighborPos(1, 2)), ... % (+x)
+ sensingObjective.objectiveFunction(neighborPos(2, 1), neighborPos(2, 2)), ... % (+y)
+ sensingObjective.objectiveFunction(neighborPos(3, 1), neighborPos(3, 2)), ... % (-x)
+ sensingObjective.objectiveFunction(neighborPos(4, 1), neighborPos(4, 2)), ... % (-y)
+ ];
+
+ % Prevent out of bounds locations from ever possibly being selected
+ neighborValues(outOfBounds) = 0;
+end
\ No newline at end of file
diff --git a/sensingModels/@fixedCardinalSensor/sensorPerformance.m b/sensingModels/@fixedCardinalSensor/sensorPerformance.m
new file mode 100644
index 0000000..2c2a294
--- /dev/null
+++ b/sensingModels/@fixedCardinalSensor/sensorPerformance.m
@@ -0,0 +1,14 @@
+function value = sensorPerformance(obj, agentPos, agentPan, agentTilt, targetPos)
+ arguments (Input)
+ obj (1, 1) {mustBeA(obj, 'fixedCardinalSensor')};
+ agentPos (1, 3) double;
+ agentPan (1, 1) double;
+ agentTilt (1, 1) double;
+ targetPos (:, 3) double;
+ end
+ arguments (Output)
+ value (:, 1) double;
+ end
+
+ value = 0.5 * ones(size(targetPos, 1), 1);
+end
\ No newline at end of file
diff --git a/sensingModels/@sigmoidSensor/initialize.m b/sensingModels/@sigmoidSensor/initialize.m
new file mode 100644
index 0000000..7938fa8
--- /dev/null
+++ b/sensingModels/@sigmoidSensor/initialize.m
@@ -0,0 +1,21 @@
+function obj = initialize(obj, alphaDist, betaDist, alphaPan, betaPan, alphaTilt, betaTilt)
+ arguments (Input)
+ obj (1, 1) {mustBeA(obj, 'sigmoidSensor')}
+ alphaDist (1, 1) double;
+ betaDist (1, 1) double;
+ alphaPan (1, 1) double;
+ betaPan (1, 1) double;
+ alphaTilt (1, 1) double;
+ betaTilt (1, 1) double;
+ end
+ arguments (Output)
+ obj (1, 1) {mustBeA(obj, 'sigmoidSensor')}
+ end
+
+ obj.alphaDist = alphaDist;
+ obj.betaDist = betaDist;
+ obj.alphaPan = alphaPan;
+ obj.betaPan = betaPan;
+ obj.alphaTilt = alphaTilt;
+ obj.betaTilt = betaTilt;
+end
\ No newline at end of file
diff --git a/sensingModels/@sigmoidSensor/sense.m b/sensingModels/@sigmoidSensor/sense.m
new file mode 100644
index 0000000..c7a2ea3
--- /dev/null
+++ b/sensingModels/@sigmoidSensor/sense.m
@@ -0,0 +1,21 @@
+function [values, positions] = sense(obj, agent, sensingObjective, domain, partitioning)
+ arguments (Input)
+ obj (1, 1) {mustBeA(obj, 'sigmoidSensor')};
+ agent (1, 1) {mustBeA(agent, 'agent')};
+ sensingObjective (1, 1) {mustBeA(sensingObjective, 'sensingObjective')};
+ domain (1, 1) {mustBeGeometry};
+ partitioning (:, :) double;
+ end
+ arguments (Output)
+ values (:, 1) double;
+ positions (:, 3) double;
+ end
+
+ % Find positions for this agent's assigned partition in the domain
+ idx = partitioning == agent.index;
+ positions = [sensingObjective.X(idx), sensingObjective.Y(idx), zeros(size(sensingObjective.X(idx)))];
+
+ % Evaluate objective function at every point in this agent's
+ % assigned partiton
+ values = sensingObjective.values(idx);
+end
\ No newline at end of file
diff --git a/sensingModels/@sigmoidSensor/sensorPerformance.m b/sensingModels/@sigmoidSensor/sensorPerformance.m
new file mode 100644
index 0000000..f82d344
--- /dev/null
+++ b/sensingModels/@sigmoidSensor/sensorPerformance.m
@@ -0,0 +1,23 @@
+function value = sensorPerformance(obj, agentPos, agentPan, agentTilt, targetPos)
+ arguments (Input)
+ obj (1, 1) {mustBeA(obj, 'sigmoidSensor')};
+ agentPos (1, 3) double;
+ agentPan (1, 1) double;
+ agentTilt (1, 1) double;
+ targetPos (:, 3) double;
+ end
+ arguments (Output)
+ value (:, 1) double;
+ end
+
+ d = vecnorm(agentPos - targetPos, 2, 2); % distance from sensor to target
+ x = vecnorm(agentPos(1:2) - targetPos(:, 1:2), 2, 2); % distance from sensor nadir to target nadir (i.e. distance ignoring height difference)
+ tiltAngle = atan2(targetPos(:, 3) - agentPos(3), x) - agentTilt;
+
+ % Membership functions
+ mu_d = 1 - (1 ./ (1 + exp(-obj.betaDist .* (d - obj.alphaDist)))); % distance
+ mu_p = 1; % pan
+ mu_t = (1 ./ (1 + exp(-obj.betaPan .* (tiltAngle + obj.alphaPan)))) - (1 ./ (1 + exp(-obj.betaPan .* (tiltAngle - obj.alphaPan)))); % tilt
+
+ value = mu_d .* mu_p .* mu_t * 1e12;
+end
\ No newline at end of file
diff --git a/sensingModels/@sigmoidSensor/sigmoidSensor.m b/sensingModels/@sigmoidSensor/sigmoidSensor.m
new file mode 100644
index 0000000..577d12c
--- /dev/null
+++ b/sensingModels/@sigmoidSensor/sigmoidSensor.m
@@ -0,0 +1,17 @@
+classdef sigmoidSensor
+ properties (SetAccess = private, GetAccess = public)
+ % Sensor parameters
+ alphaDist = NaN;
+ betaDist = NaN;
+ alphaPan = NaN;
+ betaPan = NaN;
+ alphaTilt = NaN;
+ betaTilt = NaN;
+ end
+
+ methods (Access = public)
+ [obj] = initialize(obj, alphaDist, betaDist, alphaPan, betaPan, alphaTilt, betaTilt);
+ [values, positions] = sense(obj, agent, sensingObjective, domain, partitioning);
+ [value] = sensorPerformance(obj, agentPos, agentPan, agentTilt, targetPos);
+ end
+end
\ No newline at end of file
diff --git a/sensingModels/fixedCardinalSensor.m b/sensingModels/fixedCardinalSensor.m
deleted file mode 100644
index 96da85c..0000000
--- a/sensingModels/fixedCardinalSensor.m
+++ /dev/null
@@ -1,79 +0,0 @@
-classdef fixedCardinalSensor
- % Senses in the +/-x, +/- y directions at some specified fixed length
- properties
- alphaTilt = NaN;
- r = 0.1; % fixed sensing length
- end
-
- methods (Access = public)
- function obj = initialize(obj, r)
- arguments(Input)
- obj (1, 1) {mustBeA(obj, 'fixedCardinalSensor')};
- r (1, 1) double;
- end
- arguments(Output)
- obj (1, 1) {mustBeA(obj, 'fixedCardinalSensor')};
- end
- obj.r = r;
- end
- function [neighborValues, neighborPos] = sense(obj, agent, sensingObjective, domain, partitioning)
- arguments (Input)
- obj (1, 1) {mustBeA(obj, 'fixedCardinalSensor')};
- agent (1, 1) {mustBeA(agent, 'agent')};
- sensingObjective (1, 1) {mustBeA(sensingObjective, 'sensingObjective')};
- domain (1, 1) {mustBeGeometry};
- partitioning (:, :) double = NaN;
- end
- arguments (Output)
- neighborValues (4, 1) double;
- neighborPos (4, 3) double;
- end
-
- % Set alphaTilt to produce an FOV cone with radius 'r' on the ground
- obj.alphaTilt = atan2(obj.r, agent.pos(3));
-
- % Evaluate objective at position offsets +/-[r, 0, 0] and +/-[0, r, 0]
- currentPos = agent.pos(1:2);
- neighborPos = [currentPos(1) + obj.r, currentPos(2); ... % (+x)
- currentPos(1), currentPos(2) + obj.r; ... % (+y)
- currentPos(1) - obj.r, currentPos(2); ... % (-x)
- currentPos(1), currentPos(2) - obj.r; ... % (-y)
- ];
-
- % Check for neighbor positions that fall outside of the domain
- outOfBounds = false(size(neighborPos, 1), 1);
- for ii = 1:size(neighborPos, 1)
- if ~domain.contains([neighborPos(ii, :), 0])
- outOfBounds(ii) = true;
- end
- end
-
- % Replace out of bounds positions with inoffensive in-bounds positions
- neighborPos(outOfBounds, 1:3) = repmat(agent.pos, sum(outOfBounds), 1);
-
- % Sense values at selected positions
- neighborValues = [sensingObjective.objectiveFunction(neighborPos(1, 1), neighborPos(1, 2)), ... % (+x)
- sensingObjective.objectiveFunction(neighborPos(2, 1), neighborPos(2, 2)), ... % (+y)
- sensingObjective.objectiveFunction(neighborPos(3, 1), neighborPos(3, 2)), ... % (-x)
- sensingObjective.objectiveFunction(neighborPos(4, 1), neighborPos(4, 2)), ... % (-y)
- ];
-
- % Prevent out of bounds locations from ever possibly being selected
- neighborValues(outOfBounds) = 0;
- end
- function value = sensorPerformance(obj, agentPos, agentPan, agentTilt, targetPos)
- arguments (Input)
- obj (1, 1) {mustBeA(obj, 'fixedCardinalSensor')};
- agentPos (1, 3) double;
- agentPan (1, 1) double;
- agentTilt (1, 1) double;
- targetPos (:, 3) double;
- end
- arguments (Output)
- value (:, 1) double;
- end
-
- value = 0.5 * ones(size(targetPos, 1), 1);
- end
- end
-end
\ No newline at end of file
diff --git a/sensingModels/sigmoidSensor.m b/sensingModels/sigmoidSensor.m
deleted file mode 100644
index 8eed9ee..0000000
--- a/sensingModels/sigmoidSensor.m
+++ /dev/null
@@ -1,79 +0,0 @@
-classdef sigmoidSensor
- properties (SetAccess = private, GetAccess = public)
- % Sensor parameters
- alphaDist = NaN;
- betaDist = NaN;
- alphaPan = NaN;
- betaPan = NaN;
- alphaTilt = NaN;
- betaTilt = NaN;
- end
-
- methods (Access = public)
- function obj = initialize(obj, alphaDist, betaDist, alphaPan, betaPan, alphaTilt, betaTilt)
- arguments (Input)
- obj (1, 1) {mustBeA(obj, 'sigmoidSensor')}
- alphaDist (1, 1) double;
- betaDist (1, 1) double;
- alphaPan (1, 1) double;
- betaPan (1, 1) double;
- alphaTilt (1, 1) double;
- betaTilt (1, 1) double;
- end
- arguments (Output)
- obj (1, 1) {mustBeA(obj, 'sigmoidSensor')}
- end
-
- obj.alphaDist = alphaDist;
- obj.betaDist = betaDist;
- obj.alphaPan = alphaPan;
- obj.betaPan = betaPan;
- obj.alphaTilt = alphaTilt;
- obj.betaTilt = betaTilt;
- end
- function [values, positions] = sense(obj, agent, sensingObjective, domain, partitioning)
- arguments (Input)
- obj (1, 1) {mustBeA(obj, 'sigmoidSensor')};
- agent (1, 1) {mustBeA(agent, 'agent')};
- sensingObjective (1, 1) {mustBeA(sensingObjective, 'sensingObjective')};
- domain (1, 1) {mustBeGeometry};
- partitioning (:, :) double;
- end
- arguments (Output)
- values (:, 1) double;
- positions (:, 3) double;
- end
-
- % Find positions for this agent's assigned partition in the domain
- idx = partitioning == agent.index;
- positions = [sensingObjective.X(idx), sensingObjective.Y(idx), zeros(size(sensingObjective.X(idx)))];
-
- % Evaluate objective function at every point in this agent's
- % assigned partiton
- values = sensingObjective.values(idx);
- end
- function value = sensorPerformance(obj, agentPos, agentPan, agentTilt, targetPos)
- arguments (Input)
- obj (1, 1) {mustBeA(obj, 'sigmoidSensor')};
- agentPos (1, 3) double;
- agentPan (1, 1) double;
- agentTilt (1, 1) double;
- targetPos (:, 3) double;
- end
- arguments (Output)
- value (:, 1) double;
- end
-
- d = vecnorm(agentPos - targetPos, 2, 2); % distance from sensor to target
- x = vecnorm(agentPos(1:2) - targetPos(:, 1:2), 2, 2); % distance from sensor nadir to target nadir (i.e. distance ignoring height difference)
- tiltAngle = atan2(targetPos(:, 3) - agentPos(3), x) - agentTilt;
-
- % Membership functions
- mu_d = 1 - (1 ./ (1 + exp(-obj.betaDist .* (d - obj.alphaDist)))); % distance
- mu_p = 1; % pan
- mu_t = (1 ./ (1 + exp(-obj.betaPan .* (tiltAngle + obj.alphaPan)))) - (1 ./ (1 + exp(-obj.betaPan .* (tiltAngle - obj.alphaPan)))); % tilt
-
- value = mu_d .* mu_p .* mu_t * 1e12;
- end
- end
-end
\ No newline at end of file
diff --git a/sensingObjective.m b/sensingObjective.m
deleted file mode 100644
index 5ca08bd..0000000
--- a/sensingObjective.m
+++ /dev/null
@@ -1,86 +0,0 @@
-classdef sensingObjective
- % Sensing objective definition parent class
- properties (SetAccess = private, GetAccess = public)
- label = "";
- groundAlt = 0;
- groundPos = [0, 0];
- discretizationStep = 1;
- objectiveFunction = @(x, y) 0; % define objective functions over a grid in this manner
- X = [];
- Y = [];
- values = [];
- end
-
- methods (Access = public)
- function obj = initialize(obj, objectiveFunction, footprint, groundAlt, discretizationStep)
- arguments (Input)
- obj (1,1) {mustBeA(obj, 'sensingObjective')};
- objectiveFunction (1, 1) {mustBeA(objectiveFunction, 'function_handle')};
- footprint (:, 2) double;
- groundAlt (1, 1) double = 0;
- discretizationStep (1, 1) double = 1;
- end
- arguments (Output)
- obj (1,1) {mustBeA(obj, 'sensingObjective')};
- end
-
- obj.groundAlt = groundAlt;
-
- % Extract footprint limits
- xMin = min(footprint(:, 1));
- xMax = max(footprint(:, 1));
- yMin = min(footprint(:, 2));
- yMax = max(footprint(:, 2));
-
- xGrid = unique([xMin:discretizationStep:xMax, xMax]);
- yGrid = unique([yMin:discretizationStep:yMax, yMax]);
-
- % Store grid points for plotting later
- [obj.X, obj.Y] = meshgrid(xGrid, yGrid);
-
- % Evaluate function over grid points
- obj.objectiveFunction = objectiveFunction;
- obj.values = reshape(obj.objectiveFunction(obj.X, obj.Y), size(obj.X));
-
- % store ground position
- idx = obj.values == max(obj.values, [], "all");
- obj.groundPos = [obj.X(idx), obj.Y(idx)];
- end
- function f = plot(obj, ind, f)
- arguments (Input)
- obj (1,1) {mustBeA(obj, 'sensingObjective')};
- ind (1, :) double = NaN;
- f (1,1) {mustBeA(f, 'matlab.ui.Figure')} = figure;
- end
- arguments (Output)
- f (1,1) {mustBeA(f, 'matlab.ui.Figure')};
- end
-
- % Create axes if they don't already exist
- f = firstPlotSetup(f);
-
- % Plot gradient on the "floor" of the domain
- if isnan(ind)
- hold(f.CurrentAxes, "on");
- o = surf(f.CurrentAxes, obj.X, obj.Y, repmat(obj.groundAlt, size(obj.X)), obj.values ./ max(obj.values, [], "all"), 'EdgeColor', 'none');
- o.HitTest = 'off';
- o.PickableParts = 'none';
- hold(f.CurrentAxes, "off");
-
- else
- hold(f.Children(1).Children(ind(1)), "on");
- o = surf(f.Children(1).Children(ind(1)), obj.X, obj.Y, repmat(obj.groundAlt, size(obj.X)), obj.values ./ max(obj.values, [], "all"), 'EdgeColor', 'none');
- o.HitTest = 'off';
- o.PickableParts = 'none';
- hold(f.Children(1).Children(ind(1)), "off");
- end
-
- % Add to other perspectives
- if size(ind, 2) > 1
- for ii = 2:size(ind, 2)
- copyobj(o, f.Children(1).Children(ind(ii)));
- end
- end
- end
- end
-end
\ No newline at end of file
diff --git a/test_miSim.m b/test/test_miSim.m
similarity index 99%
rename from test_miSim.m
rename to test/test_miSim.m
index ff451b0..5952af9 100644
--- a/test_miSim.m
+++ b/test/test_miSim.m
@@ -49,7 +49,7 @@ classdef test_miSim < matlab.unittest.TestCase
% Using a bivariate normal distribution
% Set peak position (mean)
mu = tc.domain.minCorner;
- while tc.domain.interiorDistance(mu) < tc.protectedRange
+ while tc.domain.distance(mu) < tc.protectedRange
mu = tc.domain.random();
end
mu(3) = 0;
@@ -191,8 +191,8 @@ classdef test_miSim < matlab.unittest.TestCase
candidateGeometry = candidateGeometry.initialize([candidatePos - tc.collisionRanges(ii) * ones(1, 3); candidatePos + tc.collisionRanges(ii) * ones(1, 3)], REGION_TYPE.COLLISION, sprintf("Agent %d collision volume", ii));
% Initialize candidate agent sensor model
- sensor = fixedCardinalSensor;
- sensor = sensor.initialize(tc.sensingLength);
+ sensor = sigmoidSensor;
+ sensor = sensor.initialize(2.5, 3, NaN, NaN, deg2rad(15), 3);
% Initialize candidate agent
newAgent = tc.agents{ii}.initialize(candidatePos, zeros(1,3), 0, 0, candidateGeometry, sensor, @gradientAscent, tc.comRange, ii, sprintf("Agent %d", ii));
diff --git a/firstPlotSetup.m b/util/firstPlotSetup.m
similarity index 100%
rename from firstPlotSetup.m
rename to util/firstPlotSetup.m
diff --git a/validators/agentsCrowdObjective.m b/util/validators/agentsCrowdObjective.m
similarity index 100%
rename from validators/agentsCrowdObjective.m
rename to util/validators/agentsCrowdObjective.m
diff --git a/validators/arguments/mustBeGeometry.m b/util/validators/arguments/mustBeGeometry.m
similarity index 100%
rename from validators/arguments/mustBeGeometry.m
rename to util/validators/arguments/mustBeGeometry.m
diff --git a/validators/arguments/mustBeSensor.m b/util/validators/arguments/mustBeSensor.m
similarity index 100%
rename from validators/arguments/mustBeSensor.m
rename to util/validators/arguments/mustBeSensor.m
diff --git a/validators/domainContainsObstacle.m b/util/validators/domainContainsObstacle.m
similarity index 100%
rename from validators/domainContainsObstacle.m
rename to util/validators/domainContainsObstacle.m
diff --git a/validators/geometryIntersects.m b/util/validators/geometryIntersects.m
similarity index 100%
rename from validators/geometryIntersects.m
rename to util/validators/geometryIntersects.m
diff --git a/validators/obstacleCoversObjective.m b/util/validators/obstacleCoversObjective.m
similarity index 100%
rename from validators/obstacleCoversObjective.m
rename to util/validators/obstacleCoversObjective.m
diff --git a/validators/obstacleCrowdsObjective.m b/util/validators/obstacleCrowdsObjective.m
similarity index 100%
rename from validators/obstacleCrowdsObjective.m
rename to util/validators/obstacleCrowdsObjective.m