I have the following code to generate a PRM map that will be used for A* application. There exist 2 problems with the code
- It keeps the blue lines representing the original PRM where lines can cross over obstacles. I don't want to keep the blue lines but I couldn't find the way to remove them.
- The green lines are going over obstacles even though they shouldn't
The code is as follows
clc;
clear all;
close all;
seed = 123512;
rng(seed);
xaxis = 100;
yaxis = 100;
obstacles = false(xaxis,yaxis);
[X,Y] = meshgrid(1:xaxis,1:yaxis);
obstacles(50:75,50:75) = true;
obstacles(25:35,30:40) = true;
obstacles(25:35,60:80) = true;
figure;
imshow(~obstacles,"InitialMagnification",1000);
axis([0 xaxis 0 yaxis]);
axis xy;
axis on;
%PRM PARAMETERS
max_nodes_connect = 4;
max_connect_len = 40;
segments = 1;
max_nodes_grid = 30;
skipped = 0;
%PRM ALGO
nodes = 0; %Counter
map = zeros(size(obstacles)); %generate map
map(obstacles) = 1; %put the obstacles
Graph_connections = Inf(max_nodes_grid,max_nodes_connect + 1); %rows = # nodes cols = ID and neighbors
while (nodes < max_nodes_grid)
node_x = randi(xaxis);
node_y = randi(yaxis);
if(map(node_y,node_x)==1 || map(node_y,node_x)==2)
continue;
end
nodes = nodes + 1; %a valid node generated
map(node_y,node_x) = 2; %2 means there exists a node at that location
hold on
scatter(node_x,node_y,"red","filled")
%NODES TO CONNECT
nodes_to_connect = [];
distances = [];
for i= 1:numel(Graph_connections(:,1))
if(Graph_connections(i,1)==Inf)
break
end
[row,col] = ind2sub(size(map),Graph_connections(i,1));
%Check if within range
if(norm([node_y,node_x]-[row,col])>max_connect_len)
continue;
end
line_on_obstacle = check_obstacle(map,node_x,node_y,row,col);
%Check if obstacle thru line HAS TO BE WRITTEN
if(line_on_obstacle)
disp("Check Obstacle: " + line_on_obstacle);
skipped = skipped + 1;
continue;
end
nodes_to_connect = [nodes_to_connect, Graph_connections(i,1)];
distances = [distances; [Graph_connections(i,1),norm([node_y,node_x]-[row,col])]];
end
Graph_connections(nodes,1) = sub2ind(size(map),node_y,node_x);
if(size(distances)>0)
sorted_distances = sortrows(distances,2);
for i = 1:min(max_nodes_connect,size(sorted_distances,1))
Graph_connections(nodes,i+1) = sorted_distances(i,1);
[row,col] = ind2sub(size(map),sorted_distances(i,1));
if(line_on_obstacle==false)
disp("Line is not on obstacle")
hold on
plot([node_x,col],[node_y,row],"green","LineWidth",1.5);
continue;
else
disp("Line is on obstacle: " + [node_x,col] + " " + [node_y,row]);
break;
end
end
disp("==========================")
end
end
function on_line = check_obstacle(map,node_x,node_y,row,col)
on_line = 0;
my_line = line([node_x,col],[node_y,row]);
line_spacing = max(abs(my_line.XData(1) - my_line.XData(2))+1,abs(my_line.XData(1) - my_line.XData(2))+1);
x_coordinates_line = round(linspace(my_line.XData(1),my_line.XData(2),line_spacing));
y_coordinates_line = round(linspace(my_line.YData(1),my_line.YData(2),line_spacing));
for i = 1:line_spacing
if(map(x_coordinates_line(i),y_coordinates_line(i))==1)
disp("ON OBSTACLE: " + x_coordinates_line(i) + " " + y_coordinates_line(i));
on_line = true;
break;
end
end
end
The check_obstacle function is used to check if the points on the line are in the boundaries of obstacles. What am I missing here?
Redrawing and NOT removing net segments longer than
Dmax
Comments
1.- Note I have added
format short
because withformat long
there is decimal accretion right at the bottom of a few intersection points, that believe it or not, cause some false results.2.- I like Torsen's explanation to find line segment intersections available here.
3.- There are faster ways to implement the main loop, but I make it go through all net-segment vs obstacle-element in case you may need it this way, to for instance count hits.
4.- There's also room for improvement in the way
Lobst
is generated.5.- These lines
it's just an easy way to plug in formulation to already written lines, reducing amount variables is also left for next version.