scenario csv on both platforms

This commit is contained in:
2026-02-28 19:36:58 -08:00
parent 5e52292b71
commit 1d4f59734b
15 changed files with 739 additions and 293 deletions

View File

@@ -49,7 +49,13 @@ function [obj] = constrainMotion(obj)
r_sum_ij = obj.agents{ii}.collisionGeometry.radius + obj.agents{jj}.collisionGeometry.radius;
v_max_ij = max(obj.agents{ii}.initialStepSize, obj.agents{jj}.initialStepSize) / obj.timestep;
slack = -(4 * r_sum_ij * v_max_ij / obj.barrierGain)^(1 / obj.barrierExponent);
if norm(A(kk, :)) < 1e-9
% Agents are coincident: A-row is zero, so b < 0 would make
% 0 b unsatisfiable. Fall back to b = 0 (no correction possible).
b(kk) = 0;
else
b(kk) = obj.barrierGain * max(slack, h(ii, jj))^obj.barrierExponent;
end
kk = kk + 1;
end
end

View File

@@ -1,4 +1,25 @@
function obj = initializeFromCsv(obj, csvPath)
% INITIALIZEFROMCSV Initialize miSim from an AERPAW scenario CSV file.
%
% Reads all guidance parameters, domain geometry, initial UAV positions,
% and obstacle definitions from the CSV, then builds and initialises the
% simulation. Ends by calling the standard obj.initialize(...) method.
%
% This is the MATLAB-path counterpart to the compiled path that unpacks a
% flat scenarioParams array in guidance_step.m. It is only ever called
% from within a coder.target('MATLAB') guard and is never compiled.
%
% Usage (inside guidance_step.m on MATLAB path):
% sim = sim.initializeFromCsv('aerpaw/config/scenario.csv');
%
% Expected CSV columns (see scenario.csv):
% timestep, maxIter, minAlt, discretizationStep, protectedRange,
% initialStepSize, barrierGain, barrierExponent, collisionRadius, comRange,
% alphaDist, betaDist, alphaTilt, betaTilt,
% domainMin ("x,y,z"), domainMax ("x,y,z"), objectivePos ("x,y"),
% initialPositions (flat "x1,y1,z1, x2,y2,z2,..."),
% numObstacles, obstacleMin (flat), obstacleMax (flat)
arguments (Input)
obj (1, 1) {mustBeA(obj, 'miSim')};
csvPath (1, 1) string;
@@ -7,6 +28,79 @@ function obj = initializeFromCsv(obj, csvPath)
obj (1, 1) {mustBeA(obj, 'miSim')};
end
params = obj.readScenarioCsv(tc.csvPath);
% ---- Parse CSV via readScenarioCsv ---------------------------------------
scenario = obj.readScenarioCsv(csvPath);
TIMESTEP = scenario.timestep;
MAX_ITER = scenario.maxIter;
MIN_ALT = scenario.minAlt;
DISCRETIZATION_STEP = scenario.discretizationStep;
PROTECTED_RANGE = scenario.protectedRange;
INITIAL_STEP_SIZE = scenario.initialStepSize;
BARRIER_GAIN = scenario.barrierGain;
BARRIER_EXPONENT = scenario.barrierExponent;
COLLISION_RADIUS = scenario.collisionRadius;
COMMS_RANGE = scenario.comRange;
ALPHA_DIST = scenario.alphaDist;
BETA_DIST = scenario.betaDist;
ALPHA_TILT = scenario.alphaTilt;
BETA_TILT = scenario.betaTilt;
DOMAIN_MIN = scenario.domainMin; % 1×3
DOMAIN_MAX = scenario.domainMax; % 1×3
OBJECTIVE_GROUND_POS = scenario.objectivePos; % 1×2
SENSOR_PERFORMANCE_MINIMUM = scenario.sensorPerformanceMinimum; % scalar
% Initial UAV positions: flat vector reshaped to N×3
flatPos = scenario.initialPositions; % 1×(3*N)
assert(mod(numel(flatPos), 3) == 0, ...
"initialPositions must have a multiple of 3 values; got %d", numel(flatPos));
positions = reshape(flatPos, 3, [])'; % N×3
numAgents = size(positions, 1);
numObstacles = scenario.numObstacles;
% ---- Build domain --------------------------------------------------------
dom = rectangularPrism;
dom = dom.initialize([DOMAIN_MIN; DOMAIN_MAX], REGION_TYPE.DOMAIN, "Guidance Domain");
% ---- Build sensing objective (MATLAB path: objectiveFunctionWrapper) -----
dom.objective = sensingObjective;
objFcn = objectiveFunctionWrapper(OBJECTIVE_GROUND_POS, 3 * eye(2));
dom.objective = dom.objective.initialize(objFcn, dom, DISCRETIZATION_STEP, PROTECTED_RANGE, SENSOR_PERFORMANCE_MINIMUM);
% ---- Build shared sensor model -------------------------------------------
sensor = sigmoidSensor;
sensor = sensor.initialize(ALPHA_DIST, BETA_DIST, ALPHA_TILT, BETA_TILT);
% ---- Initialise agents from scenario positions ---------------------------
agentList = cell(numAgents, 1);
for ii = 1:numAgents
pos = positions(ii, :);
geom = spherical;
geom = geom.initialize(pos, COLLISION_RADIUS, REGION_TYPE.COLLISION, ...
sprintf("UAV %d Collision", ii));
ag = agent;
ag = ag.initialize(pos, geom, sensor, COMMS_RANGE, MAX_ITER, ...
INITIAL_STEP_SIZE, sprintf("UAV %d", ii));
agentList{ii} = ag;
end
% ---- Build obstacles from CSV --------------------------------------------
obstacleList = cell(numObstacles, 1);
if numObstacles > 0
obsMin = reshape(scenario.obstacleMin, 3, numObstacles)'; % N×3
obsMax = reshape(scenario.obstacleMax, 3, numObstacles)';
for ii = 1:numObstacles
obs = rectangularPrism;
obs = obs.initialize([obsMin(ii, :); obsMax(ii, :)], ...
REGION_TYPE.OBSTACLE, sprintf("Obstacle %d", ii));
obstacleList{ii} = obs;
end
end
% ---- Initialise simulation (plots and video disabled) --------------------
obj = obj.initialize(dom, agentList, BARRIER_GAIN, BARRIER_EXPONENT, ...
MIN_ALT, TIMESTEP, MAX_ITER, obstacleList, false, false);
end

