3 min read

KSR10 Robotic arm programmed to follow big red squares using OpenCV

Hi, there. I know it has been a long time. But no worries I am back with a small project. I got my hands on a KSR10. The KSR10 is a simple robotic arm that any 13 year old (or 13 year old at heart) can put together. The great part of it though is even though the manual says it has no support 64-bit computers you can easily find a Python library that does. Now you know all know how much I love writing in Python. Even a broken down computer and coming home tired from work could not stop me work on the project!

I strapped a simple web-cam on the robotic arm to make it 100 times cooler. Now the robotic arm follows faces and big red squares!! I used the OpenCV library for the project. Below you can find a nice little video;

The library for the KSR10 could be found below;

ksr10.py

# this file contains the base control set for the KSR10 Robot arm
#
# Written by Niels Bosboom, n.bosboom@gmail.com, july 2012
# (based on ideas provided by http://www.aonsquared.co.uk)

# imports
import usb.core
import time

class ksr10_class:

    def __init__(self):
        self.dev = usb.core.find(idVendor=0x1267, idProduct=0x0000)
        if self.dev is None:
            print "Unable to initialize ksr10..."
        # set status to stop all movement and dim lights        
        self.status = dict()
        self.status["lights"] = 0
        self.stop()

    def sendcommand(self):
        # build command from status
        byte1 = self.status["shoulder"]*64 + self.status["elbow"]*16 + self.status["wrist"]*4 + self.status["grip"]        
        # build command        
        comm_bytes = (byte1, self.status["base"], self.status["lights"])
        # print "commando : ",comm_bytes
        # send command to device
        try:
            self.dev.ctrl_transfer(0x40, 6, 0x100, 0, comm_bytes, 1000)
        except AttributeError:
            print "KSR10 is not connected..."

    def lights(self):
        # swap lights
        if (self.status["lights"]== 0):
            self.status["lights"] = 1
        else:
            self.status["lights"] = 0
        #send command
        self.sendcommand()

    def move(self,part,direction):
        #determine which part to move:        

        # determine direction
        if (direction=='right') or (direction=='up') or (direction=='close'):
            dir_command = 1
        elif (direction=='left') or (direction=='down') or (direction=='open'):
            dir_command = 2
        else:
            dir_command = 0        
        self.status[part] = dir_command

        # send command
        self.sendcommand()

    def stop(self):
        # stop all movement and dim lights        
        self.status["shoulder"] = 0
        self.status["base"] = 0
        self.status["elbow"] = 0
        self.status["wrist"] = 0
        self.status["grip"] = 0
        # send command
        self.sendcommand()

if __name__ == '__main__':
    print "No main in this module"

And next is our neat little code that actually does the image processing;

import cv
import ksr10
import time

def find_car(image):

	size = cv.GetSize(image)

	#prepare memory

	car = cv.CreateImage(size, 8, 1)

	red = cv.CreateImage(size, 8, 1)

	hsv = cv.CreateImage(size, 8, 3)

	sat = cv.CreateImage(size, 8, 1)

	#split image into hsv, grab the sat

	cv.CvtColor(image, hsv, cv.CV_BGR2HSV)

	cv.Split(hsv, None, sat, None, None)

	#split image into rgb

	cv.Split(image, None, None, red, None)

	#find the car by looking for red, with high saturation

	cv.Threshold(red, red, 128, 255, cv.CV_THRESH_BINARY)

	cv.Threshold(sat, sat, 128, 255, cv.CV_THRESH_BINARY)

	#AND the two thresholds, finding the car

	cv.Mul(red, sat, car)

	#remove noise, highlighting the car

	cv.Erode(car, car, iterations=6)

	cv.Dilate(car, car, iterations=6)

	storage = cv.CreateMemStorage(0)

	obj = cv.FindContours(car, storage, cv.CV_RETR_CCOMP, cv.CV_CHAIN_APPROX_SIMPLE)

	cv.ShowImage('Countour Vision', car)

	if not obj:

	return(0, 0, 0, 0)

	else:

	return cv.BoundingRect(obj)

points = []

capture = cv.CaptureFromCAM(0)

if not capture:

print "Error opening capture device"

sys.exit(1)

cv.SetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_WIDTH, 640)

cv.SetCaptureProperty(capture, cv.CV_CAP_PROP_FRAME_HEIGHT, 480)

# create object

ksr = ksr10.ksr10_class()

# turn on lights

#ksr.lights()

prevx = 0

while 1:

	original = cv.QueryFrame(capture)

	car_rect = find_car(original)

	x,y,width,height = car_rect

	print car_rect

	if width>50 :

	if ((0<x)and(x 5 and abs(points[-1][1] - middle[1]) > 10:

	points.append(middle)

	cv.Rectangle(original,

	(car_rect[0], car_rect[1]),

	(car_rect[0] + car_rect[2], car_rect[1] + car_rect[3]),

	(255, 0, 0),

	1,

	8,

	0)

	for point in points:

	cv.Circle(original,

	point,

	1,

	(0, 0, 255),

	-1,

	8,

	0)

cv.ShowImage('Computer Vision', original)

k = cv.WaitKey(27)

Aaand that is how it is done!

I would like to thank Niels Bosboom for making my life easier by writing the robotic arm library.

So, have fun and code on!