diff --git a/.DS_Store b/.DS_Store new file mode 100644 index 0000000..db9d9e1 Binary files /dev/null and b/.DS_Store differ diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ba28150 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +images/ \ No newline at end of file diff --git a/README.md b/README.md index da34c65..5baaef4 100644 --- a/README.md +++ b/README.md @@ -1,2 +1,7 @@ # RaspberryDrive Use a Raspberry Pi 3 to drive an RC Car + +## Libraries +Python 2 +SimpleCV +PiCamera \ No newline at end of file diff --git a/models/decide.py b/__init__.py similarity index 100% rename from models/decide.py rename to __init__.py diff --git a/analyzeLine.pyc b/analyzeLine.pyc new file mode 100644 index 0000000..1175d20 Binary files /dev/null and b/analyzeLine.pyc differ diff --git a/analyzeblob.py b/analyzeblob.py new file mode 100644 index 0000000..695a59c --- /dev/null +++ b/analyzeblob.py @@ -0,0 +1,49 @@ +import SimpleCV +import cv2 +import time + +class AnalyzeBlob(object): + + def __init__(self,img,blob): + self.vertical_boundary = 0.3 + self.width_boundary = 0.4 + self.img = img + self.blob = blob + self.angle_to_turn = 30 + + def isBlobBlocking(self): + if (self.__heightBelowThreshold() and self.__widthSufficientToBlock()): + return True + + def isBlobDetectedOnLeft(self): + if (self.__anglingFromLeft() and self.__largeObjectStartingNearLeft()): + return True + + def isBlobDetectedOnRight(self): + if (self.__anglingFromRight() and self.__largeObjectStartingNearRight()): + return True + + def __anglingFromRight(self): + return self.blob.angle() < self.angle_to_turn + + def __largeObjectStartingNearRight(self): + return (self.blob.maxX() > self.img.size()[0] * 0.95) and (self.blob.width() > self.img.size()[0] * 0.8) and (self.blob.maxY() > self.img.size()[1] * 0.3) + + def isBlobBlockingMoreRight(self): + self.blob.angle() > 0 + + def __anglingFromLeft(self): + print self.blob.angle() + return self.blob.angle() > 90 - self.angle_to_turn + + def __largeObjectStartingNearLeft(self): + return (self.blob.maxX() < self.img.size()[0] * 0.05) and (self.blob.width() > self.img.size()[0] * 0.8) and (self.blob.maxY() > self.img.size()[1] * 0.3) + + def __heightBelowThreshold(self): + return self.blob.maxY() > self.img.size()[1] * self.vertical_boundary + + def __widthSufficientToBlock(self): + print self.blob.width() > self.img.size()[0] * self.width_boundary + return self.blob.width() > self.img.size()[0] * self.width_boundary + + diff --git a/analyzeimage.py b/analyzeimage.py new file mode 100644 index 0000000..c481fff --- /dev/null +++ b/analyzeimage.py @@ -0,0 +1,63 @@ +import SimpleCV +import cv2 +import time +from analyzeblob import * +from car_maneuvers import * +from PIL import Image + +class AnalyzeImage(object): + + def __init__(self, image,connection): + self.default_command = "stop" + self.scvImg = SimpleCV.Image(image) + self.segmented_black_white = self.scvImg.stretch(160,161) + self.black_white_blobs = self.segmented_black_white.findBlobs(minsize=100) + self.car = CarManeuvers(connection) + + def runBlobFinder(self): + if (self.black_white_blobs and (len(self.black_white_blobs) > 0)): + self.analyzeBlobs() + else: + self.car.forward() + # print x + # print blob + + def analyzeBlobs(self): + blobs = self.scvImg.findBlobs(minsize = 100) + # if blobs: + # for blob in blobs: + # if blob.area() > 100: + # blob.draw(color=(128,0,0)) + # self.scvImg.show() + # self.scvImg.show() + # time.sleep(2) + #check if blocked + for blob in self.black_white_blobs: + print blob + analyzed_blob = AnalyzeBlob(self.scvImg,blob) + + if analyzed_blob.isBlobBlocking(): + print "true" + if analyzed_blob.isBlobBlockingMoreRight(): + self.car.back_up_and_then_drive_left() + else: + self.car.back_up_and_then_drive_right() + return + + elif analyzed_blob.isBlobDetectedOnRight(): + # if analyzed_blob.blockedOnRight(): + self.car.left() + return + elif analyzed_blob.isBlobDetectedOnLeft(): + self.car.right() + return + #otherwise go forward + self.car.forward() + +# detect blobs +# if blobs +# check left and check rightt +# is blocking? +# back up +# else +# turn (in correct direction) diff --git a/analyzeimage.pyc b/analyzeimage.pyc new file mode 100644 index 0000000..adeb66c Binary files /dev/null and b/analyzeimage.pyc differ diff --git a/car_maneuvers.py b/car_maneuvers.py new file mode 100644 index 0000000..da554ec --- /dev/null +++ b/car_maneuvers.py @@ -0,0 +1,29 @@ +from connect import * + +class CarManeuvers(object): + + def __init__(self,connection): + self.connection = connection + + def forward(self): + print "executing forward" + send_command(self.connection, "forward", "0.5") + + def right(self): + print "executing right" + send_command(self.connection, "right", "0.5") + + def left(self): + print "executing left" + send_command(self.connection, "left", "0.5") + + def back_up_then_right(self): + print "executing back up and drive right" + send_command(self.connection, "backwards", "0.75") + send_command(self.connection, "right", "0.5") + + def back_up_then_left(self): + print "executing back up and drive left" + send_command(self.connection, "backwards", "0.75") + send_command(self.connection, "left", "0.5") + diff --git a/connect.py b/connect.py new file mode 100644 index 0000000..18ceda9 --- /dev/null +++ b/connect.py @@ -0,0 +1,24 @@ +import socket + +def new_connection(): + host = '192.168.2.4' + port = 9000 + s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) + s.connect((host, port)) + return s; + +def send_command(connection,command,time): + connection.send('' + command + ' ; ' + time) + return receive_confirmation(connection) + +def receive_confirmation(connection): + received = connection.recv(20) + return received; + +def send_end_connection(connection): + connection.send('quit') + return + +# example: +# con = new_conntection +# send_command(con,"forward",0.5) diff --git a/connect.pyc b/connect.pyc new file mode 100644 index 0000000..1e7ac6c Binary files /dev/null and b/connect.pyc differ diff --git a/controllers/.DS_Store b/controllers/.DS_Store new file mode 100644 index 0000000..5008ddf Binary files /dev/null and b/controllers/.DS_Store differ diff --git a/controllers/camera_thread.pyc b/controllers/camera_thread.pyc new file mode 100644 index 0000000..209c100 Binary files /dev/null and b/controllers/camera_thread.pyc differ diff --git a/controllers/controller.py b/controllers/controller.py index e69de29..930ae73 100644 --- a/controllers/controller.py +++ b/controllers/controller.py @@ -0,0 +1,58 @@ +import os +import sys +from time import sleep +sys.path.insert(0, os.getcwd()) +import analyzeblob +import analyzeimage +from analyzeimage import * +from analyzeblob import * +from get_images_from_pi import get_image, valid_image +from connect import new_connection, send_command, receive_confirmation,send_end_connection +from start_camera import start_camera +from start_server import start_server +import threading + +def start_server_thread(): + server_thread = threading.Thread(target=start_server) + server_thread.start() + +def start_camera_thread(): + camera_thread = threading.Thread(target=start_camera) + camera_thread.start() + +def start_all(): + start_server_thread() + start_camera_thread() + sleep(7) + s = new_connection() + return s + #start the server listening on contr pi + #start the camera taking pictures on camera pi + # Sleep to make sure server connects + #start the server connection on this current server + +def end_all(server): + send_end_connection(server) + server.close() + #End-all + #Camera exits automatically automatically + #Close the Server Connection on the Pi-Controller End + #Kill the server listening process + +def run(server): + count = 0 + while (count < 20): + instruction = "forward" + #retrieve image. + get_image(count) + if valid_image(os.getcwd() + "/gregTest.jpg"): + #Blog Detection + analyzed_image = AnalyzeImage(os.getcwd() + "/gregTest.jpg") + analyzed_image.runBlobFinder() + count += 1 + +server = start_all() +run(server) +end_all(server) +#exit out of controller +exit() diff --git a/controllers/server_thread.pyc b/controllers/server_thread.pyc new file mode 100644 index 0000000..b4fbebe Binary files /dev/null and b/controllers/server_thread.pyc differ diff --git a/distance_to_camera.py b/distance_to_camera.py deleted file mode 100644 index ade6403..0000000 --- a/distance_to_camera.py +++ /dev/null @@ -1,48 +0,0 @@ -# Import image library necessary for file -import SimpleCV -import sys -from SimpleCV import Image - -def check_image(image_path): - #Find file by path and import. File currently resides in same directory. - image = Image(image_path) - # grey = image.grayscale() - - instruction = "go" - array_bounds_possible_widths = [image.width / 4, image.width / 4 * 3] - shapes_pic_attributes = image.size() - - shapes_pic_size = shapes_pic_attributes[0] * shapes_pic_attributes[1] - # dist = img.colorDistance(SimpleCV.Color.Black).dilate(2) - blobs = image.findBlobs() - - #check if the blob is in the middle 1/2 of screen and is too high - for blob in blobs[:-1]: - # print blob.contains() - - if (blob.coordinates()[0] > array_bounds_possible_widths[0] and blob.coordinates()[0] < array_bounds_possible_widths[1]) and (blob.height() > image.height / 5 and blob.coordinates()[1] > image.height / 5 * 2): - # print grey.height - print blob.coordinates()[1] - print "Blob is in the way!!" - blob.draw(color=(255,0,0)) - instruction = "stop" - - # Display the blob until you click on the left side of the picture. - display = SimpleCV.Display() - while display.isNotDone(): - image.show() - if display.mouseLeft: - break - - return instruction - -print sys.argv[1] -instruction = check_image(sys.argv[1]) -print instruction - - -# def check_width(image, blob): -# print check_width -# def check_height(image, blob): -# return (blob.height() > image.height / 1.5) and blob - diff --git a/driver_code_test.py b/driver_code_test.py new file mode 100644 index 0000000..3462032 --- /dev/null +++ b/driver_code_test.py @@ -0,0 +1,38 @@ +import SimpleCV +from SimpleCV import Image +import cv2 +import time +from start_camera import start_camera +import threading + +camera_thread = threading.Thread(target=start_camera) +camera_thread.start() +from get_images_from_pi import get_image, valid_image + +count = 0 +while (count < 10): + get_image(count) + count += 1 + +exit() + +# image = Image('images/9.jpg') +# # p = image.getPalette() +# # rgb = PIL.ImageColor.getrgb("blue") +# # print rgb +# blobs = image.findBlobs(threshval=(0,0,255)) +# # blobs = image.findBlobsFromPalette( (p[0],p[1],p[2]) ) +# # blobs = image.findBlobsFromHueHistogram((0,0,50,50)) +# if blobs: +# for blob in blobs: +# print "got a blob" +# blob.draw(color=(0, 128, 0)) +# image.show() +# image.show() +# time.sleep(4) + + + + + + diff --git a/driving_server.py b/driving_server.py new file mode 100644 index 0000000..db1b1c5 --- /dev/null +++ b/driving_server.py @@ -0,0 +1,45 @@ +from socket import * +import run_rc_car as picar + +def createPiReceiver(): + serversocket = socket(AF_INET, SOCK_STREAM) + port = 9000 + new_picar = picar.PiCar() + serversocket.bind(('',port)) + serversocket.listen(5) + print "New Server Created, listening on port " + str(port) + while(1): + (clientsocket, address) = serversocket.accept() + print "accepted connection from " + str(address) + while(1): + transfer = clientsocket.recv(20) + if not transfer: break + if (transfer == "quit"): + exit() + else: + transfer = transfer.split(';') + if transfer == ['']: break + print "received: " + str(transfer) + inputParser(transfer[0].strip(),float(transfer[1]),new_picar) + clientsocket.send("true") + +def inputParser(command,number,car): + print 'executing ' + command + ' for ' + str(number) +' seconds' + if command == "forward": + car.go_forward(number) + elif command == "backward": + car.go_backward(number) + elif command == "right": + car.go_forward_right(number) + elif command == "left": + car.go_forward_left(number) + elif command == "backward right": + car.go_backward_right(number) + elif command == "backward left": + car.go_backward_left(number) + else: + car.stop() + + +createPiReceiver() +exit() diff --git a/get_images_from_pi.py b/get_images_from_pi.py new file mode 100644 index 0000000..56c6bed --- /dev/null +++ b/get_images_from_pi.py @@ -0,0 +1,16 @@ +import os +from PIL import Image + +def get_image(count): + scp_command = 'scp pi@192.168.2.5:Desktop/gregTest.jpg ' + 'images/' + str(count) + '.jpg' + os.system(scp_command) + return + # os.system('scp pi@192.168.2.5:Desktop/gregTest.jpg gregTest.jpg') + #use following to create key if needed: https://www.raspberrypi.org/documentation/remote-access/ssh/passwordless.md + +def valid_image(path): + try: + Image.open(path) + except IOError: + return False + return True diff --git a/get_images_from_pi.pyc b/get_images_from_pi.pyc new file mode 100644 index 0000000..6149f17 Binary files /dev/null and b/get_images_from_pi.pyc differ diff --git a/models/ident.py b/gregTest.jpg similarity index 100% rename from models/ident.py rename to gregTest.jpg diff --git a/images/gregTest.jpg b/images/gregTest.jpg new file mode 100644 index 0000000..af1e50f Binary files /dev/null and b/images/gregTest.jpg differ diff --git a/models/send.py b/models/send.py deleted file mode 100644 index 53a4d59..0000000 --- a/models/send.py +++ /dev/null @@ -1,13 +0,0 @@ -import socket - -UDP_IP = "10.50.111.176" -UDP_PORT = 5005 -MESSAGE = "Hello, World!" - -print "UDP target IP:", UDP_IP -print "UDP target port:", UDP_PORT -print "message:", MESSAGE - -sock = socket.socket(socket.AF_INET, # Internet - socket.SOCK_DGRAM) # UDP -sock.sendto(MESSAGE, (UDP_IP, UDP_PORT)) \ No newline at end of file diff --git a/pseudocode.py b/pseudocode.py index f09bd69..3c1fc2f 100644 --- a/pseudocode.py +++ b/pseudocode.py @@ -1,6 +1,3 @@ - - - def driveforward(time): FOR each second in time goforward(1) diff --git a/runAnalyzeLine.pyc b/runAnalyzeLine.pyc new file mode 100644 index 0000000..c0b12ff Binary files /dev/null and b/runAnalyzeLine.pyc differ diff --git a/run_rc_car.py b/run_rc_car.py new file mode 100644 index 0000000..3d98395 --- /dev/null +++ b/run_rc_car.py @@ -0,0 +1,62 @@ +import RPi.GPIO as GPIO +from time import sleep + +class PiCar(object): + + def __init__(self): + GPIO.setmode(GPIO.BOARD) + self.pins = {'left' : 11, + 'right' : 18, + 'forward' : 16, + 'backward' : 12 } + for pin_number in self.pins.itervalues(): + GPIO.setup(pin_number,GPIO.OUT) + self.stop() + + def stop(self): + for pin_number in self.pins.itervalues(): + GPIO.output(pin_number,0) + + def go_forward(self,time): + self.stop() + GPIO.output(self.pins['forward'],1) + sleep(float(time)) + self.stop() + + def go_backward(self,time): + self.stop() + GPIO.output(self.pins['backward'],1) + sleep(float(time)) + self.stop() + + def go_forward_right(self,time): + self.stop() + GPIO.output(self.pins['right'],1) + GPIO.output(self.pins['forward'],1) + sleep(float(time)) + self.stop() + + def go_forward_left(self,time): + self.stop() + GPIO.output(self.pins['left'],1) + GPIO.output(self.pins['forward'],1) + sleep(float(time)) + self.stop() + + def go_backward_right(self,time): + self.stop() + GPIO.output(self.pins['right'],1) + GPIO.output(self.pins['backward'],1) + sleep(float(time)) + self.stop() + + def go_backward_left(self,time): + self.stop() + GPIO.output(self.pins['left'],1) + GPIO.output(self.pins['backward'],1) + sleep(float(time)) + self.stop() + + +picar = PiCar() +picar.go_forward(0.5) diff --git a/run_rc_car.pyc b/run_rc_car.pyc new file mode 100644 index 0000000..aa686fe Binary files /dev/null and b/run_rc_car.pyc differ diff --git a/start_camera.py b/start_camera.py new file mode 100644 index 0000000..ea6cee7 --- /dev/null +++ b/start_camera.py @@ -0,0 +1,6 @@ +import os + +def start_camera(): + os.system('ssh pi@192.168.2.5 python RaspberryDrive/takePicture.py &') + return + diff --git a/start_camera.pyc b/start_camera.pyc new file mode 100644 index 0000000..03f4148 Binary files /dev/null and b/start_camera.pyc differ diff --git a/start_server.py b/start_server.py new file mode 100644 index 0000000..4020e03 --- /dev/null +++ b/start_server.py @@ -0,0 +1,6 @@ +import os + +def start_server(): + os.system('ssh pi@192.168.2.4 python python-libs/RaspberryDrive/driving_server.py &') + return + diff --git a/start_server.pyc b/start_server.pyc new file mode 100644 index 0000000..fdec23b Binary files /dev/null and b/start_server.pyc differ diff --git a/takePicture.py b/takePicture.py new file mode 100644 index 0000000..5872d16 --- /dev/null +++ b/takePicture.py @@ -0,0 +1,20 @@ +import picamera as p +import os +import time + +os.chdir('/home/pi/Desktop') + +cam = p.PiCamera() +cam.resolution = (320,240) +cam.hflip = True +cam.vflip = True + +x = 0 +while x < 50: + img = cam.capture('tempGregTest.jpg') + os.unlink('gregTest.jpg') + os.rename('tempGregTest.jpg','gregTest.jpg') + time.sleep(.25) + x +=1 + +exit() diff --git a/temp.py b/temp.py new file mode 100644 index 0000000..35cd3d9 --- /dev/null +++ b/temp.py @@ -0,0 +1,7 @@ +from analyzeimage import * +import os +import connect + +connection = connect.new_connection() +new_image = AnalyzeImage(os.getcwd() + '/images/testAngle4.jpg',connection) +print new_image.runBlobFinder() diff --git a/views/input.py b/views/input.py deleted file mode 100644 index e69de29..0000000 diff --git a/views/output.py b/views/output.py deleted file mode 100644 index e69de29..0000000