Selecting the min value in a matrix but with conditions

3 views (last 30 days)
I am trying to simulate swarms of agents. I have working code (using loops) but now I am trying vectorize the code. I have a function that takes in an array of agents and returns the closest agent that is also in the field of view (fov) of that agent. I have the trivial part of min distance calculation and selection but I cannot figure out how to do the selection based on the fov.
My thought was to set the agents locations to NaN that are not in the fov of a given agent. It seems to me that my other calculations would then just ignore the 'NaN' agents and thus pick the correct agent. Another dilemma is what happens when all agents are converted to NaN.
Here is my code that does the distance calculations and selection.
% --- data for testing purposes --- %
max_motion = 1.0;
% --- random initial flock position
index = 1;
for i = 1 : 10
% --- set the location of the flock member
theta = rand(1,1)*(2*pi);
r = sqrt(rand(1,1))*10;
flock(index, 1, 1) = r.*cos(theta);
flock(index, 1, 2) = r.*sin(theta);
% --- set the initial heading of the flock member (in degrees )
flock(index, 2, 1) = 360.*rand(1,1);
% --- set the initial speed
flock(index, 3, 1) = 1.0;
index = index + 1;
end
% --- parameters --- %
sensing_range = 20; %
range_agent_repulsion = 3; %
range_collision = 0.5; %
max_gamma = 0.1; % motion noise
min_gamma = -0.1; % motion noise
max_turn = deg2rad(10); % in degrees
min_motion = max_motion;
gain = 1;
gain_obstacle = 9.0;
gain_agent = 0.5;
% --- grab the flock locations
%disp('LOCATIONS')
locations = flock(:,1,:);
% --- get the dimension and size of the flock
[flock_size,dims] = size(locations);
% --- reshape the location matrice
%disp('RESHAPE')
a = reshape(locations,1,flock_size,dims);
b = reshape(locations,flock_size,1,dims);
% --- compute the distances
%disp('DISTANCES')
distances = sqrt(sum((a(ones(flock_size,1),:,:)-b(:,ones(flock_size,1),:)).^2,3));
%pause(100)
% --- convert the diagonal to NaN's
%disp('DISTANCES')
distances(logical(eye(size(distances)))) = NaN;
% --- grab the minimum distances
%disp('MIN')
[min_distances,min_index] = min(distances,[],2);
%pause(100)
% --- grab the locations of the minimum distances
%disp('LOCATIONS OF MIN')
locations_of_min = locations(min_index,:);
%pause(100)
% --- check which distances are not within the repulsion radius
%disp('REPULSION RANGE CHECK')
repulsion = range_agent_repulsion*ones(flock_size);
r = bsxfun(@ge, min_distances, repulsion);
%pause(100)
% --- check which distances are outside the sensing radius
%disp('SENSING RANGE CHECK')
sensing = sensing_range*ones(flock_size);
s = bsxfun(@le, min_distances, sensing);
%pause(100)
for i = 1 : flock_size
if ~r(i) || ~s(i)
locations_of_min(i,:) = locations(i,:);
end
end
  1 Comment
Benjamin
Benjamin on 19 Dec 2012
So I have working code for the angle check, what I need is ideas on adding it into the vectorized form of the min distance selection. I can post the angle code if somebody needs it. Thanks for y'all's help.

Sign in to comment.

Answers (1)

Benjamin
Benjamin on 19 Dec 2012
The below code is my fix to the problem, it is ugly but it seems to be working. Feel free to send improvements my way if you have the time. Thanks again to all.
% --- check the field of view
for i = 1 : flock_size
for j = 1 : flock_size
if ~calc_is_agent_in_fov(locations(i,:),locations(j,:),flock(i,2,1));
distances(i,j) = NaN;
end
end
end
%disp(distances)
% --- grab the minimum distances
%disp('MIN')
[min_distances,min_index] = min(distances,[],2);
%pause(100)
% --- grab the locations of the minimum distances
%disp('LOCATIONS OF MIN')
locations_of_min = locations(min_index,:);
%pause(100)
% --- check if no agents in field of view
fov = NaN*ones(flock_size);
fov = bsxfun(@eq, min_distances, fov);
% --- check which distances are not within the repulsion radius
%disp('REPULSION RANGE CHECK')
repulsion = range_agent_repulsion*ones(flock_size);
r = bsxfun(@ge, min_distances, repulsion);
%pause(100)
% --- check which distances are outside the sensing radius
%disp('SENSING RANGE CHECK')
sensing = sensing_range*ones(flock_size);
s = bsxfun(@le, min_distances, sensing);
%pause(100)
for i = 1 : flock_size
if ~r(i) || ~s(i) || fov(i)
locations_of_min(i,:) = locations(i,:);
end
end

Categories

Find more on Optimization Toolbox in Help Center and File Exchange

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!