View File

@@ -1,6 +1,6 @@
function scenario = readScenarioCsv(obj, csvPath)
arguments (Input)
obj (1, 1) {mustBeA(obj, 'miSim')};
obj (1, 1) {mustBeA(obj, 'miSim')}; %#ok<INUSA>
csvPath (1, 1) string;
end
arguments (Output)
@@ -8,27 +8,62 @@ function scenario = readScenarioCsv(obj, csvPath)
end
% File input validation
assert(isfile(csvPath), "%s is not a valid filepath.");
assert(endsWith(csvPath, ".csv"), "%s is not a CSV file.");
assert(isfile(csvPath), "%s is not a valid filepath.", csvPath);
assert(endsWith(csvPath, ".csv"), "%s is not a CSV file.", csvPath);
% Read file
csv = readtable(csvPath, "TextType", "String", "NumHeaderLines", 0, "VariableNamingRule", "Preserve");
csv.Properties.VariableNames = ["timestep", "maxIter", "minAlt", "discretizationStep", "protectedRange", "sensorPerformanceMinimum", "initialStepSize", "barrierGain", "barrierExponent", "numObstacles", "numAgents", "collisionRadius", "comRange", "alphaDist", "betaDist", "alphaTilt", "betaTilt"];
% Read the first two lines directly avoids readtable's quoting
% requirement that '"' must immediately follow ',' (no leading space).
fid = fopen(csvPath, 'r');
headerLine = fgetl(fid);
dataLine = fgetl(fid);
fclose(fid);
for ii = 1:size(csv.Properties.VariableNames, 2)
csv.(csv.Properties.VariableNames{ii}) = cell2mat(cellfun(@(x) str2num(x), csv.(csv.Properties.VariableNames{ii}), "UniformOutput", false));
end
assert(ischar(headerLine) && ischar(dataLine), ...
"CSV must have a header row and at least one data row.");
% Put params into standard structure
scenario = struct("timestep", csv.timestep, "maxIter", csv.maxIter, "minAlt", csv.minAlt, "discretizationStep", csv.discretizationStep, ...
"protectedRange", csv.protectedRange, "sensorPerformanceMinimum", csv.sensorPerformanceMinimum, "initialStepSize", csv.initialStepSize, ...
"barrierGain", csv.barrierGain, "barrierExponent", csv.barrierExponent, "numObstacles", csv.numObstacles,...
"numAgents", csv.numAgents, "collisionRadius", csv.collisionRadius, "comRange", csv.comRange, "alphaDist", csv.alphaDist, ...
"betaDist", csv.betaDist, "alphaTilt", csv.alphaTilt, "betaTilt", csv.betaTilt);
% Parse header: simple comma split + trim (no quoting expected in names)
headers = strtrim(strsplit(headerLine, ','));
% size check
fns = fieldnames(scenario);
for ii = 2:size(fns, 1)
assert(size(scenario.(fns{ii}), 1) == size(scenario.(fns{ii - 1}), 1), "Mismatched number of rows in scenario definition CSV");
% Parse data row: comma split that respects double-quoted fields
fields = splitQuotedCSV(dataLine);
assert(numel(fields) == numel(headers), ...
"CSV data row has %d fields but header has %d columns.", ...
numel(fields), numel(headers));
% Build output struct: strip outer quotes, trim whitespace, convert to numeric.
% str2num handles scalar ("5") and vector ("1.0, 2.0, 3.0") fields alike.
% Empty fields ("") become [] via str2num('') == [].
scenario = struct();
for ii = 1:numel(headers)
raw = strtrim(stripQuotes(fields{ii}));
scenario.(headers{ii}) = str2num(raw); %#ok<ST2NM>
end
end
% -------------------------------------------------------------------------
function fields = splitQuotedCSV(line)
% Split a CSV row by commas, respecting double-quoted fields.
% Fields may have leading/trailing whitespace around quotes.
fields = {};
inQuote = false;
start = 1;
for ii = 1:length(line)
if line(ii) == '"'
inQuote = ~inQuote;
elseif line(ii) == ',' && ~inQuote
fields{end+1} = line(start:ii-1); %#ok<AGROW>
start = ii + 1;
end
end
fields{end+1} = line(start:end);
end
% -------------------------------------------------------------------------
function s = stripQuotes(s)
% Trim whitespace then remove a single layer of enclosing double-quotes.
s = strtrim(s);
if length(s) >= 2 && s(1) == '"' && s(end) == '"'
s = s(2:end-1);
end
end

View File

@@ -0,0 +1,2 @@
timestep, maxIter, minAlt, discretizationStep, protectedRange, initialStepSize, barrierGain, barrierExponent, collisionRadius, comRange, alphaDist, betaDist, alphaTilt, betaTilt, domainMin, domainMax, objectivePos, sensorPerformanceMinimum, initialPositions, numObstacles, obstacleMin, obstacleMax
5, 100, 25.0, 0.1, 1.0, 1.0, 100, 3, 3.0, 60.0, 60.0, 0.2, 10.0, 1.0, "0.0, 0.0, 0.0", "20.0, 20.0, 55.0", "10.0, 10.0", 1e-6, "5.0, 10.0, 45.0, 15.0, 10.0, 30.0", 0, "", ""
1 timestep maxIter minAlt discretizationStep protectedRange initialStepSize barrierGain barrierExponent collisionRadius comRange alphaDist betaDist alphaTilt betaTilt domainMin domainMax objectivePos sensorPerformanceMinimum initialPositions numObstacles obstacleMin obstacleMax
2 5 100 25.0 0.1 1.0 1.0 100 3 3.0 60.0 60.0 0.2 10.0 1.0 0.0, 0.0, 0.0 20.0, 20.0, 55.0 10.0, 10.0 1e-6 5.0, 10.0, 45.0, 15.0, 10.0, 30.0 0

View File

