View on GitHub

2017Fall-SmartGarbageCar

2017Fall-SmartGarbageCar

Motivation

We got inspiration of this project from the video of an autonomous trash can on wheels that can position itself underneath pieces of garbage one tosses in its general vicinity. This original work is based on wireless communication with MicroSoft’s motion sensing camera and a powerful program that can predict where the garbage will land. In consideration of our limited devices, we proposed this project to design a smart garbage car that can detect and clean up garbages in a small area. And we implemented it on Raspberry Pi and Arduino with technique of BLE and openCV.

Dependency

Implement

The implement of this project is composed of three parts:

When designing the scheme of controlling the car’s movement, we considered 2 different plans. The first one is sending it the angle and distance between the itself and the garbage, but we found it quite difficult to control the car to turn a degree precisely, because the surface of both the wheels and the ground are very smooth and the fictional force is not enough. And sometimes they get stuck when a rotation signal is received. So we decided not to change its direction by the degree of angles and switch to the second plan. In the plan B, we control the car to move only horizontoally or vertically regarding to its former direction. And the only rotation angle is 90 degree, which is much easier to tune in the Arduino code.

Detection

Trash detection

The method we are using for trash detection is based on background subtraction. We use the MOG background subtraction detector provided by OpenCV: cv2.createBackgroundSubtractorMOG in detection. Therefore, the program requires an initial trash-free background during initialization stage. When a trash is detected, the detection is memorized until the system detects that the car move to the trash for pickup.

This is the picture of the detection while the left picture is the raw image seen by the camera and the background subtracted image is on the right. Notice that when a trash stay still for enough of time, it is considered as the background itself. Solving this problem require a initial picture of a clean background to do difference alongside by the subtractor.

alt text

Path

One big problem of moving the car to pick up the garbage is to find an appropriate path. Since we do not have an extra camera on the car, it is impossible for the car to know where to go and we have to calculate the path for the car so that it can get to the right position. However, the direction of car can not be directly detected by the camera and it is changing all the time. Therefore, we record the original direction of the car at the inital stage, and recalculate it when the car moves.

In this project, we first use a method of calculating the running average of the image provided by the camera, and use the image difference to detect the inital location of the car. Assuming that the car is in the view at the first place, such detection is done by calling the car to rotate a full cycle. After that we use the Median Flow tracker provided by OpenCV to track the movement of the car. Such tracker can be replaced by using Machine Learning technique to train a specific classifier for more accurate tracking and better detection in practice.

Also, in order to provide a better navigation path, calibration of the camera is needed. It requires a chessboard-like object which size is known in advance to calibrate and calculate the homography between the camera view and real world. In this project we used a 7x9 chessboard from the web to calibrate.

Communication

The Raspberry Pi and Arduino communicate with each other over BLE connection. In this project, the Arduino works as a BLE peripheral and provide GATT service, while the Raspberry Pi works as a central and a client. The transmission of information is implemented writing value to a GATT characteristic.

BLE module

We use an HM10 module to make the arduino work as a BLE peripheral. HM10 has 6 pins and we only need 4 of them in this case. The RX and TX pin are connected to Arduino digital pins. The VCC and GND pin are also connected to 5V and GND on the Arduino respectively.

alt text

The HM10 module can be configured using its provided set of AT commands. There are some useful AT commands that we used when setting up BLE connection.

By default, there is a single custom characteristic under a custom service provided by the HM10 module, and we can add a second write only characteristic using the AT command mentioned above. After configuration, the Arduino can get commands from Raspberry Pi by reading the value of that characteristic.

GATT programming

The program of implementing the RPi as a BLE center is based on pygatt library, which provides a Pythonic API by wrapping up gatttool command line utility.

To connect the raspberry pi with HM10 module, we first start the adapter and use it to connect the BLE module by its address.

self.address = address
self.type = addr_type
self.write_uuid = "0000ffe2-0000-1000-8000-00805f9b34fb"
try:
	self.adapter = pygatt.GATTToolBackend()
	self.adapter.start()
	print "===== adapter.connect() ====="
	self.device = self.adapter.connect(address, address_type=addr_type)
	print "address: " + str(self.device._address)
except:
  print "Cannot start adapter"

As for write characteristic value, the library provides a char_write function. All it needs is the uuid of the write-only characteristic.

device.char_write(uuid, in_buf[:20])

Since it is very likely that the openCV program is not in the same file as the pygatt code, this part is implemented using multi-thread technique as a bridge between two parts of the program. (Although we coded them into the same file in the end, we kept the multi-thread part.)

alt text

To communicate with the main thread, we define a writing event. The main thread will wait for the event and start to process it after the event is set.

Because Arduino communications with the HM10 module over serial connections and it reads information as a sequence of chars, so the commands sent from RPi to Arduino are encoded as a formed sequence of chars, which will be decoded char by char in the Arduino program.

Reference