scenario edits
This commit is contained in:
@@ -109,8 +109,8 @@ function [obj] = constrainMotion(obj)
|
|||||||
b(kk) = obj.barrierGain * max(0, h_yMax)^obj.barrierExponent;
|
b(kk) = obj.barrierGain * max(0, h_yMax)^obj.barrierExponent;
|
||||||
kk = kk + 1;
|
kk = kk + 1;
|
||||||
|
|
||||||
% Z minimum
|
% Z minimum — enforce z >= minAlt + radius (not just z >= domain floor + radius)
|
||||||
h_zMin = (obj.agents{ii}.pos(3) - obj.domain.minCorner(3)) - obj.agents{ii}.collisionGeometry.radius;
|
h_zMin = (obj.agents{ii}.pos(3) - obj.minAlt) - obj.agents{ii}.collisionGeometry.radius;
|
||||||
A(kk, (3 * ii - 2):(3 * ii)) = [0, 0, -1];
|
A(kk, (3 * ii - 2):(3 * ii)) = [0, 0, -1];
|
||||||
b(kk) = obj.barrierGain * max(0, h_zMin)^obj.barrierExponent;
|
b(kk) = obj.barrierGain * max(0, h_zMin)^obj.barrierExponent;
|
||||||
kk = kk + 1;
|
kk = kk + 1;
|
||||||
|
|||||||
@@ -84,6 +84,7 @@ function [obj] = initialize(obj, domain, agents, barrierGain, barrierExponent, m
|
|||||||
% Set CBF parameters
|
% Set CBF parameters
|
||||||
obj.barrierGain = barrierGain;
|
obj.barrierGain = barrierGain;
|
||||||
obj.barrierExponent = barrierExponent;
|
obj.barrierExponent = barrierExponent;
|
||||||
|
obj.minAlt = minAlt;
|
||||||
|
|
||||||
% Compute adjacency matrix and lesser neighbors
|
% Compute adjacency matrix and lesser neighbors
|
||||||
obj = obj.updateAdjacency();
|
obj = obj.updateAdjacency();
|
||||||
|
|||||||
@@ -49,6 +49,7 @@ BETA_TILT = scenario.betaTilt;
|
|||||||
DOMAIN_MIN = scenario.domainMin; % 1×3
|
DOMAIN_MIN = scenario.domainMin; % 1×3
|
||||||
DOMAIN_MAX = scenario.domainMax; % 1×3
|
DOMAIN_MAX = scenario.domainMax; % 1×3
|
||||||
OBJECTIVE_GROUND_POS = scenario.objectivePos; % 1×2
|
OBJECTIVE_GROUND_POS = scenario.objectivePos; % 1×2
|
||||||
|
OBJECTIVE_VAR = reshape(scenario.objectiveVar, 2, 2); % 2×2 covariance matrix
|
||||||
SENSOR_PERFORMANCE_MINIMUM = scenario.sensorPerformanceMinimum; % scalar
|
SENSOR_PERFORMANCE_MINIMUM = scenario.sensorPerformanceMinimum; % scalar
|
||||||
|
|
||||||
% Initial UAV positions: flat vector reshaped to N×3
|
% Initial UAV positions: flat vector reshaped to N×3
|
||||||
@@ -66,7 +67,7 @@ dom = dom.initialize([DOMAIN_MIN; DOMAIN_MAX], REGION_TYPE.DOMAIN, "Guidance Dom
|
|||||||
|
|
||||||
% ---- Build sensing objective (MATLAB path: objectiveFunctionWrapper) -----
|
% ---- Build sensing objective (MATLAB path: objectiveFunctionWrapper) -----
|
||||||
dom.objective = sensingObjective;
|
dom.objective = sensingObjective;
|
||||||
objFcn = objectiveFunctionWrapper(OBJECTIVE_GROUND_POS, 3 * eye(2));
|
objFcn = objectiveFunctionWrapper(OBJECTIVE_GROUND_POS, OBJECTIVE_VAR);
|
||||||
dom.objective = dom.objective.initialize(objFcn, dom, DISCRETIZATION_STEP, PROTECTED_RANGE, SENSOR_PERFORMANCE_MINIMUM);
|
dom.objective = dom.objective.initialize(objFcn, dom, DISCRETIZATION_STEP, PROTECTED_RANGE, SENSOR_PERFORMANCE_MINIMUM);
|
||||||
|
|
||||||
% ---- Build shared sensor model -------------------------------------------
|
% ---- Build shared sensor model -------------------------------------------
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ classdef miSim
|
|||||||
performance = 0; % simulation performance timeseries vector
|
performance = 0; % simulation performance timeseries vector
|
||||||
barrierGain = NaN; % CBF gain parameter
|
barrierGain = NaN; % CBF gain parameter
|
||||||
barrierExponent = NaN; % CBF exponent parameter
|
barrierExponent = NaN; % CBF exponent parameter
|
||||||
|
minAlt = 0; % minimum allowable altitude (m)
|
||||||
artifactName = "";
|
artifactName = "";
|
||||||
fPerf; % performance plot figure
|
fPerf; % performance plot figure
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -20,8 +20,8 @@ function validate(obj)
|
|||||||
for kk = 1:size(obj.agents, 1)
|
for kk = 1:size(obj.agents, 1)
|
||||||
P = min(max(obj.agents{kk}.pos, obj.obstacles{jj}.minCorner), obj.obstacles{jj}.maxCorner);
|
P = min(max(obj.agents{kk}.pos, obj.obstacles{jj}.minCorner), obj.obstacles{jj}.maxCorner);
|
||||||
d = obj.agents{kk}.pos - P;
|
d = obj.agents{kk}.pos - P;
|
||||||
if dot(d, d) <= obj.agents{kk}.collisionGeometry.radius^2
|
if dot(d, d) < obj.agents{kk}.collisionGeometry.radius^2
|
||||||
error("%s colliding with %s", obj.agents{kk}.label, obj.obstacles{jj}.label); % this will cause quadprog to fail
|
warning("%s colliding with %s by %d", obj.agents{kk}.label, obj.obstacles{jj}.label, dot(d, d) - obj.agents{kk}.collisionGeometry.radius^2); % this will cause quadprog to fail
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,2 +1,2 @@
|
|||||||
timestep, maxIter, minAlt, discretizationStep, protectedRange, initialStepSize, barrierGain, barrierExponent, collisionRadius, comRange, alphaDist, betaDist, alphaTilt, betaTilt, domainMin, domainMax, objectivePos, sensorPerformanceMinimum, initialPositions, numObstacles, obstacleMin, obstacleMax
|
timestep, maxIter, minAlt, discretizationStep, protectedRange, initialStepSize, barrierGain, barrierExponent, collisionRadius, comRange, alphaDist, betaDist, alphaTilt, betaTilt, domainMin, domainMax, objectivePos, objectiveVar, sensorPerformanceMinimum, initialPositions, numObstacles, obstacleMin, obstacleMax
|
||||||
5, 100, 30.0, 0.1, 1.0, 2.0, 100, 3, 3.0, 30.0, 60.0, 0.2, 10.0, 1.0, "0.0, 0.0, 0.0", "50.0, 50.0, 50.0", "35.0, 35.0", 1e-6, "5.0, 10.0, 45.0, 15.0, 10.0, 35.0", 0, "", ""
|
5, 100, 30.0, 0.1, 1.0, 2.0, 100, 3, 3.0, 30.0, 80.0, 0.25, 5.0, 0.1, "0.0, 0.0, 0.0", "50.0, 50.0, 80.0", "35.0, 35.0", "10, 5, 5, 10", 2e-1, "5.0, 10.0, 45.0, 15.0, 10.0, 35.0", 0, "", ""
|
||||||
|
@@ -34,7 +34,7 @@ else
|
|||||||
end
|
end
|
||||||
|
|
||||||
% Load guidance scenario from CSV (parameters for guidance_step)
|
% Load guidance scenario from CSV (parameters for guidance_step)
|
||||||
NUM_SCENARIO_PARAMS = 23;
|
NUM_SCENARIO_PARAMS = 27;
|
||||||
MAX_OBSTACLES_CTRL = int32(8);
|
MAX_OBSTACLES_CTRL = int32(8);
|
||||||
scenarioParams = zeros(1, NUM_SCENARIO_PARAMS);
|
scenarioParams = zeros(1, NUM_SCENARIO_PARAMS);
|
||||||
obstacleMin = zeros(MAX_OBSTACLES_CTRL, 3);
|
obstacleMin = zeros(MAX_OBSTACLES_CTRL, 3);
|
||||||
|
|||||||
@@ -27,7 +27,8 @@ function nextPositions = guidance_step(currentPositions, isInit, ...
|
|||||||
% 7 barrierGain 15-17 domainMin
|
% 7 barrierGain 15-17 domainMin
|
||||||
% 8 barrierExponent 18-20 domainMax
|
% 8 barrierExponent 18-20 domainMax
|
||||||
% 21-22 objectivePos
|
% 21-22 objectivePos
|
||||||
% 23 sensorPerformanceMinimum
|
% 23-26 objectiveVar (2x2, col-major)
|
||||||
|
% 27 sensorPerformanceMinimum
|
||||||
% obstacleMin (MAX_OBSTACLES × 3) double column-major obstacle corners (compiled path)
|
% obstacleMin (MAX_OBSTACLES × 3) double column-major obstacle corners (compiled path)
|
||||||
% obstacleMax (MAX_OBSTACLES × 3) double
|
% obstacleMax (MAX_OBSTACLES × 3) double
|
||||||
% numObstacles (1,1) int32 actual obstacle count
|
% numObstacles (1,1) int32 actual obstacle count
|
||||||
@@ -89,7 +90,8 @@ if isInit
|
|||||||
DOMAIN_MIN = scenarioParams(15:17);
|
DOMAIN_MIN = scenarioParams(15:17);
|
||||||
DOMAIN_MAX = scenarioParams(18:20);
|
DOMAIN_MAX = scenarioParams(18:20);
|
||||||
OBJECTIVE_GROUND_POS = scenarioParams(21:22);
|
OBJECTIVE_GROUND_POS = scenarioParams(21:22);
|
||||||
SENSOR_PERFORMANCE_MINIMUM = scenarioParams(23);
|
OBJECTIVE_VAR = reshape(scenarioParams(23:26), 2, 2);
|
||||||
|
SENSOR_PERFORMANCE_MINIMUM = scenarioParams(27);
|
||||||
|
|
||||||
% --- Build domain geometry ---
|
% --- Build domain geometry ---
|
||||||
dom = rectangularPrism;
|
dom = rectangularPrism;
|
||||||
@@ -102,7 +104,11 @@ if isInit
|
|||||||
[gridX, gridY] = meshgrid(xGrid, yGrid);
|
[gridX, gridY] = meshgrid(xGrid, yGrid);
|
||||||
dx = gridX - OBJECTIVE_GROUND_POS(1);
|
dx = gridX - OBJECTIVE_GROUND_POS(1);
|
||||||
dy = gridY - OBJECTIVE_GROUND_POS(2);
|
dy = gridY - OBJECTIVE_GROUND_POS(2);
|
||||||
objValues = exp(-0.5 * (dx .* dx + dy .* dy));
|
% Bivariate Gaussian using objectiveVar covariance matrix (avoids inv())
|
||||||
|
ov_a = OBJECTIVE_VAR(1,1); ov_b = OBJECTIVE_VAR(1,2);
|
||||||
|
ov_c = OBJECTIVE_VAR(2,1); ov_d = OBJECTIVE_VAR(2,2);
|
||||||
|
ov_det = ov_a * ov_d - ov_b * ov_c;
|
||||||
|
objValues = exp((-0.5 / ov_det) .* (ov_d .* dx.*dx - (ov_b + ov_c) .* dx.*dy + ov_a .* dy.*dy));
|
||||||
dom.objective = dom.objective.initializeWithValues(objValues, dom, ...
|
dom.objective = dom.objective.initializeWithValues(objValues, dom, ...
|
||||||
DISCRETIZATION_STEP, PROTECTED_RANGE, SENSOR_PERFORMANCE_MINIMUM);
|
DISCRETIZATION_STEP, PROTECTED_RANGE, SENSOR_PERFORMANCE_MINIMUM);
|
||||||
|
|
||||||
|
|||||||
@@ -180,6 +180,8 @@ static int readScenarioDataRow(const char* filename, char* line, int lineSize) {
|
|||||||
// 14-16: domainMin (east, north, up)
|
// 14-16: domainMin (east, north, up)
|
||||||
// 17-19: domainMax (east, north, up)
|
// 17-19: domainMax (east, north, up)
|
||||||
// 20-21: objectivePos (east, north)
|
// 20-21: objectivePos (east, north)
|
||||||
|
// 22-25: objectiveVar (2x2 col-major: v11, v12, v21, v22)
|
||||||
|
// 26 : sensorPerformanceMinimum
|
||||||
// Returns 1 on success, 0 on failure.
|
// Returns 1 on success, 0 on failure.
|
||||||
int loadScenario(const char* filename, double* params) {
|
int loadScenario(const char* filename, double* params) {
|
||||||
char line[4096];
|
char line[4096];
|
||||||
@@ -191,8 +193,8 @@ int loadScenario(const char* filename, double* params) {
|
|||||||
|
|
||||||
char* fields[32];
|
char* fields[32];
|
||||||
int nf = splitCSVRow(copy, fields, 32);
|
int nf = splitCSVRow(copy, fields, 32);
|
||||||
if (nf < 21) {
|
if (nf < 19) {
|
||||||
fprintf(stderr, "loadScenario: expected >=21 columns, got %d\n", nf);
|
fprintf(stderr, "loadScenario: expected >=19 columns, got %d\n", nf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -231,10 +233,20 @@ int loadScenario(const char* filename, double* params) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// sensorPerformanceMinimum: column 17
|
// objectiveVar: column 17, format "v11, v12, v21, v22"
|
||||||
{
|
{
|
||||||
char tmp[64]; strncpy(tmp, fields[17], sizeof(tmp) - 1); tmp[sizeof(tmp)-1] = '\0';
|
char tmp[256]; strncpy(tmp, fields[17], sizeof(tmp) - 1); tmp[sizeof(tmp)-1] = '\0';
|
||||||
params[22] = atof(trimField(tmp));
|
char* t = trimField(tmp);
|
||||||
|
if (sscanf(t, "%lf , %lf , %lf , %lf", ¶ms[22], ¶ms[23], ¶ms[24], ¶ms[25]) != 4) {
|
||||||
|
fprintf(stderr, "loadScenario: failed to parse objectiveVar: %s\n", t);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// sensorPerformanceMinimum: column 18
|
||||||
|
{
|
||||||
|
char tmp[64]; strncpy(tmp, fields[18], sizeof(tmp) - 1); tmp[sizeof(tmp)-1] = '\0';
|
||||||
|
params[26] = atof(trimField(tmp));
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("Loaded scenario: domain [%g,%g,%g] to [%g,%g,%g]\n",
|
printf("Loaded scenario: domain [%g,%g,%g] to [%g,%g,%g]\n",
|
||||||
@@ -242,7 +254,7 @@ int loadScenario(const char* filename, double* params) {
|
|||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load initial UAV positions from scenario.csv (column 17: initialPositions).
|
// Load initial UAV positions from scenario.csv (column 19: initialPositions).
|
||||||
// targets is a column-major [maxClients x 3] array (same layout as loadTargets):
|
// targets is a column-major [maxClients x 3] array (same layout as loadTargets):
|
||||||
// targets[i + 0*maxClients] = east
|
// targets[i + 0*maxClients] = east
|
||||||
// targets[i + 1*maxClients] = north
|
// targets[i + 1*maxClients] = north
|
||||||
@@ -258,13 +270,13 @@ int loadInitialPositions(const char* filename, double* targets, int maxClients)
|
|||||||
|
|
||||||
char* fields[32];
|
char* fields[32];
|
||||||
int nf = splitCSVRow(copy, fields, 32);
|
int nf = splitCSVRow(copy, fields, 32);
|
||||||
if (nf < 19) {
|
if (nf < 20) {
|
||||||
fprintf(stderr, "loadInitialPositions: expected >=19 columns, got %d\n", nf);
|
fprintf(stderr, "loadInitialPositions: expected >=20 columns, got %d\n", nf);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Column 18: initialPositions flat "x1,y1,z1, x2,y2,z2, ..."
|
// Column 19: initialPositions flat "x1,y1,z1, x2,y2,z2, ..."
|
||||||
char tmp[1024]; strncpy(tmp, fields[18], sizeof(tmp) - 1); tmp[sizeof(tmp)-1] = '\0';
|
char tmp[1024]; strncpy(tmp, fields[19], sizeof(tmp) - 1); tmp[sizeof(tmp)-1] = '\0';
|
||||||
char* t = trimField(tmp);
|
char* t = trimField(tmp);
|
||||||
|
|
||||||
double vals[3 * 4]; // up to MAX_CLIENTS triples
|
double vals[3 * 4]; // up to MAX_CLIENTS triples
|
||||||
@@ -287,7 +299,7 @@ int loadInitialPositions(const char* filename, double* targets, int maxClients)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Load obstacle bounding-box corners from scenario.csv.
|
// Load obstacle bounding-box corners from scenario.csv.
|
||||||
// Columns used: 18 (numObstacles), 19 (obstacleMin flat), 20 (obstacleMax flat).
|
// Columns used: 20 (numObstacles), 21 (obstacleMin flat), 22 (obstacleMax flat).
|
||||||
// obstacleMin and obstacleMax are column-major [maxObstacles x 3] arrays:
|
// obstacleMin and obstacleMax are column-major [maxObstacles x 3] arrays:
|
||||||
// obstacleMin[obs + 0*maxObstacles] = east_min
|
// obstacleMin[obs + 0*maxObstacles] = east_min
|
||||||
// obstacleMin[obs + 1*maxObstacles] = north_min
|
// obstacleMin[obs + 1*maxObstacles] = north_min
|
||||||
@@ -304,19 +316,19 @@ int loadObstacles(const char* filename, double* obstacleMin, double* obstacleMax
|
|||||||
|
|
||||||
char* fields[32];
|
char* fields[32];
|
||||||
int nf = splitCSVRow(copy, fields, 32);
|
int nf = splitCSVRow(copy, fields, 32);
|
||||||
if (nf < 22) return 0;
|
if (nf < 23) return 0;
|
||||||
|
|
||||||
// Column 19: numObstacles
|
// Column 20: numObstacles
|
||||||
int n = (int)atof(trimField(fields[19]));
|
int n = (int)atof(trimField(fields[20]));
|
||||||
if (n <= 0) return 0;
|
if (n <= 0) return 0;
|
||||||
if (n > maxObstacles) {
|
if (n > maxObstacles) {
|
||||||
fprintf(stderr, "loadObstacles: %d obstacles exceeds MAX_OBSTACLES=%d\n", n, maxObstacles);
|
fprintf(stderr, "loadObstacles: %d obstacles exceeds MAX_OBSTACLES=%d\n", n, maxObstacles);
|
||||||
n = maxObstacles;
|
n = maxObstacles;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Column 20: obstacleMin flat "x0,y0,z0, x1,y1,z1, ..."
|
// Column 21: obstacleMin flat "x0,y0,z0, x1,y1,z1, ..."
|
||||||
{
|
{
|
||||||
char tmp[1024]; strncpy(tmp, fields[20], sizeof(tmp) - 1); tmp[sizeof(tmp)-1] = '\0';
|
char tmp[1024]; strncpy(tmp, fields[21], sizeof(tmp) - 1); tmp[sizeof(tmp)-1] = '\0';
|
||||||
char* t = trimField(tmp);
|
char* t = trimField(tmp);
|
||||||
double vals[3 * 8]; // up to MAX_OBSTACLES triples
|
double vals[3 * 8]; // up to MAX_OBSTACLES triples
|
||||||
int parsed = 0;
|
int parsed = 0;
|
||||||
@@ -336,9 +348,9 @@ int loadObstacles(const char* filename, double* obstacleMin, double* obstacleMax
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Column 21: obstacleMax flat
|
// Column 22: obstacleMax flat
|
||||||
{
|
{
|
||||||
char tmp[1024]; strncpy(tmp, fields[21], sizeof(tmp) - 1); tmp[sizeof(tmp)-1] = '\0';
|
char tmp[1024]; strncpy(tmp, fields[22], sizeof(tmp) - 1); tmp[sizeof(tmp)-1] = '\0';
|
||||||
char* t = trimField(tmp);
|
char* t = trimField(tmp);
|
||||||
double vals[3 * 8];
|
double vals[3 * 8];
|
||||||
int parsed = 0;
|
int parsed = 0;
|
||||||
|
|||||||
@@ -17,8 +17,9 @@ int loadTargets(const char* filename, double* targets, int maxClients);
|
|||||||
|
|
||||||
// Scenario loading (scenario.csv)
|
// Scenario loading (scenario.csv)
|
||||||
// Number of elements in the flat params array passed to guidance_step.
|
// 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.
|
// Indices: 0-13 scalars, 14-16 domainMin, 17-19 domainMax, 20-21 objectivePos,
|
||||||
#define NUM_SCENARIO_PARAMS 23
|
// 22-25 objectiveVar (2x2 col-major: [v11,v12,v21,v22]), 26 sensorPerformanceMinimum.
|
||||||
|
#define NUM_SCENARIO_PARAMS 27
|
||||||
// Maximum number of obstacles (upper bound for pre-allocated arrays).
|
// Maximum number of obstacles (upper bound for pre-allocated arrays).
|
||||||
#define MAX_OBSTACLES 8
|
#define MAX_OBSTACLES 8
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,9 @@
|
|||||||
f = uifigure;
|
f = uifigure;
|
||||||
gf = geoglobe(f);
|
gf = geoglobe(f);
|
||||||
hold(gf, "on");
|
hold(gf, "on");
|
||||||
c = ["r", "g", "b", "m", "c", "y", "k"]; % plotting colors
|
c = ["g", "b", "m", "c"]; % plotting colors
|
||||||
|
|
||||||
|
% coordinate system constants
|
||||||
seaToGroundLevel = 110; % meters, measured approximately from USGS national map viewer
|
seaToGroundLevel = 110; % meters, measured approximately from USGS national map viewer
|
||||||
lla0 = [35.72550610629396, -78.70019657805574, seaToGroundLevel]; % origin (LLA)
|
lla0 = [35.72550610629396, -78.70019657805574, seaToGroundLevel]; % origin (LLA)
|
||||||
|
|
||||||
@@ -14,28 +16,27 @@ for ii = 1:size(gpsCsvs, 1)
|
|||||||
% Read CSV
|
% Read CSV
|
||||||
G{ii} = readGpsCsv(fullfile(gpsCsvs(ii).folder, gpsCsvs(ii).name));
|
G{ii} = readGpsCsv(fullfile(gpsCsvs(ii).folder, gpsCsvs(ii).name));
|
||||||
|
|
||||||
% Find when algorithm begins/ends (using ENU altitude)
|
% Find when algorithm begins/ends (using ENU altitude rate change)
|
||||||
enuTraj = lla2enu([G{ii}.Latitude, G{ii}.Longitude, G{ii}.Altitude], lla0, 'flat');
|
enuTraj = lla2enu([G{ii}.Latitude, G{ii}.Longitude, G{ii}.Altitude], lla0, 'flat');
|
||||||
|
|
||||||
verticalSpeed = movmean(abs(diff(G{ii}.Altitude)), [10, 0]);
|
verticalSpeed = movmean(abs(diff(G{ii}.Altitude)), [10, 0]);
|
||||||
|
|
||||||
startIdx = find(verticalSpeed <= prctile(verticalSpeed, 25), 1, 'first');
|
% Automatically detect start/stop of algorithm flight (ignore takeoff, setup, return to liftoff, landing segments of flight)
|
||||||
stopIdx = find(verticalSpeed <= prctile(verticalSpeed, 10), 1, 'last');
|
startIdx = find(verticalSpeed <= prctile(verticalSpeed, 25), 1, 'first'); % 25 pct threshold may need adjusting
|
||||||
|
stopIdx = find(verticalSpeed <= prctile(verticalSpeed, 25), 1, 'last');
|
||||||
|
|
||||||
|
% % Plot whole flight, including setup/cleanup
|
||||||
% startIdx = 1;
|
% startIdx = 1;
|
||||||
% stopIdx = length(verticalSpeed);
|
% stopIdx = length(verticalSpeed);
|
||||||
|
|
||||||
speed = vecnorm(diff(enuTraj), 2, 2);
|
% Plot recorded trajectory over specified range of indices
|
||||||
meanSpeed = movmean(speed, [10, 0]);
|
|
||||||
|
|
||||||
% Plot recorded trajectory
|
|
||||||
geoplot3(gf, G{ii}.Latitude(startIdx:stopIdx), G{ii}.Longitude(startIdx:stopIdx), G{ii}.Altitude(startIdx:stopIdx) + seaToGroundLevel, c(mod(ii, length(c))), 'LineWidth', 2, "MarkerSize", 5);
|
geoplot3(gf, G{ii}.Latitude(startIdx:stopIdx), G{ii}.Longitude(startIdx:stopIdx), G{ii}.Altitude(startIdx:stopIdx) + seaToGroundLevel, c(mod(ii, length(c))), 'LineWidth', 2, "MarkerSize", 5);
|
||||||
|
|
||||||
end
|
end
|
||||||
|
|
||||||
% Plot objective
|
% Plot objective
|
||||||
objectivePos = [35, 35, 0];
|
objectivePos = [35, 35, 0];
|
||||||
llaObj = enu2lla(objectivePos, lla0, 'flat');
|
llaObj = enu2lla(objectivePos, lla0, 'flat');
|
||||||
geoplot3(gf, [llaObj(1), llaObj(1)], [llaObj(2), llaObj(2)], [llaObj(3), llaObj(3) + 50], 'LineWidth', 3);
|
geoplot3(gf, [llaObj(1), llaObj(1)], [llaObj(2), llaObj(2)], [llaObj(3), llaObj(3) + 50], 'LineWidth', 3, "Color", 'y');
|
||||||
|
|
||||||
% Plot domain
|
% Plot domain
|
||||||
altOffset = 1; % to avoid clipping into the ground when displayed
|
altOffset = 1; % to avoid clipping into the ground when displayed
|
||||||
@@ -47,4 +48,9 @@ geoplot3(gf, [domain(2, 1), domain(2, 1)], [domain(1, 2), domain(1, 2)], domain(
|
|||||||
geoplot3(gf, [domain(1, 1), domain(1, 1)], [domain(2, 2), domain(2, 2)], domain(:, 3) + altOffset, 'LineWidth', 3, 'Color', 'k');
|
geoplot3(gf, [domain(1, 1), domain(1, 1)], [domain(2, 2), domain(2, 2)], domain(:, 3) + altOffset, 'LineWidth', 3, 'Color', 'k');
|
||||||
geoplot3(gf, [domain(2, 1), domain(2, 1)], [domain(2, 2), domain(2, 2)], domain(:, 3) + altOffset, 'LineWidth', 3, 'Color', 'k');
|
geoplot3(gf, [domain(2, 1), domain(2, 1)], [domain(2, 2), domain(2, 2)], domain(:, 3) + altOffset, 'LineWidth', 3, 'Color', 'k');
|
||||||
|
|
||||||
|
% Plot floor (minimum altitude constraint)
|
||||||
|
floorAlt = 30;
|
||||||
|
geoplot3(gf, [domain(1, 1), domain(2, 1), domain(2, 1), domain(1, 1), domain(1, 1)], [domain(1, 2), domain(1, 2), domain(2, 2), domain(2, 2), domain(1, 2)], repmat(domain(1, 3) + altOffset + floorAlt, 1, 5), 'LineWidth', 3, 'Color', 'r');
|
||||||
|
|
||||||
|
% finish
|
||||||
hold(gf, "off");
|
hold(gf, "off");
|
||||||
@@ -34,7 +34,7 @@ classdef parametricTestSuite < matlab.unittest.TestCase
|
|||||||
|
|
||||||
% Define scenario according to CSV specification
|
% Define scenario according to CSV specification
|
||||||
tc.domain = tc.domain.initialize([params.domainMin; params.domainMax], REGION_TYPE.DOMAIN, "Domain");
|
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);
|
tc.domain.objective = tc.domain.objective.initialize(objectiveFunctionWrapper(params.objectivePos, reshape(params.objectiveVar, [2 2])), tc.domain, params.discretizationStep, params.protectedRange, params.sensorPerformanceMinimum);
|
||||||
|
|
||||||
agents = cell(size(params.initialPositions, 2) / 3, 1);
|
agents = cell(size(params.initialPositions, 2) / 3, 1);
|
||||||
for ii = 1:size(agents, 1)
|
for ii = 1:size(agents, 1)
|
||||||
|
|||||||
Reference in New Issue
Block a user