Add consistent error and info messages, tweak image blurring. Remove penny requirement.
This commit is contained in:
parent
4ca4d0c3cd
commit
4eac873412
Binary file not shown.
@ -10,15 +10,21 @@ pwm = gpio.PWM(13, 100)
|
|||||||
pwm.start(13)
|
pwm.start(13)
|
||||||
verbose = True
|
verbose = True
|
||||||
|
|
||||||
print("Initializing Grbl...")
|
print("[ INFO ] Initializing Grbl...")
|
||||||
ser.write(b'\r\n\r\n')
|
ser.write(b'\r\n\r\n')
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
ser.write(b'$RST=#\n')
|
ser.write(b'$RST=#\n')
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
ser.flushInput()
|
ser.flushInput()
|
||||||
|
print("[ INFO ] Grbl is ready.")
|
||||||
|
|
||||||
def goToBin(bin):
|
def goToBin(bin):
|
||||||
|
print("[ INFO ] Delivering item to bin: " + str(bin))
|
||||||
adjustedBin = math.floor(bin / 2)
|
adjustedBin = math.floor(bin / 2)
|
||||||
|
if adjustedBin > 11:
|
||||||
|
print("[ INFO ] All bins full! Using overflow bin.")
|
||||||
|
bin = 0;
|
||||||
|
adjustedBin = 0;
|
||||||
distance = adjustedBin * 18
|
distance = adjustedBin * 18
|
||||||
delay = 0.5 + 0.93 * adjustedBin
|
delay = 0.5 + 0.93 * adjustedBin
|
||||||
command = 'G0 X-'
|
command = 'G0 X-'
|
||||||
@ -26,37 +32,40 @@ def goToBin(bin):
|
|||||||
command += '\n'
|
command += '\n'
|
||||||
ser.write(b'$X\n')
|
ser.write(b'$X\n')
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
print(command)
|
print("[ INFO ] Sending command to Grbl: " + command)
|
||||||
ser.write(command.encode('utf-8'))
|
ser.write(command.encode('utf-8'))
|
||||||
# s.write("$C\n")
|
# s.write("$C\n")
|
||||||
while True:
|
while True:
|
||||||
grbl_out = str(ser.readline().strip()) # Wait for grbl response with carriage return
|
grbl_out = str(ser.readline().strip()) # Wait for grbl response with carriage return
|
||||||
print(grbl_out.find('error'))
|
print(grbl_out.find('error'))
|
||||||
if int(grbl_out.find('error')) >= 0 :
|
if int(grbl_out.find('error')) >= 0 :
|
||||||
print("REC:",grbl_out)
|
print("[ EXIT ] Grbl reported an error.")
|
||||||
print(" Grbl reported error!")
|
|
||||||
quit()
|
quit()
|
||||||
elif int(grbl_out.find('ok')) >= 0 :
|
elif int(grbl_out.find('ok')) >= 0 :
|
||||||
if verbose: print('REC:',grbl_out)
|
if verbose: print('[ INFO ] Grbl message: ',grbl_out)
|
||||||
break
|
break
|
||||||
|
print("[ INFO ] Waiting for " + str(delay) + " seconds.")
|
||||||
time.sleep(delay)
|
time.sleep(delay)
|
||||||
if bin % 2 == 0: # tilt to left
|
if bin % 2 == 0: # tilt to left
|
||||||
|
print("[ INFO ] Titling motor to left side.")
|
||||||
pwm.ChangeDutyCycle(5)
|
pwm.ChangeDutyCycle(5)
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
pwm.ChangeDutyCycle(14)
|
pwm.ChangeDutyCycle(14)
|
||||||
else:
|
else:
|
||||||
|
print("[ INFO ] Titling motor to right side.")
|
||||||
pwm.ChangeDutyCycle(25)
|
pwm.ChangeDutyCycle(25)
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
pwm.ChangeDutyCycle(13)
|
pwm.ChangeDutyCycle(13)
|
||||||
time.sleep(1)
|
time.sleep(1)
|
||||||
|
print("[ INFO ] Sending command to Grbl: G0 X0")
|
||||||
ser.write(b'G0 X0\n')
|
ser.write(b'G0 X0\n')
|
||||||
while True:
|
while True:
|
||||||
grbl_out = str(ser.readline().strip()) # Wait for grbl response with carriage return
|
grbl_out = str(ser.readline().strip()) # Wait for grbl response with carriage return
|
||||||
if int(grbl_out.find('error')) >= 0 :
|
if int(grbl_out.find('error')) >= 0 :
|
||||||
print("REC:",grbl_out)
|
print("[ EXIT ] Grbl reported an error.")
|
||||||
print(" Grbl reported error!")
|
|
||||||
quit()
|
quit()
|
||||||
elif int(grbl_out.find('ok')) >= 0 :
|
elif int(grbl_out.find('ok')) >= 0 :
|
||||||
if verbose: print('REC:',grbl_out)
|
if verbose: print('[ INFO ] Grbl message: ',grbl_out)
|
||||||
break
|
break
|
||||||
|
print("[ INFO ] Waiting for " + str(delay) + " seconds.")
|
||||||
time.sleep(delay)
|
time.sleep(delay)
|
@ -4,4 +4,4 @@ pixels = neopixel.NeoPixel(board.D18, 24)
|
|||||||
def ledOff():
|
def ledOff():
|
||||||
pixels.fill((0,0,0))
|
pixels.fill((0,0,0))
|
||||||
def ledOn():
|
def ledOn():
|
||||||
pixels.fill((50,50,50))
|
pixels.fill((0,0,0))
|
41
detect.py
41
detect.py
@ -98,7 +98,7 @@ def detect(calibration_width, img_file, show, quick):
|
|||||||
cv2.waitKey(0)
|
cv2.waitKey(0)
|
||||||
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
|
||||||
gray = cv2.GaussianBlur(gray, (7, 7), 0)
|
gray = cv2.GaussianBlur(gray, (7, 7), 0)
|
||||||
|
gray = cv2.GaussianBlur(gray, (7, 7), 0)
|
||||||
# perform edge detection, then perform a dilation + erosion to
|
# perform edge detection, then perform a dilation + erosion to
|
||||||
# close gaps in between object edges
|
# close gaps in between object edges
|
||||||
edged = cv2.Canny(gray, 50, 100)
|
edged = cv2.Canny(gray, 50, 100)
|
||||||
@ -107,6 +107,8 @@ def detect(calibration_width, img_file, show, quick):
|
|||||||
edged = cv2.dilate(edged, None, iterations=1)
|
edged = cv2.dilate(edged, None, iterations=1)
|
||||||
edged = cv2.erode(edged, None, iterations=1)
|
edged = cv2.erode(edged, None, iterations=1)
|
||||||
edged = cv2.dilate(edged, None, iterations=1)
|
edged = cv2.dilate(edged, None, iterations=1)
|
||||||
|
#edged = cv2.erode(edged, None, iterations=1)
|
||||||
|
#edged = cv2.dilate(edged, None, iterations=1)
|
||||||
if show and not quick:
|
if show and not quick:
|
||||||
cv2.imshow("Item Sorter", edged)
|
cv2.imshow("Item Sorter", edged)
|
||||||
cv2.waitKey(0)
|
cv2.waitKey(0)
|
||||||
@ -122,6 +124,7 @@ def detect(calibration_width, img_file, show, quick):
|
|||||||
num = 0
|
num = 0
|
||||||
|
|
||||||
# Calibration loop
|
# Calibration loop
|
||||||
|
"""
|
||||||
for c in cnts:
|
for c in cnts:
|
||||||
# if the contour is not sufficiently large, ignore it
|
# if the contour is not sufficiently large, ignore it
|
||||||
if cv2.contourArea(c) < 100:
|
if cv2.contourArea(c) < 100:
|
||||||
@ -170,8 +173,8 @@ def detect(calibration_width, img_file, show, quick):
|
|||||||
# and near(mean_val[0], 63, 40) is True and near(mean_val[1], 108, 40) is True and near(mean_val[2], 104, 40) is True:
|
# and near(mean_val[0], 63, 40) is True and near(mean_val[1], 108, 40) is True and near(mean_val[2], 104, 40) is True:
|
||||||
pixelsPerMetric = smaller(dA, dB) / calibration_width
|
pixelsPerMetric = smaller(dA, dB) / calibration_width
|
||||||
continue
|
continue
|
||||||
|
"""
|
||||||
#pixelsPerMetric = 25
|
pixelsPerMetric = 25
|
||||||
orig = image.copy()
|
orig = image.copy()
|
||||||
objtype = "Unknown"
|
objtype = "Unknown"
|
||||||
objname = ""
|
objname = ""
|
||||||
@ -181,42 +184,22 @@ def detect(calibration_width, img_file, show, quick):
|
|||||||
num += 1
|
num += 1
|
||||||
# if the contour is not sufficiently large, ignore it
|
# if the contour is not sufficiently large, ignore it
|
||||||
#pixelsPerMetric = 75
|
#pixelsPerMetric = 75
|
||||||
if cv2.contourArea(c) < 100 or pixelsPerMetric is None:
|
if cv2.contourArea(c) < 300 or pixelsPerMetric is None:
|
||||||
continue
|
continue
|
||||||
# compute the rotated bounding box of the contour
|
# compute the rotated bounding box of the contour
|
||||||
|
|
||||||
box = cv2.minAreaRect(c)
|
box = cv2.minAreaRect(c)
|
||||||
box = cv2.cv.BoxPoints(box) if imutils.is_cv2() else cv2.boxPoints(box)
|
box = cv2.cv.BoxPoints(box) if imutils.is_cv2() else cv2.boxPoints(box)
|
||||||
box = np.array(box, dtype="int")
|
box = np.array(box, dtype="int")
|
||||||
|
|
||||||
# order the points in the contour such that they appear
|
|
||||||
# in top-left, top-right, bottom-right, and bottom-left
|
|
||||||
# order, then draw the outline of the rotated bounding
|
|
||||||
# box
|
|
||||||
#box = perspective.order_points(box)
|
|
||||||
|
|
||||||
# loop over the original points and draw them
|
|
||||||
# for (x, y) in box:
|
|
||||||
#cv2.circle(orig, (int(x), int(y)), 5, (0, 0, 255), -1)
|
|
||||||
|
|
||||||
# unpack the ordered bounding box, then compute the midpoint
|
# unpack the ordered bounding box, then compute the midpoint
|
||||||
# between the top-left and top-right coordinates, followed by
|
# between the top-left and top-right coordinates, followed by
|
||||||
# the midpoint between bottom-left and bottom-right coordinates
|
# the midpoint between bottom-left and bottom-right coordinates
|
||||||
(tl, tr, br, bl) = box
|
(tl, tr, br, bl) = box
|
||||||
(tltrX, tltrY) = midpoint(tl, tr)
|
(tltrX, tltrY) = midpoint(tl, tr)
|
||||||
(blbrX, blbrY) = midpoint(bl, br)
|
(blbrX, blbrY) = midpoint(bl, br)
|
||||||
|
|
||||||
# compute the midpoint between the top-left and top-right points,
|
# compute the midpoint between the top-left and top-right points,
|
||||||
# followed by the midpoint between the top-right and bottom-right
|
# followed by the midpoint between the top-right and bottom-right
|
||||||
(tlblX, tlblY) = midpoint(tl, bl)
|
(tlblX, tlblY) = midpoint(tl, bl)
|
||||||
(trbrX, trbrY) = midpoint(tr, br)
|
(trbrX, trbrY) = midpoint(tr, br)
|
||||||
# draw the midpoints on the image
|
|
||||||
#cv2.circle(orig, (int(tltrX), int(tltrY)), 5, (255, 0, 0), -1)
|
|
||||||
#cv2.circle(orig, (int(blbrX), int(blbrY)), 5, (255, 0, 0), -1)
|
|
||||||
#cv2.circle(orig, (int(tlblX), int(tlblY)), 5, (255, 0, 0), -1)
|
|
||||||
#cv2.circle(orig, (int(trbrX), int(trbrY)), 5, (255, 0, 0), -1)
|
|
||||||
|
|
||||||
# draw lines between the midpoints
|
|
||||||
# compute the Euclidean distance between the midpoints
|
# compute the Euclidean distance between the midpoints
|
||||||
dA = np.linalg.norm(np.array((tltrX, tltrY, 0)) -
|
dA = np.linalg.norm(np.array((tltrX, tltrY, 0)) -
|
||||||
np.array((blbrX, blbrY, 0)))
|
np.array((blbrX, blbrY, 0)))
|
||||||
@ -255,7 +238,7 @@ def detect(calibration_width, img_file, show, quick):
|
|||||||
if circular and itemwr == 0.75:
|
if circular and itemwr == 0.75:
|
||||||
objtype = "Penny"
|
objtype = "Penny"
|
||||||
iteml = 0
|
iteml = 0
|
||||||
else:
|
"""else:
|
||||||
|
|
||||||
if circular and near(radius * 2 / pixelsPerMetric, 0.4, 0.03):
|
if circular and near(radius * 2 / pixelsPerMetric, 0.4, 0.03):
|
||||||
# Keps nut or spacer
|
# Keps nut or spacer
|
||||||
@ -298,6 +281,7 @@ def detect(calibration_width, img_file, show, quick):
|
|||||||
if itemhr == 0.1875 and rectangular:
|
if itemhr == 0.1875 and rectangular:
|
||||||
objtype = "Axle"
|
objtype = "Axle"
|
||||||
iteml = (radius * 2 / pixelsPerMetric + itemw) / 2
|
iteml = (radius * 2 / pixelsPerMetric + itemw) / 2
|
||||||
|
"""
|
||||||
rows, cols = orig.shape[:2]
|
rows, cols = orig.shape[:2]
|
||||||
[vx, vy, xx, yy] = cv2.fitLine(c, cv2.DIST_L2, 0, 0.01, 0.01)
|
[vx, vy, xx, yy] = cv2.fitLine(c, cv2.DIST_L2, 0, 0.01, 0.01)
|
||||||
lefty = int((-xx*vy/vx) + yy)
|
lefty = int((-xx*vy/vx) + yy)
|
||||||
@ -337,7 +321,7 @@ def detect(calibration_width, img_file, show, quick):
|
|||||||
0.6, (50, 50, 220), 2)
|
0.6, (50, 50, 220), 2)
|
||||||
output = ""
|
output = ""
|
||||||
objname = objtype;
|
objname = objtype;
|
||||||
|
"""
|
||||||
if objtype == "Screw" or objtype == "Standoff":
|
if objtype == "Screw" or objtype == "Standoff":
|
||||||
output = str(iteml) + "in"
|
output = str(iteml) + "in"
|
||||||
objname += str(iteml)
|
objname += str(iteml)
|
||||||
@ -345,6 +329,7 @@ def detect(calibration_width, img_file, show, quick):
|
|||||||
output = "{:.2f}in".format(iteml)
|
output = "{:.2f}in".format(iteml)
|
||||||
objname += str(itemwr)
|
objname += str(itemwr)
|
||||||
#print(objname)
|
#print(objname)
|
||||||
|
"""
|
||||||
list.append(objname)
|
list.append(objname)
|
||||||
if circular:
|
if circular:
|
||||||
cv2.putText(orig, output, # print data
|
cv2.putText(orig, output, # print data
|
||||||
@ -385,8 +370,8 @@ def magicSort(contour):
|
|||||||
name += ", " + str(abs(int(humoments[i][0])))
|
name += ", " + str(abs(int(humoments[i][0])))
|
||||||
#magicNumber2 += abs(humoments[i][0])
|
#magicNumber2 += abs(humoments[i][0])
|
||||||
#magicNumber += humoments[i][0]
|
#magicNumber += humoments[i][0]
|
||||||
print(str(humoments))
|
#print(str(humoments))
|
||||||
#print(magicNumber)
|
#print(magicNumber)
|
||||||
#name = "Unknown: " + str(int(magicNumber1)) + ", " + str(int(magicNumber2))
|
#name = "Unknown: " + str(int(magicNumber1)) + ", " + str(int(magicNumber2))
|
||||||
print(name)
|
#print(name)
|
||||||
return name
|
return name
|
@ -15,13 +15,13 @@ while True:
|
|||||||
data = s.recv(1024)
|
data = s.recv(1024)
|
||||||
#control_pixel.ledOn()
|
#control_pixel.ledOn()
|
||||||
if not data: break
|
if not data: break
|
||||||
print("Found "+str(data))
|
print("[ INFO ] Item name: "+ str(data)[2:len(str(data))-1])
|
||||||
selectedBin = sort.sort(str(data)[2:len(str(data))-1])
|
selectedBin = sort.sort(str(data)[2:len(str(data))-1])
|
||||||
control_pixel.ledOff()
|
control_pixel.ledOff()
|
||||||
control_motor.goToBin(selectedBin)
|
control_motor.goToBin(selectedBin)
|
||||||
control_pixel.ledOn()
|
control_pixel.ledOn()
|
||||||
s.sendall(b'Continue')
|
s.sendall(b'Continue')
|
||||||
except socket.error:
|
except socket.error:
|
||||||
print("Error Occured.")
|
print("[ EXIT ] Socket connection error.")
|
||||||
break
|
break
|
||||||
s.close()
|
s.close()
|
@ -30,11 +30,11 @@ def go():
|
|||||||
#control_motor.goToBin(selectedBin)
|
#control_motor.goToBin(selectedBin)
|
||||||
|
|
||||||
def sendString(string):
|
def sendString(string):
|
||||||
print("Found " + string)
|
print("[ INFO ] Item found: " + string)
|
||||||
try:
|
try:
|
||||||
conn.sendall(string.encode('utf-8'))
|
conn.sendall(string.encode('utf-8'))
|
||||||
except socket.error:
|
except socket.error:
|
||||||
print("Error Occured.")
|
print("[ EXIT ] Socket connection error.")
|
||||||
|
|
||||||
|
|
||||||
if not video:
|
if not video:
|
||||||
@ -49,22 +49,22 @@ else :
|
|||||||
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
|
||||||
#s.setsockopt(s, socket.SOL_SOCKET, socket.SO_REUSEADDR)
|
#s.setsockopt(s, socket.SOL_SOCKET, socket.SO_REUSEADDR)
|
||||||
s.bind((host, port))
|
s.bind((host, port))
|
||||||
print("waiting for connection")
|
print("[ INFO ] TCP stream initialized. Waiting for client...")
|
||||||
s.listen(1)
|
s.listen(1)
|
||||||
conn, addr = s.accept()
|
conn, addr = s.accept()
|
||||||
print('Connected to', addr)
|
print('[ INFO ] Connected to ', addr)
|
||||||
time.sleep(2)
|
time.sleep(2)
|
||||||
waitForPi = True
|
waitForPi = True
|
||||||
while waitForPi is True:
|
while waitForPi is True:
|
||||||
try:
|
try:
|
||||||
print("waiting for data")
|
print("[ INFO ] Waiting for confirmation message.")
|
||||||
data = conn.recv(1024)
|
data = conn.recv(1024)
|
||||||
if not data: break
|
if not data: break
|
||||||
encoding = 'utf-8'
|
encoding = 'utf-8'
|
||||||
print ("Client: "+str(data))
|
print ("[ INFO ] Message recieved: "+str(data))
|
||||||
waitForPi = False
|
waitForPi = False
|
||||||
except socket.error:
|
except socket.error:
|
||||||
print("Error Occured.")
|
print("[ EXIT ] Socket connection error.")
|
||||||
break
|
break
|
||||||
# server command for imx135 camera ./video2stdout | gst-launch-1.0 -v fdsrc ! h264parse ! rtph264pay config-interval=1 pt=96 ! gdppay ! tcpserversink host=192.168.43.152 port=5001
|
# server command for imx135 camera ./video2stdout | gst-launch-1.0 -v fdsrc ! h264parse ! rtph264pay config-interval=1 pt=96 ! gdppay ! tcpserversink host=192.168.43.152 port=5001
|
||||||
# server command for udp: ./video2stdout | gst-launch-1.0 -v fdsrc ! h264parse ! rtph264pay config-interval=10 pt=96 ! udpsink host=192.168.43.40 port=9000
|
# server command for udp: ./video2stdout | gst-launch-1.0 -v fdsrc ! h264parse ! rtph264pay config-interval=10 pt=96 ! udpsink host=192.168.43.40 port=9000
|
||||||
@ -75,7 +75,7 @@ else :
|
|||||||
ret = capture.grab()
|
ret = capture.grab()
|
||||||
x+=1
|
x+=1
|
||||||
if not ret:
|
if not ret:
|
||||||
print('empty frame')
|
print('[ EXIT ] Empty frame received.')
|
||||||
break
|
break
|
||||||
#print('frame')
|
#print('frame')
|
||||||
if x > 1:
|
if x > 1:
|
||||||
@ -84,13 +84,13 @@ else :
|
|||||||
items,output = detect.detect(calibration_width, frame, True, True)
|
items,output = detect.detect(calibration_width, frame, True, True)
|
||||||
cv2.imshow('Item Sorter', output)
|
cv2.imshow('Item Sorter', output)
|
||||||
x = 0
|
x = 0
|
||||||
if "Penny" in items and len(items) > 1:
|
if len(items) > 0:
|
||||||
items.remove("Penny")
|
#items.remove("Penny")
|
||||||
itema = items[0]
|
itema = items[0]
|
||||||
valid = True
|
valid = True
|
||||||
for item in items:
|
for item in items:
|
||||||
if item != itema:
|
if item != itema:
|
||||||
print("Too many items!")
|
print("[ INFO ] More than one object present.")
|
||||||
valid = False
|
valid = False
|
||||||
break
|
break
|
||||||
if valid:
|
if valid:
|
||||||
@ -113,10 +113,12 @@ else :
|
|||||||
waitForPi = False
|
waitForPi = False
|
||||||
capture = cv2.VideoCapture('udpsrc port=9000 caps="application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264" ! rtph264depay ! avdec_h264 ! videoconvert ! appsink sync=false', cv2.CAP_GSTREAMER)
|
capture = cv2.VideoCapture('udpsrc port=9000 caps="application/x-rtp, media=(string)video, clock-rate=(int)90000, encoding-name=(string)H264" ! rtph264depay ! avdec_h264 ! videoconvert ! appsink sync=false', cv2.CAP_GSTREAMER)
|
||||||
except socket.error:
|
except socket.error:
|
||||||
print("Error Occured.")
|
print("[ EXIT ] Socket connection error.")
|
||||||
break
|
break
|
||||||
|
|
||||||
if cv2.waitKey(1)&0xFF == ord('q'):
|
if cv2.waitKey(1)&0xFF == ord('q'):
|
||||||
|
print("[ EXIT ] Shutting down.")
|
||||||
|
s.shutdown(1)
|
||||||
s.close()
|
s.close()
|
||||||
break
|
break
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user