fixed guidance only pulling things towards the middle and added CA QP CBF code
This commit is contained in:
@@ -1,5 +1,5 @@
|
|||||||
classdef agent
|
classdef agent
|
||||||
properties (SetAccess = private, GetAccess = public)
|
properties (SetAccess = public, GetAccess = public)
|
||||||
% Identifiers
|
% Identifiers
|
||||||
index = NaN;
|
index = NaN;
|
||||||
label = "";
|
label = "";
|
||||||
|
|||||||
24
@agent/run.m
24
@agent/run.m
@@ -9,12 +9,6 @@ function obj = run(obj, domain, partitioning, t)
|
|||||||
obj (1, 1) {mustBeA(obj, 'agent')};
|
obj (1, 1) {mustBeA(obj, 'agent')};
|
||||||
end
|
end
|
||||||
|
|
||||||
% Update collision barrier function
|
|
||||||
% first part evaluates to +/-1 if the point is outside/inside the collision geometry
|
|
||||||
% Second part determines the distance from the point to the boundary of the collision geometry
|
|
||||||
obj.barrierFunction = @(x) (1 - 2 * obj.collisionGeometry.contains(x)) * obj.collisionGeometry.distance(x); % x is 1x3
|
|
||||||
obj.dBarrierFunction = @(x) obj.collisionGeometry.distanceGradient(x); % x is 1x3
|
|
||||||
|
|
||||||
% Collect objective function values across partition
|
% Collect objective function values across partition
|
||||||
partitionMask = partitioning == obj.index;
|
partitionMask = partitioning == obj.index;
|
||||||
objectiveValues = domain.objective.values(partitionMask); % f(omega) on W_n
|
objectiveValues = domain.objective.values(partitionMask); % f(omega) on W_n
|
||||||
@@ -85,6 +79,11 @@ function obj = run(obj, domain, partitioning, t)
|
|||||||
r = randi([1, size(x, 1)]);
|
r = randi([1, size(x, 1)]);
|
||||||
x = x(r); y = y(r);
|
x = x(r); y = y(r);
|
||||||
|
|
||||||
|
% switch them
|
||||||
|
temp = x;
|
||||||
|
x = y;
|
||||||
|
y = temp;
|
||||||
|
|
||||||
% find objective location in discrete domain
|
% find objective location in discrete domain
|
||||||
[~, xIdx] = find(domain.objective.groundPos(1) == domain.objective.X);
|
[~, xIdx] = find(domain.objective.groundPos(1) == domain.objective.X);
|
||||||
xIdx = unique(xIdx);
|
xIdx = unique(xIdx);
|
||||||
@@ -104,12 +103,17 @@ function obj = run(obj, domain, partitioning, t)
|
|||||||
|
|
||||||
% Use largest grad(C) value to find the direction of the next position
|
% Use largest grad(C) value to find the direction of the next position
|
||||||
[xNextIdx, yNextIdx] = find(nGradC == max(nGradC, [], 'all'));
|
[xNextIdx, yNextIdx] = find(nGradC == max(nGradC, [], 'all'));
|
||||||
|
% switch them
|
||||||
|
temp = xNextIdx;
|
||||||
|
xNextIdx = yNextIdx;
|
||||||
|
yNextIdx = temp;
|
||||||
|
|
||||||
roundingScale = 10^-log10(domain.objective.discretizationStep);
|
roundingScale = 10^-log10(domain.objective.discretizationStep);
|
||||||
pNext = [floor(roundingScale .* mean(unique(domain.objective.X(:, xNextIdx))))./roundingScale, floor(roundingScale .* mean(unique(domain.objective.Y(yNextIdx, :))))./roundingScale, obj.pos(3)]; % have to do some unfortunate rounding here soemtimes
|
pNext = [floor(roundingScale .* mean(unique(domain.objective.X(:, xNextIdx))))./roundingScale, floor(roundingScale .* mean(unique(domain.objective.Y(yNextIdx, :))))./roundingScale, obj.pos(3)]; % have to do some unfortunate rounding here soemtimes
|
||||||
|
|
||||||
% Determine next position
|
% Determine next position
|
||||||
vDir = (pNext - obj.pos)./norm(pNext - obj.pos, 2);
|
vDir = (pNext - obj.pos)./norm(pNext - obj.pos, 2);
|
||||||
rate = 0.2 - 0.004 * t;
|
rate = 0.1 - 0.0004 * t; % slow down as you get closer, coming to a stop by the end
|
||||||
nextPos = obj.pos + vDir * rate;
|
nextPos = obj.pos + vDir * rate;
|
||||||
|
|
||||||
% Move to next position
|
% Move to next position
|
||||||
@@ -118,5 +122,11 @@ function obj = run(obj, domain, partitioning, t)
|
|||||||
|
|
||||||
% Reinitialize collision geometry in the new position
|
% Reinitialize collision geometry in the new position
|
||||||
d = obj.pos - obj.collisionGeometry.center;
|
d = obj.pos - obj.collisionGeometry.center;
|
||||||
|
if isa(obj.collisionGeometry, 'rectangularPrism')
|
||||||
obj.collisionGeometry = obj.collisionGeometry.initialize([obj.collisionGeometry.minCorner; obj.collisionGeometry.maxCorner] + d, obj.collisionGeometry.tag, obj.collisionGeometry.label);
|
obj.collisionGeometry = obj.collisionGeometry.initialize([obj.collisionGeometry.minCorner; obj.collisionGeometry.maxCorner] + d, obj.collisionGeometry.tag, obj.collisionGeometry.label);
|
||||||
|
elseif isa(obj.collisionGeometry, 'spherical')
|
||||||
|
obj.collisionGeometry = obj.collisionGeometry.initialize(obj.collisionGeometry.center + d, obj.collisionGeometry.radius, obj.collisionGeometry.tag, obj.collisionGeometry.label);
|
||||||
|
else
|
||||||
|
error("?");
|
||||||
|
end
|
||||||
end
|
end
|
||||||
61
@miSim/constrainMotion.m
Normal file
61
@miSim/constrainMotion.m
Normal file
@@ -0,0 +1,61 @@
|
|||||||
|
function [obj] = constrainMotion(obj)
|
||||||
|
arguments (Input)
|
||||||
|
obj (1, 1) {mustBeA(obj, 'miSim')};
|
||||||
|
end
|
||||||
|
arguments (Output)
|
||||||
|
obj (1, 1) {mustBeA(obj, 'miSim')};
|
||||||
|
end
|
||||||
|
|
||||||
|
if size(obj.agents, 1) < 2
|
||||||
|
return;
|
||||||
|
% this doesn't work right now with only one agent
|
||||||
|
end
|
||||||
|
|
||||||
|
agents = [obj.agents{:}];
|
||||||
|
v = reshape(([agents.pos] - [agents.lastPos])./obj.timestep, 3, size(obj.agents, 1))';
|
||||||
|
|
||||||
|
h = NaN(size(obj.agents, 1));
|
||||||
|
h(logical(eye(size(obj.agents, 1)))) = 0; % self value is 0
|
||||||
|
nCon = nchoosek(size(obj.agents, 1), 2);
|
||||||
|
kk = 1;
|
||||||
|
A = zeros(nCon, 3 * size(obj.agents, 1));
|
||||||
|
b = zeros(nCon, 1);
|
||||||
|
for ii = 1:(size(obj.agents, 1) - 1)
|
||||||
|
for jj = (ii + 1):size(obj.agents, 1)
|
||||||
|
h(ii, jj) = norm(agents(ii).pos - agents(jj).pos)^2 - (agents(ii).collisionGeometry.radius + agents(jj).collisionGeometry.radius)^2;
|
||||||
|
h(jj, ii) = h(ii, jj);
|
||||||
|
|
||||||
|
A(kk, (3 * ii - 2):(3 * ii)) = -2 * (agents(ii).pos - agents(jj).pos);
|
||||||
|
A(kk, (3 * jj - 2):(3 * jj)) = -A(kk, (3 * ii - 2):(3 * ii));
|
||||||
|
b(kk) = obj.barrierGain * h(ii, jj)^3;
|
||||||
|
kk = kk + 1;
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
% Solve QP program generated earlier
|
||||||
|
vhat = reshape(v', 3 * size(obj.agents, 1), 1);
|
||||||
|
H = 2 * eye(3 * size(obj.agents, 1));
|
||||||
|
f = -2 * vhat;
|
||||||
|
|
||||||
|
% Update solution based on constraints
|
||||||
|
opt = optimoptions('quadprog', 'Display', 'off');
|
||||||
|
[vNew, ~, exitflag] = quadprog(sparse(H), double(f), A, b, [],[], [], [], [], opt);
|
||||||
|
vNew = reshape(vNew, 3, size(obj.agents, 1))';
|
||||||
|
|
||||||
|
if exitflag <= 0
|
||||||
|
warning("QP failed, continuing with unconstrained solution...")
|
||||||
|
vNew = v;
|
||||||
|
end
|
||||||
|
|
||||||
|
% Update the "next position" that was previously set by unconstrained
|
||||||
|
% GA using the constrained solution produced here
|
||||||
|
for ii = 1:size(vNew, 1)
|
||||||
|
obj.agents{ii}.pos = obj.agents{ii}.lastPos + vNew(ii, :) * obj.timestep;
|
||||||
|
end
|
||||||
|
|
||||||
|
% Here we run this at the simulation level, but in reality there is no
|
||||||
|
% parent level, so this would be run independently on each agent.
|
||||||
|
% Running at the simulation level is just meant to simplify the
|
||||||
|
% simulation
|
||||||
|
|
||||||
|
end
|
||||||
@@ -14,6 +14,7 @@ classdef miSim
|
|||||||
sensorPerformanceMinimum = 1e-6; % minimum sensor performance to allow assignment of a point in the domain to a partition
|
sensorPerformanceMinimum = 1e-6; % minimum sensor performance to allow assignment of a point in the domain to a partition
|
||||||
partitioning = NaN;
|
partitioning = NaN;
|
||||||
performance = 0; % cumulative sensor performance
|
performance = 0; % cumulative sensor performance
|
||||||
|
barrierGain = 100; % collision avoidance parameter
|
||||||
|
|
||||||
fPerf; % performance plot figure
|
fPerf; % performance plot figure
|
||||||
end
|
end
|
||||||
@@ -43,6 +44,7 @@ classdef miSim
|
|||||||
methods (Access = public)
|
methods (Access = public)
|
||||||
[obj] = initialize(obj, domain, objective, agents, timestep, partitoningFreq, maxIter, obstacles);
|
[obj] = initialize(obj, domain, objective, agents, timestep, partitoningFreq, maxIter, obstacles);
|
||||||
[obj] = run(obj);
|
[obj] = run(obj);
|
||||||
|
[obj] = constrainMotion(obj);
|
||||||
[obj] = partition(obj);
|
[obj] = partition(obj);
|
||||||
[obj] = updateAdjacency(obj);
|
[obj] = updateAdjacency(obj);
|
||||||
[obj] = plot(obj);
|
[obj] = plot(obj);
|
||||||
|
|||||||
@@ -27,6 +27,10 @@ function [obj] = run(obj)
|
|||||||
obj.agents{jj} = obj.agents{jj}.run(obj.domain, obj.partitioning, obj.t);
|
obj.agents{jj} = obj.agents{jj}.run(obj.domain, obj.partitioning, obj.t);
|
||||||
end
|
end
|
||||||
|
|
||||||
|
% Adjust motion determined by unconstrained gradient ascent using
|
||||||
|
% CBF constraints solved by QP
|
||||||
|
obj = constrainMotion(obj);
|
||||||
|
|
||||||
% Update total performance
|
% Update total performance
|
||||||
obj.performance = [obj.performance, sum(cellfun(@(x) x.performance(end), obj.agents))];
|
obj.performance = [obj.performance, sum(cellfun(@(x) x.performance(end), obj.agents))];
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,10 @@ function obj = initialize(obj, bounds, tag, label, objectiveFunction, discretiza
|
|||||||
% Compute center
|
% Compute center
|
||||||
obj.center = obj.minCorner + obj.dimensions ./ 2;
|
obj.center = obj.minCorner + obj.dimensions ./ 2;
|
||||||
|
|
||||||
|
% Compute a (fake) radius
|
||||||
|
% fully contains the rectangular prism from the center
|
||||||
|
obj.radius = (1/2) * sqrt(sum(obj.dimensions.^2));
|
||||||
|
|
||||||
% Compute vertices
|
% Compute vertices
|
||||||
obj.vertices = [obj.minCorner;
|
obj.vertices = [obj.minCorner;
|
||||||
obj.maxCorner(1), obj.minCorner(2:3);
|
obj.maxCorner(1), obj.minCorner(2:3);
|
||||||
@@ -44,4 +48,13 @@ function obj = initialize(obj, bounds, tag, label, objectiveFunction, discretiza
|
|||||||
if tag == REGION_TYPE.DOMAIN
|
if tag == REGION_TYPE.DOMAIN
|
||||||
obj.objective = sensingObjective;
|
obj.objective = sensingObjective;
|
||||||
end
|
end
|
||||||
|
|
||||||
|
% Initialize CBF
|
||||||
|
% first part evaluates to +/-1 if the point is outside/inside the collision geometry
|
||||||
|
% Second part determines the distance from the point to the boundary of the collision geometry
|
||||||
|
obj.barrierFunction = @(x) (1 - 2 * obj.collisionGeometry.contains(x)) * obj.collisionGeometry.distance(x); % x is 1x3
|
||||||
|
% gradient of barrier function
|
||||||
|
obj.dBarrierFunction = @(x) obj.collisionGeometry.distanceGradient(x); % x is 1x3
|
||||||
|
% as long as the collisionGeometry object is updated during runtime,
|
||||||
|
% these functions never have to be updated again
|
||||||
end
|
end
|
||||||
@@ -11,6 +11,7 @@ classdef rectangularPrism
|
|||||||
dimensions = NaN(1, 3);
|
dimensions = NaN(1, 3);
|
||||||
center = NaN;
|
center = NaN;
|
||||||
footprint = NaN(4, 2);
|
footprint = NaN(4, 2);
|
||||||
|
radius = NaN; % fake radius
|
||||||
|
|
||||||
% Graph
|
% Graph
|
||||||
vertices = NaN(8, 3);
|
vertices = NaN(8, 3);
|
||||||
@@ -20,6 +21,10 @@ classdef rectangularPrism
|
|||||||
|
|
||||||
% Plotting
|
% Plotting
|
||||||
lines;
|
lines;
|
||||||
|
|
||||||
|
% collision
|
||||||
|
barrierFunction;
|
||||||
|
dBarrierFunction;
|
||||||
end
|
end
|
||||||
properties (SetAccess = public, GetAccess = public)
|
properties (SetAccess = public, GetAccess = public)
|
||||||
% Sensing objective (for DOMAIN region type only)
|
% Sensing objective (for DOMAIN region type only)
|
||||||
|
|||||||
10
geometries/@spherical/contains.m
Normal file
10
geometries/@spherical/contains.m
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
function c = contains(obj, pos)
|
||||||
|
arguments (Input)
|
||||||
|
obj (1, 1) {mustBeA(obj, 'spherical')};
|
||||||
|
pos (:, 3) double;
|
||||||
|
end
|
||||||
|
arguments (Output)
|
||||||
|
c (:, 1) logical
|
||||||
|
end
|
||||||
|
c = norm(obj.center - pos) <= obj.radius;
|
||||||
|
end
|
||||||
28
geometries/@spherical/containsLine.m
Normal file
28
geometries/@spherical/containsLine.m
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
function c = containsLine(obj, pos1, pos2)
|
||||||
|
arguments (Input)
|
||||||
|
obj (1, 1) {mustBeA(obj, 'spherical')};
|
||||||
|
pos1 (1, 3) double;
|
||||||
|
pos2 (1, 3) double;
|
||||||
|
end
|
||||||
|
arguments (Output)
|
||||||
|
c (1, 1) logical
|
||||||
|
end
|
||||||
|
|
||||||
|
d = pos2 - pos1;
|
||||||
|
f = pos1 - obj.center;
|
||||||
|
|
||||||
|
a = dot(d, d);
|
||||||
|
b = 2 * dot(f, d);
|
||||||
|
c = dot(f, f) - obj.radius^2;
|
||||||
|
|
||||||
|
disc = b^2 - 4*a*c;
|
||||||
|
|
||||||
|
if disc < 0
|
||||||
|
c = false;
|
||||||
|
return;
|
||||||
|
end
|
||||||
|
|
||||||
|
t = [(-b - sqrt(disc)) / (2 * a), (-b + sqrt(disc)) / (2 * a)];
|
||||||
|
|
||||||
|
c = (t(1) >= 0 && t(1) <= 1) || (t(2) >= 0 && t(2) <= 1);
|
||||||
|
end
|
||||||
42
geometries/@spherical/initialize.m
Normal file
42
geometries/@spherical/initialize.m
Normal file
@@ -0,0 +1,42 @@
|
|||||||
|
function obj = initialize(obj, center, radius, tag, label)
|
||||||
|
arguments (Input)
|
||||||
|
obj (1, 1) {mustBeA(obj, 'spherical')};
|
||||||
|
center (1, 3) double;
|
||||||
|
radius (1, 1) double;
|
||||||
|
tag (1, 1) REGION_TYPE = REGION_TYPE.INVALID;
|
||||||
|
label (1, 1) string = "";
|
||||||
|
end
|
||||||
|
arguments (Output)
|
||||||
|
obj (1, 1) {mustBeA(obj, 'spherical')};
|
||||||
|
end
|
||||||
|
|
||||||
|
obj.tag = tag;
|
||||||
|
obj.label = label;
|
||||||
|
|
||||||
|
% Define geometry
|
||||||
|
obj.center = center;
|
||||||
|
obj.radius = radius;
|
||||||
|
obj.diameter = 2 * obj.radius;
|
||||||
|
|
||||||
|
% Initialize CBF
|
||||||
|
obj.barrierFunction = @(x) NaN;
|
||||||
|
% gradient of barrier function
|
||||||
|
obj.dBarrierFunction = @(x) NaN;
|
||||||
|
|
||||||
|
% fake vertices in a cross pattern
|
||||||
|
obj.vertices = [obj.center + [obj.radius, 0, 0]; ...
|
||||||
|
obj.center - [obj.radius, 0, 0]; ...
|
||||||
|
obj.center + [0, obj.radius, 0]; ...
|
||||||
|
obj.center - [0, obj.radius, 0]; ...
|
||||||
|
obj.center + [0, 0, obj.radius]; ...
|
||||||
|
obj.center - [0, 0, obj.radius]];
|
||||||
|
% fake edges in two perpendicular rings
|
||||||
|
obj.edges = [1, 3; ...
|
||||||
|
3, 2; ...
|
||||||
|
2, 4; ...
|
||||||
|
4, 1; ...
|
||||||
|
1, 5; ...
|
||||||
|
5, 2; ...
|
||||||
|
2, 6; ...
|
||||||
|
6, 1];
|
||||||
|
end
|
||||||
43
geometries/@spherical/plotWireframe.m
Normal file
43
geometries/@spherical/plotWireframe.m
Normal file
@@ -0,0 +1,43 @@
|
|||||||
|
function [obj, f] = plotWireframe(obj, ind, f)
|
||||||
|
arguments (Input)
|
||||||
|
obj (1, 1) {mustBeA(obj, 'spherical')};
|
||||||
|
ind (1, :) double = NaN;
|
||||||
|
f (1, 1) {mustBeA(f, 'matlab.ui.Figure')} = figure;
|
||||||
|
end
|
||||||
|
arguments (Output)
|
||||||
|
obj (1, 1) {mustBeA(obj, 'spherical')};
|
||||||
|
f (1, 1) {mustBeA(f, 'matlab.ui.Figure')};
|
||||||
|
end
|
||||||
|
|
||||||
|
% Create axes if they don't already exist
|
||||||
|
f = firstPlotSetup(f);
|
||||||
|
|
||||||
|
% Create plotting inputs
|
||||||
|
[X, Y, Z] = sphere(8);
|
||||||
|
% Scale
|
||||||
|
X = X * obj.radius;
|
||||||
|
Y = Y * obj.radius;
|
||||||
|
Z = Z * obj.radius;
|
||||||
|
% Shift
|
||||||
|
X = X + obj.center(1);
|
||||||
|
Y = Y + obj.center(2);
|
||||||
|
Z = Z + obj.center(3);
|
||||||
|
|
||||||
|
% Plot the boundaries of the geometry into 3D view
|
||||||
|
if isnan(ind)
|
||||||
|
o = plot3(f.CurrentAxes, X, Y, Z, '-', 'Color', obj.tag.color, 'LineWidth', 2);
|
||||||
|
else
|
||||||
|
hold(f.Children(1).Children(ind(1)), "on");
|
||||||
|
o = plot3(f.Children(1).Children(ind(1)), X, Y, Z, '-', 'Color', obj.tag.color, 'LineWidth', 2);
|
||||||
|
hold(f.Children(1).Children(ind(1)), "off");
|
||||||
|
end
|
||||||
|
|
||||||
|
% Copy to other requested tiles
|
||||||
|
if numel(ind) > 1
|
||||||
|
for ii = 2:size(ind, 2)
|
||||||
|
o = [o, copyobj(o(:, 1), f.Children(1).Children(ind(ii)))];
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
obj.lines = o;
|
||||||
|
end
|
||||||
15
geometries/@spherical/random.m
Normal file
15
geometries/@spherical/random.m
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
function r = random(obj)
|
||||||
|
arguments (Input)
|
||||||
|
obj (1, 1) {mustBeA(obj, 'spherical')};
|
||||||
|
end
|
||||||
|
arguments (Output)
|
||||||
|
r (1, 3) double
|
||||||
|
end
|
||||||
|
y = (rand - 0.5) * 2; % uniform draw on [-1, 1]
|
||||||
|
R = sqrt(1 - y^2);
|
||||||
|
lon = (rand - 0.5) * 2 * pi; % uniform draw on [-pi, pi]
|
||||||
|
s = [R * sin(lon), y, R * cos(lon)]; % random point on surface
|
||||||
|
r = s * rand^(1/3); % scaled to random normalized radius [0, 1]
|
||||||
|
|
||||||
|
r = obj.center + obj.radius * r;
|
||||||
|
end
|
||||||
37
geometries/@spherical/spherical.m
Normal file
37
geometries/@spherical/spherical.m
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
classdef spherical
|
||||||
|
% Rectangular prism geometry
|
||||||
|
properties (SetAccess = private, GetAccess = public)
|
||||||
|
% Meta
|
||||||
|
tag = REGION_TYPE.INVALID;
|
||||||
|
label = "";
|
||||||
|
|
||||||
|
% Spatial
|
||||||
|
center = NaN;
|
||||||
|
radius = NaN;
|
||||||
|
diameter = NaN;
|
||||||
|
|
||||||
|
vertices; % fake vertices
|
||||||
|
edges; % fake edges
|
||||||
|
|
||||||
|
% Plotting
|
||||||
|
lines;
|
||||||
|
|
||||||
|
% collision
|
||||||
|
barrierFunction;
|
||||||
|
dBarrierFunction;
|
||||||
|
end
|
||||||
|
properties (SetAccess = public, GetAccess = public)
|
||||||
|
% Sensing objective (for DOMAIN region type only)
|
||||||
|
objective;
|
||||||
|
end
|
||||||
|
|
||||||
|
methods (Access = public)
|
||||||
|
[obj ] = initialize(obj, center, radius, tag, label);
|
||||||
|
[r ] = random(obj);
|
||||||
|
[c ] = contains(obj, pos);
|
||||||
|
[d ] = distance(obj, pos);
|
||||||
|
[g ] = distanceGradient(obj, pos);
|
||||||
|
[c ] = containsLine(obj, pos1, pos2);
|
||||||
|
[obj, f] = plotWireframe(obj, ind, f);
|
||||||
|
end
|
||||||
|
end
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info>
|
||||||
|
<Category UUID="FileClassCategory">
|
||||||
|
<Label UUID="design"/>
|
||||||
|
</Category>
|
||||||
|
</Info>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info location="random.m" type="File"/>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info>
|
||||||
|
<Category UUID="FileClassCategory">
|
||||||
|
<Label UUID="design"/>
|
||||||
|
</Category>
|
||||||
|
</Info>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info location="containsLine.m" type="File"/>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info>
|
||||||
|
<Category UUID="FileClassCategory">
|
||||||
|
<Label UUID="design"/>
|
||||||
|
</Category>
|
||||||
|
</Info>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info location="spherical.m" type="File"/>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info/>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info location="1" type="DIR_SIGNIFIER"/>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info>
|
||||||
|
<Category UUID="FileClassCategory">
|
||||||
|
<Label UUID="design"/>
|
||||||
|
</Category>
|
||||||
|
</Info>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info location="contains.m" type="File"/>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info>
|
||||||
|
<Category UUID="FileClassCategory">
|
||||||
|
<Label UUID="design"/>
|
||||||
|
</Category>
|
||||||
|
</Info>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info location="initialize.m" type="File"/>
|
||||||
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info>
|
||||||
|
<Category UUID="FileClassCategory">
|
||||||
|
<Label UUID="design"/>
|
||||||
|
</Category>
|
||||||
|
</Info>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info location="plotWireframe.m" type="File"/>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info/>
|
||||||
@@ -0,0 +1,2 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Info location="@spherical" type="File"/>
|
||||||
@@ -279,8 +279,10 @@ classdef test_miSim < matlab.unittest.TestCase
|
|||||||
end
|
end
|
||||||
|
|
||||||
% Initialize candidate agent collision geometry
|
% Initialize candidate agent collision geometry
|
||||||
candidateGeometry = rectangularPrism;
|
% candidateGeometry = rectangularPrism;
|
||||||
candidateGeometry = candidateGeometry.initialize([candidatePos - tc.collisionRanges(ii) * ones(1, 3); candidatePos + tc.collisionRanges(ii) * ones(1, 3)], REGION_TYPE.COLLISION, sprintf("Agent %d collision volume", ii));
|
% candidateGeometry = candidateGeometry.initialize([candidatePos - tc.collisionRanges(ii) * ones(1, 3); candidatePos + tc.collisionRanges(ii) * ones(1, 3)], REGION_TYPE.COLLISION, sprintf("Agent %d collision volume", ii));
|
||||||
|
candidateGeometry = spherical;
|
||||||
|
candidateGeometry = candidateGeometry.initialize(candidatePos, tc.collisionRanges(ii), REGION_TYPE.COLLISION, sprintf("Agent %d collision volume", ii));
|
||||||
|
|
||||||
% Initialize candidate agent sensor model
|
% Initialize candidate agent sensor model
|
||||||
sensor = sigmoidSensor;
|
sensor = sigmoidSensor;
|
||||||
@@ -418,7 +420,7 @@ classdef test_miSim < matlab.unittest.TestCase
|
|||||||
tc.domain = tc.domain.initialize([zeros(1, 3); l * ones(1, 3)], REGION_TYPE.DOMAIN, "Domain");
|
tc.domain = tc.domain.initialize([zeros(1, 3); l * ones(1, 3)], REGION_TYPE.DOMAIN, "Domain");
|
||||||
|
|
||||||
% make basic sensing objective
|
% make basic sensing objective
|
||||||
tc.domain.objective = tc.domain.objective.initialize(@(x, y) mvnpdf([x(:), y(:)], tc.domain.center(1:2)), tc.domain, tc.discretizationStep, tc.protectedRange);
|
tc.domain.objective = tc.domain.objective.initialize(@(x, y) mvnpdf([x(:), y(:)], [2, 8]), tc.domain, tc.discretizationStep, tc.protectedRange);
|
||||||
|
|
||||||
% Initialize agent collision geometry
|
% Initialize agent collision geometry
|
||||||
geometry1 = rectangularPrism;
|
geometry1 = rectangularPrism;
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
function mustBeGeometry(geometry)
|
function mustBeGeometry(geometry)
|
||||||
validGeometries = ["rectangularPrism";];
|
validGeometries = ["rectangularPrism"; "spherical"];
|
||||||
if isa(geometry, 'cell')
|
if isa(geometry, 'cell')
|
||||||
for ii = 1:size(geometry, 1)
|
for ii = 1:size(geometry, 1)
|
||||||
assert(any(arrayfun(@(x) isa(geometry{ii}, x), validGeometries)), "Geometry in index %d is not a valid geometry class", ii);
|
assert(any(arrayfun(@(x) isa(geometry{ii}, x), validGeometries)), "Geometry in index %d is not a valid geometry class", ii);
|
||||||
|
|||||||
Reference in New Issue
Block a user