In a perfect world, this autonomous RC car would have worked like a charm. However, compromise after compromise, I finally came to a project I am proud of. It may not have kalman filters, PID control, or be the fastest car in the west, but it did follow and create its own path autonomously. In the future, I hope to get a better car which will allow me to do all the things I hoped to. In addition, I would probably use c++ instead of python because python runs considerably slower.
The final project consisted of me controlling the motors manually with a motor driver/h-bridge. My original idea was to solder pins to the existing control board in the car, but when that fried, I had to control them manually. I used a slot-type optocoupler and some cardboard to measure how far the wheels have turned. To measure the direction that the car was pointing towards, I used the Adafruit 9dof sensor which did the absolute orientation measurements for me.
Written in python, and scrappily made, the code is what made the project what it is. In essence, various hander allow controlling and communication to the hardware. One hander establishes interrupts for the encoder, another communicates to the gyroscope, and a final one creates functions to run the motors.
Once these handlers were made, it was on to coding the actual autonomy. I took an existing search algorithm called A* and used it to find the shortest path between two points on a map. Then, I translated the 90 and 45 degree turns into instruction sets that accommodated the car’s turn radius. I did this by creating tangent arcs that intercepted the lines at 2 points, and using that to find hard coordinates to turn to.
One of the major compromises I had to make was using bang bang control instead of PID. PID is the industry standard for control systems because it is accurate, and most accurately simulates how a human would control a car. Unfortunately, to use PID, the steering must be controlled by a servo. If it is controlled by a motor, such as my car, you can only move fully right or fully left.
A kalman filter is also the industry standard for filtering fluctuating data. It can quickly find accurate average data even though the input may fluctuate. I was hoping to use it for the gyroscope which was fluctuating about 1%, which for an autonomous car is quite a lot.
Final Milestone: LCD & Assembly
This final milestone incorporates the movement capabilities of the car with a predefined path. This way, nearly any map with predefined start and end positions can be used on the car. It uses a search algorithm to find a temporary path. The output of that algorithm is then manipulated in a way that it is followable by the car.
How it works
This was by far the most difficult milestone for me to achieve. The first part was easy: finding the shortest path with the ‘A*’ algorithm. It works by ranking the surrounding pixels by desirability, and finding the path of the most ‘desirable’ pixels. This was simple because the problem was already solved (Thanks to Christian Careaga for uploading the python version to the internet).
The hard part was translating the data to something the car could understand and follow. The sharp turns provided by the output of the A* algorithm could not be made by the car. Therefore, I had to use geometry to construct a way to integrate turning radii with the sharp turns.
Above is an image of the path, and the A* output. The white areas are open for the car to move. The grey areas are my paddings from the wall to protect the car. Finally, the black represent places where the car cannot drive.
Inside the image, a green pixel represents the starting position (center of mass of the car). A red pixel similarly represents the ending point.
The redline is the output of the A* algorithm, and it represents the shortest path.
Why I Used It.
The A* Algorithm, created in the early 1970s, was a faster alternative to the more well-known Dijkstra’s Algorithm. It provides a path planning solution for getting around obstacles. I used it to solve the simpler problem of finding a path. There are more possible solutions, but this was the easiest to implement because the code was available online.
How It Works
The algorithm works by ranking the squares around the target. Each square is given a fscore, gscore, and hscore. A fscore ranks the absolute distance between the square and the target. A gscore is the cost of traveling from the start square to the current square. A hscore is a guess to the cost of moving from one square to the goal. Comparing the three scores between squares, and choosing the ones with the lowest score is how the A* algorithm works.
Why I Need it
The A* Algorithm, though it works, does not produce a followable path. The sharp 45 and 90 degree turns cannot be made by the car. Instead, I need to incorporate a turning radius into the path. I attempted this by constructing arcs tangent to the straight lines and incorporating them into the instruction set.
Most of the difficulties came with designing the algorithm. Creating the arcs was not the problem, but detecting the changes in angles was hard. I resorted to saving the generated path into a file, and reading the path to detect angles. In addition, the A* algorithm took 30 seconds to complete, which made it impossible to run in real time. Part of this was the Raspberry pi, but mostly because the raspberry pi does not support CUDA (using the graphics card to run code).
Second Milestone: PCB Transfer & Testing
This milestone allow me to interface with the various sensors used to calculate my relative position. I used a LDR to measure wheel rotation and used the absolute orientation sensor in the BNO055 to measure the heading.
How it works
As I mentioned earlier, tracking wheel rotations is a vital part to knowing where you are relative to the starting position. To tackle this problem, I used a Light Dependent Resistor (LDR) to detect if the sensor is behind a spoke or open space. Then, using some calculations, I can indirectly determine the resistance of the LDR, which depends on the ambient light.
Knowing the heading is a much simpler task. Using the BNO055 IMU from adafruit, I can extract the absolute orientation of the car.
First Milestone: IoT Compatibility
First Milestone Video - Forrest L.
Since my code was not working, I thought that possibly redownloading the entire IDE may help with properly resetting my board and libraries again, as I was afraid that I may have downloaded an incorrect file. Uninstalling the Arduino IDE would clear all memory on my local disc in regards to my code.
Even after redownloading my IDE,
Starter Project Video - Forrest L.
How it Works
The brain of my night light is an Arduino micro-controller board located on my breadboard. It runs pre-deployed code from the Arduino Integrated Development Environment (IDE) and controls the LED through jumper wires placed in pins around the board. When the potentiometer is turned, the current sent to the LED is limited by a resistor, which in turn changes the color of the LED from red all the way to magenta.
Major roadblocks I faced with my starter project were in regards with the time I spent with a malfunctioning breadboard as well as with the LED cathode. With the breadboard issue, I spent time looking over my wires to make sure the pins were in the correct location. After that, I took more preliminary steps to see where the issue would lie. I then used a multimeter to see if the resistors or if the board were not conducting power. That was the issue and then I replaced my breadboard, which then worked! Following that, the next issue was with the LED itself. It would not work when plugged into ground, so then changing the wire placement to the 5V rail worked, thus I concluded the LED was not a common LED, but an LED cathode. This meant that all the RGB values displayed were reciprocal to what they were supposed to be, and after a bit of research I was able to resolve this issue to finally get a working project.
My Starter Project is the Arduino controlled night light, a simple night light that uses photoresistor inputs to determine when an LED should turn on and off. By turning a dial, the color of the LED will also change to hardcoded RGB colors. With my starter project, I learned about the usage of a resistor, as well as how LED cathodes functions.