@@ -1,23 +0,0 @@
# AERPAW Controller (Server) Configuration
# Target waypoints in ENU coordinates (meters: east, north, up)
# Grouped by client: first N entries = Client 1, next N = Client 2, etc.
# Each client must have the same number of waypoints.
#
# Flight pattern:
# UAV 1 (45m alt): straight line along x-axis, 4m intervals
# UAV 2 (30m alt): triangular path, diverges then converges
#
# WP1: x=0 (close, ~10m apart)
# WP2: x=4 (medium, ~20m apart)
# WP3: x=8 (far, ~25m apart)
# WP4: x=12 (medium, ~20m apart)
# WP5: x=16 (close, ~10m apart)
#
# Max distance from origin: ~22m (all waypoints within geofence)
#
targets:
# UAV 1 Initial Position — west side of guidance domain
- [5.0, 10.0, 45.0]
# UAV 2 Initial Position — east side of guidance domain
- [15.0, 10.0, 30.0]

View File

@@ -88,6 +88,11 @@
<Size type="coderapp.internal.codertype.Dimension"/>
<Size type="coderapp.internal.codertype.Dimension"/>
</Types>
<Types id="18" type="coderapp.internal.codertype.PrimitiveType">
<ClassName>int32</ClassName>
<Size type="coderapp.internal.codertype.Dimension"/>
<Size type="coderapp.internal.codertype.Dimension"/>
</Types>
</Types>
</coderapp.internal.interface.project.Interface>
</MF0>
@@ -329,445 +334,445 @@
</Artifacts>
<Artifacts id="40" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/cone.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/cone.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="41" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/cone.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/controller.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="42" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/controller.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/controller.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="43" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/controller.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/controller_data.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="44" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/controller_data.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/controller_data.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="45" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/controller_data.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/controller_initialize.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="46" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/controller_initialize.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/controller_initialize.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="47" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/controller_initialize.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/controller_internal_types.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="48" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/controller_internal_types.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/controller_terminate.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="49" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/controller_terminate.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/controller_terminate.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="50" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/controller_terminate.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/controller_types.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="51" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/controller_types.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/countsort.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="52" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/countsort.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/countsort.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="53" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/countsort.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/deleteColMoveEnd.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="54" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/deleteColMoveEnd.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/deleteColMoveEnd.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="55" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/deleteColMoveEnd.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/dot.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="56" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/dot.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/dot.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="57" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/dot.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/driver.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="58" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/driver.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/driver.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="59" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/driver.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/exp.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="60" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/exp.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/exp.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="61" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/exp.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/eye.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="62" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/eye.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/eye.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="63" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/eye.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/factorQR.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="64" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/factorQR.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/factorQR.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="65" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/factorQR.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/factoryConstruct.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="66" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/factoryConstruct.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/factoryConstruct.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="67" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/factoryConstruct.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/feasibleX0ForWorkingSet.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="68" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/feasibleX0ForWorkingSet.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/feasibleX0ForWorkingSet.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="69" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/feasibleX0ForWorkingSet.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/feasibleratiotest.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="70" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/feasibleratiotest.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/feasibleratiotest.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="71" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/feasibleratiotest.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/find.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="72" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/find.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/find.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="73" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/find.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/fullColLDL2_.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="74" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/fullColLDL2_.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/fullColLDL2_.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="75" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/fullColLDL2_.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/guidance_step.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="76" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/guidance_step.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/guidance_step.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="77" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/guidance_step.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/iterate.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="78" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/iterate.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/iterate.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="79" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/iterate.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/ixamax.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="80" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/ixamax.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/ixamax.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="81" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/ixamax.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/ixfun.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="82" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/ixfun.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/ixfun.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="83" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/ixfun.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/lesserNeighbor.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="84" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/lesserNeighbor.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/lesserNeighbor.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="85" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/lesserNeighbor.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/linearForm_.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="86" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/linearForm_.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/linearForm_.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="87" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/linearForm_.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/maxConstraintViolation.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="88" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/maxConstraintViolation.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/maxConstraintViolation.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="89" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/maxConstraintViolation.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/meshgrid.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="90" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/meshgrid.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/meshgrid.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="91" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/meshgrid.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/miSim.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="92" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/miSim.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/miSim.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="93" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/miSim.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/minOrMax.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="94" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/minOrMax.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/minOrMax.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="95" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/minOrMax.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/mpower.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="96" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/mpower.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/mpower.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="97" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/mpower.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/nchoosek.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="98" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/nchoosek.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/nchoosek.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="99" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/nchoosek.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/norm.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="100" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/norm.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/norm.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="101" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/norm.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/partition.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="102" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/partition.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/partition.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="103" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/partition.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/phaseone.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="104" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/phaseone.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/phaseone.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="105" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/phaseone.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/quadprog.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="106" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/quadprog.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/quadprog.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="107" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/quadprog.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/ratiotest.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="108" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/ratiotest.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/ratiotest.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="109" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/ratiotest.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/rectangularPrism.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="110" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/rectangularPrism.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/removeConstr.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="111" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/rectangularPrism.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/removeConstr.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="112" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/removeConstr.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/repmat.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="113" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/removeConstr.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/repmat.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
@@ -833,245 +838,221 @@
</Artifacts>
<Artifacts id="124" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/sensingObjective.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/sensingObjective.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="125" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/sensingObjective.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/sensorPerformance.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="126" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/sensorPerformance.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/sensorPerformance.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="127" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/sensorPerformance.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/setProblemType.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="128" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/setProblemType.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/setProblemType.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="129" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/setProblemType.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/sigmoidSensor.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="130" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/sigmoidSensor.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/sort.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="131" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/sigmoidSensor.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/sort.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="132" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/sort.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/spherical.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="133" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/sort.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/sprintf.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="134" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/spherical.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/sprintf.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="135" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/spherical.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/squareQ_appendCol.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="136" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/sprintf.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/squareQ_appendCol.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="137" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/sprintf.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/string1.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="138" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/squareQ_appendCol.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/sum.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="139" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/squareQ_appendCol.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/sum.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="140" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/string1.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/unique.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="141" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/string1.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/unique.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="142" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/sum.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/vecnorm.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="143" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/sum.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/vecnorm.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="144" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/unique.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/xgemv.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="145" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/unique.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/xgemv.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="146" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/vecnorm.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/xgeqp3.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="147" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/vecnorm.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/xgeqp3.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="148" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/xgemv.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/xnrm2.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="149" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/xgemv.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/xnrm2.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="150" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/xgeqp3.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/xrotg.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="151" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/xgeqp3.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/xrotg.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="152" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/xnrm2.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/xzgeqp3.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="153" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/xnrm2.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/xzgeqp3.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="154" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/xrotg.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/xzlarf.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="155" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/xrotg.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/xzlarf.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="156" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/xzgeqp3.cpp</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/xzlarfg.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="157" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/xzgeqp3.h</Path>
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/xzlarfg.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="158" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/xzlarf.cpp</Path>
<Path>/home/kdee/matlab/R2025a/extern/include/tmwtypes.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="159" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/xzlarf.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="160" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/xzlarfg.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="161" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/xzlarfg.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="162" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/matlab/R2025a/extern/include/tmwtypes.h</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="163" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/examples/main.cpp</Path>
</File>
<Type>GENERATED_SOURCE</Type>
</Artifacts>
<Artifacts id="164" type="coderapp.internal.build.mfz.CodegenArtifact">
<Artifacts id="160" type="coderapp.internal.build.mfz.CodegenArtifact">
<File type="coderapp.internal.util.mfz.FileSpec">
<Path>/home/kdee/Desktop/miSim/aerpaw/codegen/examples/main.h</Path>
</File>
@@ -1079,7 +1060,7 @@
</Artifacts>
<BuildFolder type="coderapp.internal.util.mfz.FileSpec"/>
<Success>true</Success>
<Timestamp>2026-02-25T11:42:50</Timestamp>
<Timestamp>2026-02-27T17:26:39</Timestamp>
</MainBuildResult>
</coderapp.internal.mlc.mfz.MatlabCoderProjectState>
</MF0>

