Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add support for L293 driver #243

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
13 changes: 10 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@ See self-driving in action

This project builds a self-driving RC car using Raspberry Pi, Arduino and open source software. Raspberry Pi collects inputs from a camera module and an ultrasonic sensor, and sends data to a computer wirelessly. The computer processes input images and sensor data for object detection (stop sign and traffic light) and collision avoidance respectively. A neural network model runs on computer and makes predictions for steering based on input images. Predictions are then sent to the Arduino for RC car control.

**Note: This is the code for running a car powered with an esp8266 and L293 driver**

### Setting up environment with Anaconda
1. Install [`miniconda(Python3)`](https://conda.io/miniconda.html) on your computer
2. Create `auto-rccar` environment with all necessary libraries for this project
Expand All @@ -31,8 +33,8 @@ This project builds a self-driving RC car using Raspberry Pi, Arduino and open s
    `stream_client.py`: stream video frames in jpeg format to the host computer
    `ultrasonic_client.py`: send distance data measured by sensor to the host computer

**arduino/**
    `rc_keyboard_control.ino`: control RC car controller
**esp/**
    `boot.py`: RC car controller

**computer/**
    **cascade_xml/**
Expand All @@ -54,7 +56,12 @@ This project builds a self-driving RC car using Raspberry Pi, Arduino and open s


### How to drive
1. **Testing:** Flash `rc_keyboard_control.ino` to Arduino and run `rc_control_test.py` to drive the RC car with keyboard. Run `stream_server_test.py` on computer and then run `stream_client.py` on raspberry pi to test video streaming. Similarly, `ultrasonic_server_test.py` and `ultrasonic_client.py` can be used for sensor data streaming testing.

***Note: Remember to do the TODO in the following file:***

  `config.py` **line 2**

1. **Testing:** Flash `boot.py`, `config.py` & `webrepl_cfg.py` to ESP8266 and run `rc_control_test.py` to drive the RC car with keyboard. Run `stream_server_test.py` on computer and then run `stream_client.py` on raspberry pi to test video streaming. Similarly, `ultrasonic_server_test.py` and `ultrasonic_client.py` can be used for sensor data streaming testing.

2. **Pi Camera calibration (optional):** Take multiple chess board images using pi camera module at various angles and put them into **`chess_board`** folder, run `picam_calibration.py` and returned parameters from the camera matrix will be used in `rc_driver.py`.

Expand Down
Binary file added __pycache__/config.cpython-38.pyc
Binary file not shown.
1 change: 0 additions & 1 deletion arduino/README.md

This file was deleted.

102 changes: 0 additions & 102 deletions arduino/rc_keyboard_control.ino

This file was deleted.

Binary file added computer/__pycache__/model.cpython-38.pyc
Binary file not shown.
Binary file not shown.
73 changes: 44 additions & 29 deletions computer/collect_training_data.py
Original file line number Diff line number Diff line change
@@ -1,28 +1,36 @@
__author__ = 'zhengwang'

import os, sys, inspect

cd = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
pd = os.path.dirname(cd)
sys.path.insert(0, pd)

import numpy as np
import cv2
import serial
import pygame
from pygame.locals import *
import socket
import time
import os
import urllib.request as httpReq
import config


class CollectTrainingData(object):

def __init__(self, host, port, serial_port, input_size):
def __init__(self, host, port, input_size):

self.server_socket = socket.socket()
self.server_socket.bind((host, port))
self.server_socket.listen(0)

# accept a single connection
self.connection = self.server_socket.accept()[0].makefile('rb')
self.httpURL = config.httpURL

# connect to a seral port
self.ser = serial.Serial(serial_port, 115200, timeout=1)
# connect to a serial port
# self.ser = serial.Serial(serial_port, 115200, timeout=1)
self.send_inst = True

self.input_size = input_size
Expand Down Expand Up @@ -81,62 +89,72 @@ def collect(self):

# complex orders
if key_input[pygame.K_UP] and key_input[pygame.K_RIGHT]:
print("Forward Right")
X = np.vstack((X, temp_array))
y = np.vstack((y, self.k[1]))
saved_frame += 1
self.ser.write(chr(6).encode())
res = httpReq.urlopen(self.httpURL + "motrCtrl(1,0)&motrCtrl(2,1)?/")
print("Forward Right: " + res)
# self.ser.write(chr(6).encode())

elif key_input[pygame.K_UP] and key_input[pygame.K_LEFT]:
print("Forward Left")
X = np.vstack((X, temp_array))
y = np.vstack((y, self.k[0]))
saved_frame += 1
self.ser.write(chr(7).encode())
res = httpReq.urlopen(self.httpURL + "motrCtrl(1,1)&motrCtrl(2,0)?/")
print("Forward Left: " + res)
# self.ser.write(chr(7).encode())

elif key_input[pygame.K_DOWN] and key_input[pygame.K_RIGHT]:
print("Reverse Right")
self.ser.write(chr(8).encode())
res = httpReq.urlopen(self.httpURL + "motrCtrl(1,-1)&motrCtrl(2,1)?/")
print("Reverse Right: " + res)
# self.ser.write(chr(8).encode())

elif key_input[pygame.K_DOWN] and key_input[pygame.K_LEFT]:
print("Reverse Left")
self.ser.write(chr(9).encode())
res = httpReq.urlopen(self.httpURL + "motrCtrl(1,1)&motrCtrl(2,-1)?/")
print("Reverse Left: " + res)
# self.ser.write(chr(9).encode())

# simple orders
elif key_input[pygame.K_UP]:
print("Forward")
saved_frame += 1
X = np.vstack((X, temp_array))
y = np.vstack((y, self.k[2]))
self.ser.write(chr(1).encode())
res = httpReq.urlopen(self.httpURL + "motrCtrl(1,1)&motrCtrl(2,1)?/")
print("Forward: " + res)
# self.ser.write(chr(1).encode())

elif key_input[pygame.K_DOWN]:
print("Reverse")
self.ser.write(chr(2).encode())
res = httpReq.urlopen(self.httpURL + "motrCtrl(1,-1)&motrCtrl(2,-1)?/")
print("Reverse: " + res)
# self.ser.write(chr(2).encode())

elif key_input[pygame.K_RIGHT]:
print("Right")
X = np.vstack((X, temp_array))
y = np.vstack((y, self.k[1]))
saved_frame += 1
self.ser.write(chr(3).encode())
res = httpReq.urlopen(self.httpURL + "motrCtrl(1,0)&motrCtrl(2,1)?/")
print("Right: " + res)
# self.ser.write(chr(3).encode())

elif key_input[pygame.K_LEFT]:
print("Left")
X = np.vstack((X, temp_array))
y = np.vstack((y, self.k[0]))
saved_frame += 1
self.ser.write(chr(4).encode())
res = httpReq.urlopen(self.httpURL + "motrCtrl(1,1)&motrCtrl(2,0)?/")
print("Left: " + res)
# self.ser.write(chr(4).encode())

elif key_input[pygame.K_x] or key_input[pygame.K_q]:
print("exit")
self.send_inst = False
self.ser.write(chr(0).encode())
self.ser.close()
res = httpReq.urlopen(self.httpURL + "motrCtrl(1,0)&motrCtrl(2,0)?/")
print("Exit: " + res)
# self.ser.close()
break

elif event.type == pygame.KEYUP:
self.ser.write(chr(0).encode())
res = httpReq.urlopen(self.httpURL + "motrCtrl(1,0)&motrCtrl(2,0)?/")
print("Exit: " + res)
# self.ser.write(chr(0).encode())

if cv2.waitKey(1) & 0xFF == ord('q'):
break
Expand Down Expand Up @@ -168,13 +186,10 @@ def collect(self):

if __name__ == '__main__':
# host, port
h, p = "192.168.1.100", 8000

# serial port
sp = "/dev/tty.usbmodem1421"
h, p = config.serverIP, 8000

# vector size, half of the image
s = 120 * 320

ctd = CollectTrainingData(h, p, sp, s)
ctd = CollectTrainingData(h, p, s)
ctd.collect()
Binary file added computer/model_train_test/data_test.npz
Binary file not shown.
263 changes: 263 additions & 0 deletions computer/model_train_test/train_predict_test.ipynb

Large diffs are not rendered by default.

13 changes: 9 additions & 4 deletions computer/rc_driver.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,16 @@
__author__ = 'zhengwang'

import os, sys, inspect

cd = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
pd = os.path.dirname(cd)
sys.path.insert(0, pd)

import cv2
import sys
import threading
import socketserver
import numpy as np

import config

from model import NeuralNetwork
from rc_driver_helper import *
Expand Down Expand Up @@ -39,7 +44,7 @@ class VideoStreamHandler(socketserver.StreamRequestHandler):
nn.load_model("saved_model/nn_model.xml")

obj_detection = ObjectDetection()
rc_car = RCControl("/dev/tty.usbmodem1421")
rc_car = RCControl()

# cascade classifiers
stop_cascade = cv2.CascadeClassifier("cascade_xml/stop_sign.xml")
Expand Down Expand Up @@ -183,7 +188,7 @@ def start(self):


if __name__ == '__main__':
h, p1, p2 = "192.168.1.100", 8000, 8002
h, p1, p2 = config.serverIP, 8000, 8002

ts = Server(h, p1, p2)
ts.start()
33 changes: 24 additions & 9 deletions computer/rc_driver_helper.py
Original file line number Diff line number Diff line change
@@ -1,30 +1,45 @@
__author__ = 'zhengwang'

import os, sys, inspect

cd = os.path.dirname(os.path.abspath(inspect.getfile(inspect.currentframe())))
pd = os.path.dirname(cd)
sys.path.insert(0, pd)

import serial
import cv2
import math
import urllib.request as httpReq
import config


class RCControl(object):

def __init__(self, serial_port):
self.serial_port = serial.Serial(serial_port, 115200, timeout=1)
def __init__(self):
# self.serial_port = serial.Serial(serial_port, 115200, timeout=1)
# http://192.168.4.1/?motrCtrl(1,mode=0)&motrCtrl(2,mode=0)?/
self.httpURL = config.httpURL

def steer(self, prediction):
if prediction == 2:
self.serial_port.write(chr(1).encode())
print("Forward")
# self.serial_port.write(chr(1).encode())
res = httpReq.urlopen(self.httpURL + "motrCtrl(1,1)&motrCtrl(2,1)?/")
print("Forward: " + res)
elif prediction == 0:
self.serial_port.write(chr(7).encode())
print("Left")
# self.serial_port.write(chr(7).encode())
res = httpReq.urlopen(self.httpURL + "motrCtrl(1,-1)&motrCtrl(2,1)?/")
print("Left: " + res)
elif prediction == 1:
self.serial_port.write(chr(6).encode())
print("Right")
# self.serial_port.write(chr(6).encode())
res = httpReq.urlopen(self.httpURL + "motrCtrl(1,1)&motrCtrl(2,-1)?/")
print("Right: " + res)
else:
self.stop()

def stop(self):
self.serial_port.write(chr(0).encode())
# self.serial_port.write(chr(0).encode())
res = httpReq.urlopen(self.httpURL + "motrCtrl(1,0)&motrCtrl(2,0)?/")
print("Stop: "+ res)


class DistanceToCamera(object):
Expand Down
Loading