Robot A.I. idea for non neural network approach.
September 9, 2012
In this Blog I am simply gethering my thoughs in preperation for a long term project. Hopefully some programming Guru's will post some good ideas. Maybe it will inspire someone else. I am just one nueron in the huge brain of humanity.
When I was 12, I taught myself to program in GW basic on an IBM clone that ran at 8MHz with monochrome, text only graphics and a 5¼inch floppy disk drive. At that time I wanted to write an artificial inteligence.
My theory was that an A.I. was really just a database with some code that would break down your text input into basic concepts, feed it to a database in a meaningful way and convert the results into a text output that hopefully made sense.
30 years later my programming skills are still pretty basic (pun intended) but I think my general theory is still valid. The most important part is that the A.I needs a database, in this case a memory of events that have happened to it which can then be applied to current events to determine a suitable response.
From what I have read about nueral networks they work on a similar principle. My understanding though is that they would really work best in a machine built using graphic cards where you end up with lots of simple processors performing simple repetative tasks since each neuron is effectively a very simple processor.
In this blog I want to explore the possibility of a simple A.I. using an Arduino or Picaxe processor not using a neural network.In theory, a neural network is very adaptable and should work with any robot configuration. It is also somewhat unpredictable and random to begin with. One advantage of a non-neural network is that you can program specific directives into it from the beginning that will not change.
The most critical part of such a program will be memory and time recognition so an SD card or I2C external memory and real time clock (RTC) would be recommended for any prototype.
The key to inteligince, artifical or otherwise is memory. Unless you have an Eidetic Memory then you can basically divide your memory into 2 categories, short term and long term. As our robot will have limited memory and processing power I want to divide it's memory in a similar way.
My concept of this memory division is this: When the robot is running about doing robot things, all events will be recorded along with a timestamp from the RTC into short term memory. When the robot is at rest on a charging station then it can do some robot dreaming. In this case, sort through the short term memory and create a compressed version in long term memory. This compressed version will not be as detailed, only storing significant events such as a successful completion of a task or an error such as a collision. Time stamps are used to sort the information into chronological order. As the long term memory is compressed it should also be quicker for the program to sort through when determining a correct response to a situation.
This is perhaps the most important part. The entire reason for storing previous events in memory is so that the robot can derive a proper response to a situation.When the robot encounter a situation, for example, a collision is detected, then the robot can search it's memory for similar events.
If your robot is fairly simple and does not know where it is then it may search the memory to find the maneuver with the highest success rate such as "reverse for 500mS, turn right 30°, continue". A more advanced robot with GPS or some other means of determining location would refine the memory search for previous similar events at that location.
What is Good and Bad to a Robot?
Perhaps the most difficult part is determining what input is bad and what is good. With only limited sensors, what is a bad input or situation to be avoided and what is good? If you look at a baby who is just starting to touch things and try to put them in it's mouth then it is simple - pain or unpleasant taste is bad. No pain is interesting and pleasant taste / sensations is good.
For your robot, good and bad input depends on the task of the robot. If the robot must clean a floor then while a large impact is bad, a gental, continuous pressure against it as it cleans the foor near a wall could be a good thing as it lets the robot know it is not missing any of the floor near the wall.
For my first experiment I want to keep things simple. Navigation is important for any mobile robot. This first robot will pretend it is cleaning the floor. This means it must cover the entire area of the floor as efficiently as possible without missing any spots.
It will use the RTC to ensure it only cleans from 2am to 5am when everyone should be asleep to reduce the likelyhood of being stepped on. As people may tend to get up during the night for a snack or to use the bathroom The robot will learn through trial and error to avoid those locations during certain times and may even change it's start and finish time on certain days to suit the habbits of the occupants.
I am just going to mount a Micro Magician controller on a Doodle Bot base. The 3-axis accelerometer will provide collision detection and the IR receiver will be used to locate the charging station. Doodle Bot's simple encoders will give 8 counts per wheel revolution and a voltage divider will allow the robot to monitor it's battery voltage. A left and right metal strip along either side will provide terminals for recharging. The front of the Doodle Bot is a wedge shape so it should be easy to follow an IR beacon between two electrodes and wedge itself in for recharging.
I can take advantage of the fact that this robot is designed to draw. By using a large whiteboard for a floor and giving the robot a whiteboard marker I can see where the robot has been and how experience affects the robots path. By setting up a few walls on the board I can easily create a miniature household for the robot to clean.
For my experiment I am using an RTC and SD card reader from Futurelec that I have had sitting in a draw for over 3 years now.
The results of this experiment should be some basic code that would be useful to any mobile robot capable of roaming around the home.
I've had a lot of feedback already and think I need to clarify my intentions. I hope to come up with an A.I. library that anyone can use with any Arduino. There are plenty of SD card reader and RTC sheilds about. If all goes well then I might make a suitable shield for my Micro Magician.
At this point, my theoretical library would have a function for storing raw data (short term memory) on the SD card as well as one or more functions for sorting / compressing the data to become long term memory.
Once I have my Doodle Bot modified and ready for experiment 1 I will post my results and code.
I have built my prototype for experiment 1. It is time to start practicing what I preach. I will continue this blog as a robot post.
I am still writing my first bit of code which is not much more than a datalogger for the sensors. At this point in the experiment I need to work out the best way to organize the "memories" so that they can be easily interpreted as short term memory and sorted/compressed for long term memory.
The first problem I spotted was that the SD card library is huge (about 5K) so I am going to be struggling with the 16K of the current Micro Magician. Fortunately I should have the first prototype of the Micro Magician Pro next week which has an ATmega328P as well as both 5V and 3.3V regulators. This will make the RTC happy as it needs a 5V suppy which is currently being supplied by the USB cable.
The second problem I had was that the Wire library does not work very well with an 8MHz clock. I have now found a new, updated I2C library which solves this problem as well as having cool new features such as fast mode (400Khz), scan() which looks for available I2C addresses and pullup() which enables the processsors internal pullup resistors which is ideal for a 3.3V processor reading a 5V I2C device.
Ok, I finally sorted out my problems with the I2C code and the DS1307, as with most difficult problems it was a combination of hardware and software. I have now upgraded to the first prototype of my Micro Magician Pro and a 7.4V, 2 cell LiPo rated at 1000mAh. The onboard 5V regulator allows me to power the DS1307 without limiting myself to 4x 1.2V NiMh batteries.
Now that I have the RTC working properly I wanted to take advantage of it's 56 byte of non volatile ram. Unlike the EEPROM memory in modern MCU's, the non voloatile memory can be written to as many times as you like without damage occuring. This is because it is ordinary RAM and the RTC battery stops it from being lost when you turn the robot off.
For now I am using some of this memory to record the periods of time where the processor is shut down. To do this, my code reads the time from the RTC once every second and writes a copy to the NV RAM. In the setup function which only runs when the processor first starts up, the program reads back the last time stored in memory and compares it with the current time. It then writes this "Shutdown Period" into a second section of the NV RAM.
This data will not be useful for my current experiment but could be handy at a later stage. My main reason for doing this now was to test that I had everything working properly. I suspect the NV RAM will come in handy for other things later.
Now I can start some serious programming!
The first thing I need to do is work out my file structure for the short term memory. The exact structure will depend a lot on your robot and what sensors it has. The short term memory will record all data for later, indepth examination while the batteries are charging (dream time).
When I sat down to plan my memory structure I was surprised at just how many bytes of memory each "event" would need. The robot does not have many sensors (a 3-axis accelerometer, 2 encoders and an IR receiver) but I still ended up with a minimum of 49 bytes. I am going to round this number up to 64bytes per memory event. This way I have a few spare if I've forgotten anything or want to add more sensors later.
Here is the current structure of a single "memory event". The number at the left is an index number used for selecting specific information from the event.
Note index 0, this is a quick reference byte that records the reason for the event being recorded e.g. impact detected or motor stalled.This can be used later when the robot is looking for memories of similar occurances hapening. For our robot to be inteligent it must be able to cross reference and analyze these memories.
AI short memory data structure 0 memory trigger event byte 1 year byte 2 month byte 3 date byte 4 day byte 5 hour byte 6 minute byte 7 second byte 8 magnitude msb 9 magnitude lsb 10 deltx msb 11 deltx lsb 12 delty msb 13 delty lsb 14 deltz msb 15 deltz lsb 16 x-axis msb 17 x-axis lsb 18 y-axis msb 19 y-axis lsb 20 z-axis msb 21 z-axis lsb 22 0G time milliseconds msb 23 0G time milliseconds lsb 24 left encoder count msb 25 left encoder count lsb 26 right encoder count msb 27 right encoder count lsb 28 left speed msb 29 left speed lsb 30 right speed msb 31 right speed lsb 32 left & right brake byte 33 left & right stall byte 34 servo position msb 35 servo position lsb 36 battery voltage msb 37 battery voltage lsb 38 IR command received byte 39 current mode byte 40 position X co-ordinate msb 41 position X co-ordinate lsb 42 position Y co-ordinate msb 43 position Y co-ordinate lsb 44 position Z co-ordinate msb 45 position Z co-ordinate lsb 46 direction byte 47 action taken byte 48 reason for action byte 49-63 spare byte
A lot of this data is not really relavent and can ultimately be eliminated from a memory event. For example, 0G fall time is only relavent if the robot actually falls. The problem is that our processor is no super computer and trying to sort through this information while the robot is functioning would significantly slow down it's reaction time.
Another problem is that until the information is fully analysed we do not know what information is significant and what is not. This is where the robots "dream time" comes in. The idea is that the robot uses the time in the docking station to analyse the events with 20-20 hind sight and try to find ways to improve it's response in a situation.
My goal is to have all this done by my lowly MCU although I admit it may be neccessary to use a PC to analyse the data on the SD card while the robot sleeps. At this stage it might sound like I am attempting the impossible but stop and look at Patrick's maze solving robot. The robot runs through the maze using a standard "follow the wall" routine and then analyzes the path it took to optimize it. Next time the robot goes through the maze it makes no wrong turns.
My current approach for STEP 1 is to just save it all in a standard format as quick as possible and sort it later when the batteries are on charge. This may change as I write the code. I'm having a few problems with the impact code right now which may be due to either mechanical vibration or electrical noise from the I2C interface.