View File

@@ -3,36 +3,55 @@ arguments (Input)
numClients (1, 1) int32;
end
coder.extrinsic('disp', 'loadTargetsFromYaml');
coder.extrinsic('disp', 'readScenarioCsv');
% Maximum clients and waypoints supported
% Maximum clients supported (one initial position per UAV)
MAX_CLIENTS = 4;
MAX_WAYPOINTS = 10;
MAX_TARGETS = MAX_CLIENTS * MAX_WAYPOINTS;
MAX_TARGETS = MAX_CLIENTS;
% Allocate targets array (MAX_TARGETS x 3)
targets = zeros(MAX_TARGETS, 3);
numWaypoints = int32(0);
totalLoaded = int32(0); % pre-declare type for coder.ceval %#ok<NASGU>
% Load targets from YAML config file
% Load initial UAV positions from scenario CSV
if coder.target('MATLAB')
disp('Loading targets from server.yaml (simulation)...');
targetsLoaded = loadTargetsFromYaml('aerpaw/config/server.yaml');
totalLoaded = size(targetsLoaded, 1);
targets(1:totalLoaded, :) = targetsLoaded(1:totalLoaded, :);
numWaypoints = int32(totalLoaded / numClients);
disp(['Loaded ', num2str(numWaypoints), ' waypoints per client']);
disp('Loading initial positions from scenario.csv (simulation)...');
tmpSim = miSim;
sc = tmpSim.readScenarioCsv('aerpaw/config/scenario.csv');
flatPos = double(sc.initialPositions); % 1×(3*N) flat vector
posMatrix = reshape(flatPos, 3, [])'; % N×3, same layout as initializeFromCsv
totalLoaded = int32(size(posMatrix, 1));
targets(1:totalLoaded, :) = posMatrix;
numWaypoints = int32(1);
disp(['Loaded ', num2str(double(totalLoaded)), ' initial positions']);
else
coder.cinclude('controller_impl.h');
% Define filename as null-terminated character array for C compatibility
filename = ['config/server.yaml', char(0)];
% loadTargets fills targets array (column-major for MATLAB compatibility)
totalLoaded = int32(0);
totalLoaded = coder.ceval('loadTargets', coder.ref(filename), ...
filename = ['config/scenario.csv', char(0)];
totalLoaded = coder.ceval('loadInitialPositions', coder.ref(filename), ...
coder.ref(targets), int32(MAX_TARGETS));
numWaypoints = totalLoaded / int32(numClients);
end
% Load guidance scenario from CSV (parameters for guidance_step)
NUM_SCENARIO_PARAMS = 23;
MAX_OBSTACLES_CTRL = int32(8);
scenarioParams = zeros(1, NUM_SCENARIO_PARAMS);
obstacleMin = zeros(MAX_OBSTACLES_CTRL, 3);
obstacleMax = zeros(MAX_OBSTACLES_CTRL, 3);
numObstacles = int32(0);
if ~coder.target('MATLAB')
coder.cinclude('controller_impl.h');
scenarioFilename = ['config/scenario.csv', char(0)];
coder.ceval('loadScenario', coder.ref(scenarioFilename), coder.ref(scenarioParams));
numObstacles = coder.ceval('loadObstacles', coder.ref(scenarioFilename), ...
coder.ref(obstacleMin), coder.ref(obstacleMax), ...
int32(MAX_OBSTACLES_CTRL));
end
% On MATLAB path, scenarioParams and obstacle arrays are left as zeros.
% guidance_step's MATLAB path loads parameters directly from scenario.csv
% via sim.initializeFromCsv and does not use these arrays.
% Initialize server
if coder.target('MATLAB')
disp('Initializing server (simulation)...');
@@ -105,8 +124,12 @@ positions = zeros(MAX_CLIENTS, 3);
if ~coder.target('MATLAB')
coder.ceval('sendRequestPositions', int32(numClients));
coder.ceval('recvPositions', int32(numClients), coder.ref(positions), int32(MAX_CLIENTS));
else
% Simulation: seed positions from CSV waypoints so agents don't start at origin
positions(1:totalLoaded, :) = targets(1:totalLoaded, :);
end
guidance_step(positions(1:numClients, :), true);
guidance_step(positions(1:numClients, :), true, ...
scenarioParams, obstacleMin, obstacleMax, numObstacles);
% Main guidance loop
for step = 1:MAX_GUIDANCE_STEPS
@@ -117,7 +140,8 @@ for step = 1:MAX_GUIDANCE_STEPS
end
% Run one guidance step: feed GPS positions in, get targets out
nextPositions = guidance_step(positions(1:numClients, :), false);
nextPositions = guidance_step(positions(1:numClients, :), false, ...
scenarioParams, obstacleMin, obstacleMax, numObstacles);
% Send target to each client (no ACK/READY expected in guidance mode)
for i = 1:numClients
@@ -129,6 +153,11 @@ for step = 1:MAX_GUIDANCE_STEPS
end
end
% Simulation: advance positions to guidance outputs for closed-loop feedback
if coder.target('MATLAB')
positions(1:numClients, :) = nextPositions(1:numClients, :);
end
% Wait for the guidance rate interval before the next iteration
if ~coder.target('MATLAB')
coder.ceval('sleepMs', int32(GUIDANCE_RATE_MS));

View File

@@ -1,67 +1,52 @@
function nextPositions = guidance_step(currentPositions, isInit)
function nextPositions = guidance_step(currentPositions, isInit, ...
scenarioParams, ...
obstacleMin, obstacleMax, numObstacles)
% guidance_step One step of the miSim sensing coverage guidance algorithm.
%
% Wraps the miSim gradient-ascent + CBF motion algorithm for AERPAW.
% Holds full simulation state in a persistent variable between calls.
%
% Usage (from controller.m):
% guidance_step(initPositions, true) % first call: initialise state
% nextPos = guidance_step(gpsPos, false) % subsequent calls: run one step
% guidance_step(initPositions, true, scenarioParams, obstacleMin, obstacleMax, numObstacles)
% nextPos = guidance_step(gpsPos, false, scenarioParams, obstacleMin, obstacleMax, numObstacles)
%
% Inputs:
% currentPositions (MAX_CLIENTS × 3) double ENU [east north up] metres
% isInit (1,1) logical true on first call only
% scenarioParams (1 × NUM_SCENARIO_PARAMS) double
% Flat array of guidance parameters (compiled path).
% On MATLAB path this is ignored; parameters are loaded
% from scenario.csv via initializeFromCsv instead.
% Index mapping (1-based):
% 1 timestep 9 collisionRadius
% 2 maxIter 10 comRange
% 3 minAlt 11 alphaDist
% 4 discretizationStep 12 betaDist
% 5 protectedRange 13 alphaTilt
% 6 initialStepSize 14 betaTilt
% 7 barrierGain 15-17 domainMin
% 8 barrierExponent 18-20 domainMax
% 21-22 objectivePos
% 23 sensorPerformanceMinimum
% obstacleMin (MAX_OBSTACLES × 3) double column-major obstacle corners (compiled path)
% obstacleMax (MAX_OBSTACLES × 3) double
% numObstacles (1,1) int32 actual obstacle count
%
% Output:
% nextPositions (MAX_CLIENTS × 3) double guidance targets, ENU metres
%
% Codegen notes:
% - Persistent variable 'sim' holds the miSim object between calls.
% - Plotting/video are disabled (makePlots=false, makeVideo=false) for
% deployment. The coder.target('MATLAB') guards in the miSim/agent
% class files must be in place before codegen will succeed.
% - objectiveFunctionWrapper returns a function handle which is not
% directly codegen-compatible; the MATLAB path uses it normally. The
% compiled path requires an equivalent C impl (see TODO below).
% - On MATLAB path isInit uses sim.initializeFromCsv (file I/O, not compiled).
% - On compiled path isInit uses scenarioParams + obstacle arrays directly.
% - Plotting/video are disabled (makePlots=false, makeVideo=false).
coder.extrinsic('disp', 'objectiveFunctionWrapper');
coder.extrinsic('disp', 'objectiveFunctionWrapper', 'initializeFromCsv');
% =========================================================================
% Tunable guidance parameters adjust here and recompile as needed.
% =========================================================================
MAX_CLIENTS = int32(4); % must match MAX_CLIENTS in controller.m
% Domain bounds in ENU metres [east, north, up]
DOMAIN_MIN = [ 0.0, 0.0, 25.0];
DOMAIN_MAX = [ 20.0, 20.0, 55.0];
MIN_ALT = 25.0; % hard altitude floor (m)
% Sensing objective: bivariate Gaussian centred at [east, north]
OBJECTIVE_GROUND_POS = [10.0, 10.0];
DISCRETIZATION_STEP = 0.1; % objective grid step (m) coarser = faster
PROTECTED_RANGE = 1.0; % objective centre must be >this from domain edge
% Agent safety geometry
COLLISION_RADIUS = 3.0; % spherical collision radius (m)
COMMS_RANGE = 60.0; % communications range (m)
% Gradient-ascent parameters
INITIAL_STEP_SIZE = 1; % step size at iteration 0 (decays to 0 at MAX_ITER)
MAX_ITER = 100; % guidance steps (sets decay rate)
% Sensor model (sigmoidSensor)
ALPHA_DIST = 60.0; % effective sensing distance (m) set beyond max domain slant range (~53 m)
BETA_DIST = 0.2; % distance sigmoid steepness gentle, tilt drives the coverage gradient
ALPHA_TILT = 10.0; % max useful tilt angle (degrees)
BETA_TILT = 1.0; % tilt sigmoid steepness
% Safety filter Control Barrier Function (CBF/QP)
BARRIER_GAIN = 100;
BARRIER_EXPONENT = 3;
% Simulation timestep (s) should match GUIDANCE_RATE_MS / 1000 in controller.m
TIMESTEP = 5.0;
% =========================================================================
% Path to scenario CSV used on MATLAB path only (not compiled)
SCENARIO_CSV = 'aerpaw/config/scenario.csv';
persistent sim;
if isempty(sim)
@@ -76,22 +61,42 @@ numAgents = int32(size(currentPositions, 1));
if isInit
if coder.target('MATLAB')
disp('[guidance_step] Initialising simulation...');
end
% MATLAB path: load all parameters and obstacles from scenario CSV.
% initializeFromCsv reads the file, builds domain/agents/obstacles,
% and calls sim.initialize internally.
sim = sim.initializeFromCsv(SCENARIO_CSV);
disp('[guidance_step] Initialisation complete.');
else
% ================================================================
% Compiled path: unpack scenarioParams array and obstacle arrays.
% ================================================================
TIMESTEP = scenarioParams(1);
MAX_ITER = int32(scenarioParams(2));
MIN_ALT = scenarioParams(3);
DISCRETIZATION_STEP = scenarioParams(4);
PROTECTED_RANGE = scenarioParams(5);
INITIAL_STEP_SIZE = scenarioParams(6);
BARRIER_GAIN = scenarioParams(7);
BARRIER_EXPONENT = scenarioParams(8);
COLLISION_RADIUS = scenarioParams(9);
COMMS_RANGE = scenarioParams(10);
ALPHA_DIST = scenarioParams(11);
BETA_DIST = scenarioParams(12);
ALPHA_TILT = scenarioParams(13);
BETA_TILT = scenarioParams(14);
DOMAIN_MIN = scenarioParams(15:17);
DOMAIN_MAX = scenarioParams(18:20);
OBJECTIVE_GROUND_POS = scenarioParams(21:22);
SENSOR_PERFORMANCE_MINIMUM = scenarioParams(23);
% --- Build domain geometry ---
dom = rectangularPrism;
dom = dom.initialize([DOMAIN_MIN; DOMAIN_MAX], REGION_TYPE.DOMAIN, "Guidance Domain");
% --- Build sensing objective ---
% --- Build sensing objective (inline Gaussian; codegen-compatible) ---
dom.objective = sensingObjective;
if coder.target('MATLAB')
% objectiveFunctionWrapper returns a function handle MATLAB only.
objFcn = objectiveFunctionWrapper(OBJECTIVE_GROUND_POS, 3*eye(2));
dom.objective = dom.objective.initialize(objFcn, dom, ...
DISCRETIZATION_STEP, PROTECTED_RANGE);
else
% Evaluate bivariate Gaussian inline (codegen-compatible; no function handle).
% Must build the same grid that initializeWithValues uses internally.
xGrid = unique([DOMAIN_MIN(1):DISCRETIZATION_STEP:DOMAIN_MAX(1), DOMAIN_MAX(1)]);
yGrid = unique([DOMAIN_MIN(2):DISCRETIZATION_STEP:DOMAIN_MAX(2), DOMAIN_MAX(2)]);
[gridX, gridY] = meshgrid(xGrid, yGrid);
@@ -99,8 +104,7 @@ if isInit
dy = gridY - OBJECTIVE_GROUND_POS(2);
objValues = exp(-0.5 * (dx .* dx + dy .* dy));
dom.objective = dom.objective.initializeWithValues(objValues, dom, ...
DISCRETIZATION_STEP, PROTECTED_RANGE);
end
DISCRETIZATION_STEP, PROTECTED_RANGE, SENSOR_PERFORMANCE_MINIMUM);
% --- Build shared sensor model ---
sensor = sigmoidSensor;
@@ -119,13 +123,20 @@ if isInit
agentList{ii} = ag;
end
% --- Build obstacle list from flat arrays ---
coder.varsize('obstacleList', [8, 1], [1, 0]);
obstacleList = cell(int32(0), 1);
for ii = 1:numObstacles
obs = rectangularPrism;
obs = obs.initialize([obstacleMin(ii, :); obstacleMax(ii, :)], ...
REGION_TYPE.OBSTACLE, sprintf("Obstacle %d", ii));
obstacleList{ii} = obs;
end
% --- Initialise simulation (plots and video disabled) ---
sim = miSim;
sim = sim.initialize(dom, agentList, BARRIER_GAIN, BARRIER_EXPONENT, ...
MIN_ALT, TIMESTEP, MAX_ITER, cell(0, 1), false, false);
if coder.target('MATLAB')
disp('[guidance_step] Initialisation complete.');
MIN_ALT, TIMESTEP, MAX_ITER, obstacleList, false, false);
end
% On the init call return current positions unchanged

