-
Notifications
You must be signed in to change notification settings - Fork 0
/
DrawingEngine.m
339 lines (309 loc) · 11.3 KB
/
DrawingEngine.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
%% Drawing Engine
% This Program takes an input image and generates trajectories for the ABB
% IRB 1600 robot to draw. First, edges are detected with canny edge
% detection. Second, a propritary bredth first seach algorithm is used to
% make seach for lines. This process is itterated through the image a
% pixel at a time. Pixels are toggled to zero to ensure lines are not
% overlayed
clc
close all
clear variables
% A personal photo of Moscow City from September 2016 is locally stored in
% the file directory. The image is loaded in as a test file. It is a jpg
% but its 2017 to hopefully that won"t matter.
I = imread('Photos/PTDC0073.jpg');
% The 12 Megapixel native size from the camera is just too big for MATLAB.
% It actually does the resizing automatically and throws a warning, but
% this shuts it up.
I = imresize(I, 0.33);
% Displays info about the image and the image itself
%whos J
%figure, imshow(I);
% the image must be converted to greyscale
gray = rgb2gray(I);
figure, imshow(gray);
% Run Canny Edge detection to find the outlines
edge_method = 'Canny';
%threshold = 0.05;
can = edge(gray, edge_method);
figure, imshow(can);
%% Path Making Finding
% form a collection
collection = {};
eightConnect = [0 1; 1 1; 1 0; 1 -1; 0 -1; -1 -1; -1 0; -1 1];
hasNeighbors = false;
isDone = false;
frontier = {};
repeat = {};
% set the values that determine which paths and points to keep
minLength = 6;
storePointCount = 6;
%can = [0 0 0 0 0 0 0 0; 0 0 1 1 0 1 1 0; 0 0 0 0 1 0 1 0;1 1 1 1 0 0 1 1;1 0 1 0 1 0 1 1;1 1 0 0 0 1 0 1;1 0 1 1 0 1 1 1;0 0 1 1 0 0 0 0]
[row,col] = size(can);
% Begin to form a chain of pixels
curve = {};
% Initialize count of curves
curveCount = 0;
% Initialize count of points
pointCount = 0;
while ~isDone
% Iterate through each cell
% Go Through each row
for r_m = 1:row
% Go through each element
for c_m = 1:col
% Get the current pixel
r_s = r_m;
c_s = c_m;
pixel = can(r_s,c_s);
% If its an edge
while pixel
% Initially assume it has no neighbors
hasNeighbors = false;
% Check if it has any neighbors
for m = 1:length(eightConnect)
% If the next pixel is an edge
x = r_s + eightConnect(m, 1);
y = c_s + eightConnect(m, 2);
% check for validity of neighbors
if (x > 0) && (y > 0) && (x <= row) && (y <= col)
% If a neighbor is valid and an edge and store only
% every other point
if can(x, y)
% add to frontier
frontier{end+1} = [x,y];
% set flag to true
hasNeighbors = true;
end
end
end
% if it has neighbors
if hasNeighbors
% store only every other point
if (mod(pointCount,storePointCount) == 0)
% Add the current pixel as the first in the chain
curve{end+1}=[r_s c_s];
end
pointCount = pointCount +1;
% If conected to more than one pixel, store info to avoid
% loss of lines
if(length(frontier) > 1)
%has more than one connection so add to list and clear
%to avoid loops
repeat{end+1}=[r_s c_s];
can(r_s, c_s) = 0;
else
% otherwise clear current pixel to avoid loops
can(r_s, c_s) = 0;
end
% add first found frontier (theortically heading away
% from starting position)
[front_r,front_c] = ind2sub(size(frontier),1);
canPos = frontier{front_r,front_c};
r_s = canPos(1);
c_s = canPos(2);
% clear frontier for next loop
frontier = {};
% set next search point
pixel = can(r_s,c_s);
else
% Add the current pixel as the first in the chain
curve{end+1}=[r_s c_s];
% clear current pixel to avoid loops
can(r_s, c_s) = 0;
% set next search point (goes back to orig)
pixel = can(r_m,c_m);
end
end
% add the curve that was just generated provided its longer
% than the min length
if length(curve) > minLength
curveCount = curveCount + 1;
collection{curveCount,1} = curve;
% reset curve
curve = {};
% repopulate repeated nodes if necessary
if (size(repeat,1) > 0) || (size(repeat,2) > 0)
for z = 1:sub2ind(size(repeat),size(repeat,1),size(repeat,2))
[rp_irow,rp_icol] = ind2sub(size(repeat),z);
rp_val = repeat{rp_irow,rp_icol};
can(rp_val(1,1),rp_val(1,2)) = 1;
end
repeat = {};
end
else
% reset curve array
curve = {};
% reset repeated array
repeat = {};
end
end
end
% assume that picture is empty of edges
isEmpty = true;
% Iterate through each cell
% Go Through each row
for r_m = 1:row
% Go through each element
for c_m = 1:col
if can(r_m,c_m)
% found an edge cell
isEmpty = false;
end
end
end
if isEmpty
isDone = true;
disp("Sketch Composition Complete")
end
end
% plot collection to see simulated sketch
if (size(collection,1) > 0) || (size(collection,2) > 0)
figure;
hold on;
for z = 1:sub2ind(size(collection),size(collection,1),size(collection,2))
% clear structure to hold path
clctn_path = {};
point = [];
% pull path from collection
[clctn_irow,clctn_icol] = ind2sub(size(collection),z);
% store path from collection
clctn_path = collection{clctn_irow,clctn_icol};
% need to modify the format of the data so that Matlab can plot it
for y = 1:sub2ind(size(clctn_path),size(clctn_path,1),size(clctn_path,2))
% pull point from path
[clctn_p_row,clctn_p_col] = ind2sub(size(clctn_path),y);
temp = clctn_path{clctn_p_row,clctn_p_col};
% store point in n x matrix
point(y,1) = temp(1,1);
point(y,2) = temp(1,2);
end
% plot simulated sketch
plot(point(:,1),point(:,2));
end
hold off;
disp("Simulated Plot Complete");
end
%% Generate Rapid Code
% An offset needs to be made to account for the gipper on the EOAT
MarkerHeight = 190;
% Set a constant for the height to draw on
% The board is 1/8 inch thick, 3.175 mm
HEIGHT = 3.18 + MarkerHeight;
ClearenceHeight = 10 + MarkerHeight;
% Set a scale for pixels per inch
% Needs to be mapped
PPI = 1035/533.4;
xOffset = 5;
yOffset = 5;
% Create a File ID
% "a" character is used to ensure it appends
% "w" ensure existing contents are discarded
fID = fopen("RapidCommand.txt", 'a');
fBeginID = fopen("RapidCommand.txt", 'w');
% Begin text file generation with necessary meta data
% Print Module
fprintf(fBeginID, "MODULE Module1\r\n");
fprintf(fID, "\r\n");
% Print Targets
% For each curve,
% move linear to just above the first point
% move down to first point
% For each other point in the curve
% move linear to that
% when at last point in curve lift up linear
targCount = 1;
ThinCount = 1;
ThinThresh = 10;
for prow = 1:length(collection)
tPath = collection{prow};
% create the offset starting point
Chords = tPath{1};
xCoord = Chords(1);
yCoord = Chords(2);
% Map the coordinates
xCoord = pixelToPosition(xCoord, PPI, xOffset);
yCoord = pixelToPosition(yCoord, PPI, yOffset);
zCoord = ClearenceHeight;
ID = int2str(targCount) + "0";
fprintf(fID, makeTargetCode(ID, xCoord, yCoord, zCoord));
targCount = targCount + 1;
% Make the targets for the rest of the path
for targ = 1:length(tPath)
Chords = tPath{targ};
xCoord = Chords(1);
yCoord = Chords(2);
% Map the coordinates
xCoord = pixelToPosition(xCoord, PPI, xOffset);
yCoord = pixelToPosition(yCoord, PPI, yOffset);
zCoord = HEIGHT;
ID = int2str(targCount) + "0";
fprintf(fID, makeTargetCode(ID, xCoord, yCoord, zCoord));
targCount = targCount + 1;
end
% create the offset ending point
Chords = tPath{end};
xCoord = Chords(1);
yCoord = Chords(2);
LastX = xCoord;
LastY = yCoord;
% Map the coordinates
xCoord = pixelToPosition(xCoord, PPI, xOffset);
yCoord = pixelToPosition(yCoord, PPI, yOffset);
zCoord = ClearenceHeight;
ID = int2str(targCount) + "0";
fprintf(fID, makeTargetCode(ID, xCoord, yCoord, zCoord));
targCount = targCount + 1;
end
% Print Main
fprintf(fID, "\r\n");
fprintf(fID, "PROC main()\r\n");
% itterate through the list of paths
for prow = 1:length(collection)
fprintf(fID, " Path_" + int2str(prow) + "0;\r\n");
end
fprintf(fID, "ENDPROC\r\n");
% Print Paths
% itterate through each path
% within each path, itterate through each target
% figure amount of local curve and map to z value
% print moveL command
fprintf(fID, "\r\n");
pTargCount = 1;
for prow = 1:length(collection)
tPath = collection{prow};
fprintf(fID, "PROC Path_" + int2str(prow) + "0()\r\n");
% insert starting offset Point
TargetID = int2str(pTargCount) + "0";
vel = "v50";
z = "fine";
tool = "tool0";
workobj = "Workobject_1";
fprintf(fID, makeMoveL(TargetID, vel, z, tool, workobj));
pTargCount = pTargCount + 1;
% insert the path points
for pTarg = 1:length(tPath)
TargetID = int2str(pTargCount) + "0";
vel = "v50";
z = "z1";
tool = "tool0";
workobj = "Workobject_1";
fprintf(fID, makeMoveL(TargetID, vel, z, tool, workobj));
pTargCount = pTargCount + 1;
end
% insert ending offset Point
TargetID = int2str(pTargCount) + "0";
vel = "v50";
z = "fine";
tool = "tool0";
workobj = "Workobject_1";
fprintf(fID, makeMoveL(TargetID, vel, z, tool, workobj));
pTargCount = pTargCount + 1;
fprintf(fID, "ENDPROC\r\n");
fprintf(fID, "\r\n");
end
% Print ENDMODULE
fprintf(fID, "ENDMODULE\r\n");
% Close the file now that we are done
fclose(fID);
disp("RAPID Code Generation Complete");