130 lines
5.8 KiB
Matlab
130 lines
5.8 KiB
Matlab
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 (per-UAV), comRange (per-UAV),
|
||
% alphaDist (per-UAV), betaDist (per-UAV),
|
||
% alphaTilt (per-UAV), betaTilt (per-UAV),
|
||
% domainMin ("x,y,z"), domainMax ("x,y,z"), objectivePos ("x,y"),
|
||
% objectiveVar ("v11,v12,v21,v22"), sensorPerformanceMinimum,
|
||
% 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;
|
||
end
|
||
arguments (Output)
|
||
obj (1, 1) {mustBeA(obj, 'miSim')};
|
||
end
|
||
|
||
% ---- 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;
|
||
% Per-UAV parameters (vectors with one element per UAV)
|
||
COLLISION_RADIUS_VEC = scenario.collisionRadius; % 1×N
|
||
COMMS_RANGE_VEC = scenario.comRange; % 1×N
|
||
ALPHA_DIST_VEC = scenario.alphaDist; % 1×N
|
||
BETA_DIST_VEC = scenario.betaDist; % 1×N
|
||
ALPHA_TILT_VEC = scenario.alphaTilt; % 1×N
|
||
BETA_TILT_VEC = scenario.betaTilt; % 1×N
|
||
|
||
DOMAIN_MIN = scenario.domainMin; % 1×3
|
||
DOMAIN_MAX = scenario.domainMax; % 1×3
|
||
OBJECTIVE_GROUND_POS = scenario.objectivePos; % 1×2
|
||
OBJECTIVE_VAR = reshape(scenario.objectiveVar, 2, 2); % 2×2 covariance matrix
|
||
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);
|
||
|
||
% Validate per-UAV parameter lengths match numAgents
|
||
assert(numel(COLLISION_RADIUS_VEC) == numAgents, ...
|
||
"collisionRadius has %d values but expected %d (one per UAV)", numel(COLLISION_RADIUS_VEC), numAgents);
|
||
assert(numel(COMMS_RANGE_VEC) == numAgents, ...
|
||
"comRange has %d values but expected %d (one per UAV)", numel(COMMS_RANGE_VEC), numAgents);
|
||
assert(numel(ALPHA_DIST_VEC) == numAgents, ...
|
||
"alphaDist has %d values but expected %d (one per UAV)", numel(ALPHA_DIST_VEC), numAgents);
|
||
assert(numel(BETA_DIST_VEC) == numAgents, ...
|
||
"betaDist has %d values but expected %d (one per UAV)", numel(BETA_DIST_VEC), numAgents);
|
||
assert(numel(ALPHA_TILT_VEC) == numAgents, ...
|
||
"alphaTilt has %d values but expected %d (one per UAV)", numel(ALPHA_TILT_VEC), numAgents);
|
||
assert(numel(BETA_TILT_VEC) == numAgents, ...
|
||
"betaTilt has %d values but expected %d (one per UAV)", numel(BETA_TILT_VEC), numAgents);
|
||
|
||
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, OBJECTIVE_VAR);
|
||
dom.objective = dom.objective.initialize(objFcn, dom, DISCRETIZATION_STEP, PROTECTED_RANGE, SENSOR_PERFORMANCE_MINIMUM);
|
||
|
||
% ---- Initialise agents from scenario positions ---------------------------
|
||
% Each agent gets its own sensor model and collision/comms radii from the
|
||
% per-UAV parameter vectors.
|
||
agentList = cell(numAgents, 1);
|
||
for ii = 1:numAgents
|
||
pos = positions(ii, :);
|
||
|
||
% Per-UAV sensor model
|
||
sensor = sigmoidSensor;
|
||
sensor = sensor.initialize(ALPHA_DIST_VEC(ii), BETA_DIST_VEC(ii), ...
|
||
ALPHA_TILT_VEC(ii), BETA_TILT_VEC(ii));
|
||
|
||
geom = spherical;
|
||
geom = geom.initialize(pos, COLLISION_RADIUS_VEC(ii), REGION_TYPE.COLLISION, ...
|
||
sprintf("UAV %d Collision", ii));
|
||
ag = agent;
|
||
ag = ag.initialize(pos, geom, sensor, COMMS_RANGE_VEC(ii), 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
|