View File

@@ -113,6 +113,255 @@ int loadTargets(const char* filename, double* targets, int maxClients) {
return count;
}
// ---------------------------------------------------------------------------
// Scenario CSV loading
// ---------------------------------------------------------------------------
// Split a CSV data row into fields, respecting quoted commas.
// Inserts NUL terminators into `line` in place.
// Returns the number of fields found.
static int splitCSVRow(char* line, char** fields, int maxFields) {
int n = 0;
bool inQuote = false;
if (n < maxFields) fields[n++] = line;
for (char* p = line; *p && *p != '\n' && *p != '\r'; ++p) {
if (*p == '"') {
inQuote = !inQuote;
} else if (*p == ',' && !inQuote && n < maxFields) {
*p = '\0';
fields[n++] = p + 1;
}
}
// NUL-terminate the last field (strip trailing newline)
for (char* p = fields[n - 1]; *p; ++p) {
if (*p == '\n' || *p == '\r') { *p = '\0'; break; }
}
return n;
}
// Trim leading/trailing ASCII whitespace and remove enclosing double-quotes.
// Modifies the string in place and returns the start of the trimmed content.
static char* trimField(char* s) {
// Trim leading whitespace
while (*s == ' ' || *s == '\t') ++s;
// Remove enclosing quotes
size_t len = strlen(s);
if (len >= 2 && s[0] == '"' && s[len - 1] == '"') {
s[len - 1] = '\0';
++s;
}
// Trim trailing whitespace
char* end = s + strlen(s) - 1;
while (end > s && (*end == ' ' || *end == '\t')) { *end-- = '\0'; }
return s;
}
// Open scenario.csv, skip the header row, return the data row in `line`.
// Returns 1 on success, 0 on failure.
static int readScenarioDataRow(const char* filename, char* line, int lineSize) {
FILE* f = fopen(filename, "r");
if (!f) {
std::cerr << "loadScenario: cannot open " << filename << "\n";
return 0;
}
// Skip header row
if (!fgets(line, lineSize, f)) { fclose(f); return 0; }
// Read data row
int ok = (fgets(line, lineSize, f) != NULL);
fclose(f);
return ok ? 1 : 0;
}
// Load guidance parameters from scenario.csv into flat params[NUM_SCENARIO_PARAMS].
// Index mapping (0-based):
// 0-13 : timestep, maxIter, minAlt, discretizationStep, protectedRange,
// initialStepSize, barrierGain, barrierExponent, collisionRadius,
// comRange, alphaDist, betaDist, alphaTilt, betaTilt
// 14-16: domainMin (east, north, up)
// 17-19: domainMax (east, north, up)
// 20-21: objectivePos (east, north)
// Returns 1 on success, 0 on failure.
int loadScenario(const char* filename, double* params) {
char line[4096];
if (!readScenarioDataRow(filename, line, sizeof(line))) return 0;
char copy[4096];
strncpy(copy, line, sizeof(copy) - 1);
copy[sizeof(copy) - 1] = '\0';
char* fields[32];
int nf = splitCSVRow(copy, fields, 32);
if (nf < 21) {
fprintf(stderr, "loadScenario: expected >=21 columns, got %d\n", nf);
return 0;
}
// Scalar fields (columns 013)
for (int i = 0; i < 14; i++) {
params[i] = atof(trimField(fields[i]));
}
// domainMin: column 14, format "east, north, up"
{
char tmp[256]; strncpy(tmp, fields[14], sizeof(tmp) - 1); tmp[sizeof(tmp)-1] = '\0';
char* t = trimField(tmp);
if (sscanf(t, "%lf , %lf , %lf", &params[14], &params[15], &params[16]) != 3) {
fprintf(stderr, "loadScenario: failed to parse domainMin: %s\n", t);
return 0;
}
}
// domainMax: column 15
{
char tmp[256]; strncpy(tmp, fields[15], sizeof(tmp) - 1); tmp[sizeof(tmp)-1] = '\0';
char* t = trimField(tmp);
if (sscanf(t, "%lf , %lf , %lf", &params[17], &params[18], &params[19]) != 3) {
fprintf(stderr, "loadScenario: failed to parse domainMax: %s\n", t);
return 0;
}
}
// objectivePos: column 16
{
char tmp[256]; strncpy(tmp, fields[16], sizeof(tmp) - 1); tmp[sizeof(tmp)-1] = '\0';
char* t = trimField(tmp);
if (sscanf(t, "%lf , %lf", &params[20], &params[21]) != 2) {
fprintf(stderr, "loadScenario: failed to parse objectivePos: %s\n", t);
return 0;
}
}
// sensorPerformanceMinimum: column 17
{
char tmp[64]; strncpy(tmp, fields[17], sizeof(tmp) - 1); tmp[sizeof(tmp)-1] = '\0';
params[22] = atof(trimField(tmp));
}
printf("Loaded scenario: domain [%g,%g,%g] to [%g,%g,%g]\n",
params[14], params[15], params[16], params[17], params[18], params[19]);
return 1;
}
// Load initial UAV positions from scenario.csv (column 17: initialPositions).
// targets is a column-major [maxClients x 3] array (same layout as loadTargets):
// targets[i + 0*maxClients] = east
// targets[i + 1*maxClients] = north
// targets[i + 2*maxClients] = up
// Returns number of positions loaded.
int loadInitialPositions(const char* filename, double* targets, int maxClients) {
char line[4096];
if (!readScenarioDataRow(filename, line, sizeof(line))) return 0;
char copy[4096];
strncpy(copy, line, sizeof(copy) - 1);
copy[sizeof(copy) - 1] = '\0';
char* fields[32];
int nf = splitCSVRow(copy, fields, 32);
if (nf < 19) {
fprintf(stderr, "loadInitialPositions: expected >=19 columns, got %d\n", nf);
return 0;
}
// Column 18: initialPositions flat "x1,y1,z1, x2,y2,z2, ..."
char tmp[1024]; strncpy(tmp, fields[18], sizeof(tmp) - 1); tmp[sizeof(tmp)-1] = '\0';
char* t = trimField(tmp);
double vals[3 * 4]; // up to MAX_CLIENTS triples
int parsed = 0;
char* tok = strtok(t, ",");
while (tok && parsed < 3 * maxClients) {
vals[parsed++] = atof(tok);
tok = strtok(nullptr, ",");
}
int count = parsed / 3;
for (int i = 0; i < count; i++) {
targets[i + 0 * maxClients] = vals[i * 3 + 0]; // east
targets[i + 1 * maxClients] = vals[i * 3 + 1]; // north
targets[i + 2 * maxClients] = vals[i * 3 + 2]; // up
}
printf("Loaded %d initial position(s) from scenario\n", count);
return count;
}
// Load obstacle bounding-box corners from scenario.csv.
// Columns used: 18 (numObstacles), 19 (obstacleMin flat), 20 (obstacleMax flat).
// obstacleMin and obstacleMax are column-major [maxObstacles x 3] arrays:
// obstacleMin[obs + 0*maxObstacles] = east_min
// obstacleMin[obs + 1*maxObstacles] = north_min
// obstacleMin[obs + 2*maxObstacles] = up_min
// Returns number of obstacles loaded (0 if none or on error).
int loadObstacles(const char* filename, double* obstacleMin, double* obstacleMax,
int maxObstacles) {
char line[4096];
if (!readScenarioDataRow(filename, line, sizeof(line))) return 0;
char copy[4096];
strncpy(copy, line, sizeof(copy) - 1);
copy[sizeof(copy) - 1] = '\0';
char* fields[32];
int nf = splitCSVRow(copy, fields, 32);
if (nf < 22) return 0;
// Column 19: numObstacles
int n = (int)atof(trimField(fields[19]));
if (n <= 0) return 0;
if (n > maxObstacles) {
fprintf(stderr, "loadObstacles: %d obstacles exceeds MAX_OBSTACLES=%d\n", n, maxObstacles);
n = maxObstacles;
}
// Column 20: obstacleMin flat "x0,y0,z0, x1,y1,z1, ..."
{
char tmp[1024]; strncpy(tmp, fields[20], sizeof(tmp) - 1); tmp[sizeof(tmp)-1] = '\0';
char* t = trimField(tmp);
double vals[3 * 8]; // up to MAX_OBSTACLES triples
int parsed = 0;
char* tok = strtok(t, ",");
while (tok && parsed < 3 * n) {
vals[parsed++] = atof(tok);
tok = strtok(nullptr, ",");
}
if (parsed < 3 * n) {
fprintf(stderr, "loadObstacles: obstacleMin has fewer values than expected\n");
return 0;
}
for (int obs = 0; obs < n; obs++) {
obstacleMin[obs + 0 * maxObstacles] = vals[obs * 3 + 0]; // east
obstacleMin[obs + 1 * maxObstacles] = vals[obs * 3 + 1]; // north
obstacleMin[obs + 2 * maxObstacles] = vals[obs * 3 + 2]; // up
}
}
// Column 21: obstacleMax flat
{
char tmp[1024]; strncpy(tmp, fields[21], sizeof(tmp) - 1); tmp[sizeof(tmp)-1] = '\0';
char* t = trimField(tmp);
double vals[3 * 8];
int parsed = 0;
char* tok = strtok(t, ",");
while (tok && parsed < 3 * n) {
vals[parsed++] = atof(tok);
tok = strtok(nullptr, ",");
}
if (parsed < 3 * n) {
fprintf(stderr, "loadObstacles: obstacleMax has fewer values than expected\n");
return 0;
}
for (int obs = 0; obs < n; obs++) {
obstacleMax[obs + 0 * maxObstacles] = vals[obs * 3 + 0];
obstacleMax[obs + 1 * maxObstacles] = vals[obs * 3 + 1];
obstacleMax[obs + 2 * maxObstacles] = vals[obs * 3 + 2];
}
}
printf("Loaded %d obstacle(s) from scenario\n", n);
return n;
}
// Message type names for logging
static const char* messageTypeName(uint8_t msgType) {
switch (msgType) {

View File

@@ -15,6 +15,31 @@ void closeServer();
// Configuration
int loadTargets(const char* filename, double* targets, int maxClients);
// Scenario loading (scenario.csv)
// Number of elements in the flat params array passed to guidance_step.
// Indices: 0-13 scalars, 14-16 domainMin, 17-19 domainMax, 20-21 objectivePos.
#define NUM_SCENARIO_PARAMS 23
// Maximum number of obstacles (upper bound for pre-allocated arrays).
#define MAX_OBSTACLES 8
// Load guidance parameters from scenario.csv into flat params[NUM_SCENARIO_PARAMS].
// Returns 1 on success, 0 on failure.
int loadScenario(const char* filename, double* params);
// Load initial UAV positions from scenario.csv (initialPositions column).
// targets is a column-major [maxClients x 3] array (same layout as loadTargets).
// Returns number of positions loaded.
int loadInitialPositions(const char* filename, double* targets, int maxClients);
// Load obstacle bounding-box corners from scenario.csv.
// obstacleMin and obstacleMax are column-major [maxObstacles x 3] arrays
// (same layout convention as loadTargets / recvPositions).
// Returns the number of obstacles loaded.
int loadObstacles(const char* filename,
double* obstacleMin,
double* obstacleMax,
int maxObstacles);
// User interaction
void waitForUserInput();

View File

@@ -6,9 +6,9 @@ c = ["r", "g", "b", "m", "c", "y", "k"]; % plotting colors
seaToGroundLevel = 110; % meters, measured approximately from USGS national map viewer
% Paths to logs
gpsCsvs = fullfile ("sandbox", "test1", ...
["GPS_DATA_0c8d904aa159_2026-02-24_21:33:25.csv"; ...
"GPS_DATA_8e4f52dac04d_2026-02-24_21:33:25.csv"; ...
gpsCsvs = fullfile ("sandbox", "test2", ...
["GPS_DATA_0c8d904aa159_2026-02-27_20:52:33.csv"; ...
"GPS_DATA_8e4f52dac04d_2026-02-27_20:52:33.csv"; ...
]);
G = cell(size(gpsCsvs));

View File

@@ -1,2 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="server.yaml" type="File"/>

View File

@@ -0,0 +1,2 @@
<?xml version="1.0" encoding="UTF-8"?>
<Info location="scenario.csv" type="File"/>

View File

@@ -27,6 +27,43 @@ classdef parametricTestSuite < matlab.unittest.TestCase
methods (Test)
% Test cases
function test_scenario(tc)
% Load scenario definition
tc.csvPath = fullfile(matlab.project.rootProject().RootFolder, "aerpaw", "config", "scenario.csv");
params = tc.testClass.readScenarioCsv(tc.csvPath);
% Define scenario according to CSV specification
tc.domain = tc.domain.initialize([params.domainMin; params.domainMax], REGION_TYPE.DOMAIN, "Domain");
tc.domain.objective = tc.domain.objective.initialize(objectiveFunctionWrapper(params.objectivePos), tc.domain, params.discretizationStep, params.protectedRange, params.sensorPerformanceMinimum);
agents = cell(size(params.initialPositions, 2) / 3, 1);
for ii = 1:size(agents, 1)
agents{ii} = agent;
sensorModel = sigmoidSensor;
sensorModel = sensorModel.initialize(params.alphaDist, params.betaDist, params.alphaTilt, params.betaTilt);
collisionGeometry = spherical;
collisionGeometry = collisionGeometry.initialize(params.initialPositions((((ii - 1) * 3) + 1):(ii * 3)), params.collisionRadius, REGION_TYPE.COLLISION, sprintf("Agent %d collision geometry", ii));
agents{ii} = agents{ii}.initialize(params.initialPositions((((ii - 1) * 3) + 1):(ii * 3)), collisionGeometry, sensorModel, params.comRange, params.maxIter, params.initialStepSize, sprintf("Agent %d", ii), tc.plotCommsGeometry);
end
% TODO
obstacles = {};
% Set up simulation
tc.testClass = tc.testClass.initialize(tc.domain, agents, params.barrierGain, params.barrierExponent, params.minAlt, params.timestep, params.maxIter, obstacles, tc.makePlots, tc.makeVideo);
% Save simulation parameters to output file
tc.testClass.writeInits();
% Run
tc.testClass = tc.testClass.run();
% Cleanup
tc.testClass = tc.testClass.teardown();
end
function csv_parametric_tests_random_agents(tc)
% Read in parameters to iterate over
params = tc.testClass.readScenarioCsv(tc.csvPath);