Tuesday, September 14, 2010

The "von Neumann" machine & parallel processing

It's been a while since I last posted a message. I've been thinking a lot about machine architectures and the most prevalent one, the "von Neumann" one (see right). This architecture basically serves the Turing machine very well. The Turing machine is a bit more of a philosophical model, whereas the von Neumann architecture is a specification for the implementation of one. The CPU here is a serial processor unit which, in any way you put it, never executes more than one instruction at any given time, or per clock cycle. The CPU then has a couple of pins available that are connected to outside devices or buses. Sometimes the buses don't really contain anything, but you could put some PCI, PCIe, ISA or other kinds of electronics in them, or you could attach some device to a serial, parallel, USB or FireWire port and then the more advanced Operating Systems would allow the automatic registration of these devices and subsequent allocations of address spaces and such (through a driver and hardware-specific communication protocol like USB has).

The architecture above is very well suited for mathematical calculations, because you could write programs that are expected to execute code in a serial way and this architecture would per definition execute those commands one after the other, store the intermediate results in memory, pick them up again at a later stage, post-process them with other results, produce output to screen, write it to disk, send it over the internet and whatever other "logic" you dare to endeavour in.

The above describes a regular PC and everything is deterministically determined. Its very architecture makes it very hard, if not impossible, to write programs on it that behave in ways that you would not be able to explain, assuming you have the tools available to verify the signals and so on (so it's a theoretical statement). This deterministic processing is what makes the design viable. It is by its nature serial, because the CPU must retrieve one instruction to execute, fetch something from memory, store it into memory and do this in the correct order for the program to function correctly.

One architecture that is too complex for us to design is one where the CPU is no longer processing one instruction per clock cycle, one after the other in serial fashion, but a CPU where you can have a very high number of processing units and memory is not in one place, but distributed around this network as well.

Most applications that we write nowadays are data-driven. Now, the interesting thing here is that I think more and more applications are written data-driven style instead of purely as code. Anywhere else but the enterprise world that is :). Data-driven programming means that you move logic, output or processing from code (long switch statements or branches) into processing tables, datafiles or whatever. Almost, if not all, machine learning programs are always by definition data-driven programs. The algorithm itself is usually quite compact as a program, but frequently needs mountains of data to function correctly.

The main complication in the entire thing is that purely serially written code avoids the complexity of having to synchronize results later on, most importantly at the right time. This latter thing is also what plagues certain parallel architectures and programs that already do exist and also complicates designs for GPU's, FPGA's and so on. You could also call it the binding problem in psychology. It's easy to think of channels of processing where a little bit of the entire thing happens in that single stage, but connecting the dots later to make it a larger whole that means more than each channel individually is a very large challenge. Maybe not if you have the time to put it together thoroughly at leisure, but certainly at realtime.

Friday, August 20, 2010

Flying with Ardupilot Mega

I'm experimenting with the ArduPilot Mega source code and settings and have finally succeeded to get it working properly using a FlightGear simulator and the board setup through a serial USB link. I've made a flight, slightly rough around the edges, around San Francisco airport in the simulator with some tweaked waypoints. You can find that file here.

The biggest problem in getting the link working has been the communication between the PC and the arduino board and FlightGear. FG may reduce or increase framerates and start buffering data when the interface program is not consuming them fast enough. The current interface is almost ready for real use, but can I think still increase the speed in which it passes data around.

In order to get stuff working, you should check the source code out of code.google.com and make sure that you're pointing to the correct library location. Download the GPS_IMU.zip which is used for the communication with the USB 'ground station' (the flightgear link). Then reduce the NAV_P gain in the APM_PID_Gains.h file to something like .5 and reduce the other P gains too (you'll notice if the gain is set too high when it becomes unstable in flight and increases the roll or pitch constantly).

As I said, the flow of data was the biggest problem, so communication with flightgear is now attempted to be optimized. FlightGear does not care too much if there is nothing to read, but writing more than it can handle will buffer data on the IP buffers. So you should aim to write 1-2 Hz less than the link setting. Also pay attention to the frame rate that FG is able to put out, because that is the minimum update frequency you can use.

Reading from a port should be done as fast as possible and ideally outside of the main "50 Hz" loop. Since Arduino attempts to follow a 50Hz loop, you could attempt to follow the same in the interface application, but there's a possibility that you overload the link. The older XPlane app issued the attitude and additionally the GPS at 5 Hz, but I modified that to output XPlane attitude @ roughly 42.5 Hz and GPS @ 5 Hz. That leaves a bit of space to get rid of any overload that might occur on the arduino side.

Reading from the serial port should also occur as fast as possible. This way, you can keep everything in the same loop once you use a couple of global variables for whatever data is read from the links. Once something can be written, then just set up the packets and kick it out the door.

There are probably some configs to change in the Arduino source code before thinsg will work for you:
  • I have airspeed sensor set to 0.
  • The example waypoint file has been modified to allow the cessna to make the turns (better:).
  • GCS_PROTOCOL is set to 3.
  • GPS_PROTOCOL is set to 3.
  • GPS_IMU is included.
  • The #ifdef GPS_PROTOCOL != 3 before the GPS.read() is commented ( around line 610 in main source file, inside update_GPS function).
I first ran in STABILIZE mode and verified that I got responsiveness on the sticks. If your interface is buffering too much, reading too slow or writing too fast then you may get responses after 5 seconds. That will never converge to a model that can fly properly.

Then after STABILIZE mode you can quickly verify FLY_BY_WIRE_A and B to see if that works out. Then I loaded the waypoints and turned on AUTO mode. For that to work, just start flightgear and pause it. Zoom out a bit with Shift-X until you see the throttle stick. Hit "H" to see the HUD to get more info. Then make sure the switch is set to manual with throttle at zero. Start up the interface. Wait for the servo's to wiggle and the interface to print "Ready to Fly". Now you can switch to AUTO mode, but you have to control the throttle manually. I basically set throttle to full.

Because I don't have a rudder attached (nor is this set in the ardupilot.xml file), the plane veers off to the left due to the propeller torque until it lifts off the ground. The ardupilot mega will then slowly turn back to the heading it had when it was going 3 m/s (12 knots). Initially I used 10 degrees pitch, but noticed that it tried to drill itself into the ground. Making that 20 degrees again fixed it. Also make sure that your NAV P gains are correctly set, as these will determine how eager the autopilot is to get to the setpoint. Since the stock cessna of FlightGear is a bit slow in relation to an easystar, these P gains probably have to be reduced. It will then be less strict in following the waypoints, but allows for easier flight.

Have fun!

Monday, August 16, 2010

Making HD videos in France

I've returned from a small holiday in France and took the UAV to fly over there. I used the GoPro HD camera in the cockpit and shot a couple of videos @ 60 fps, 1280x720p. The results are on YouTube with a slightly reduced bitrate (more compression):



And another one near the castle of Castlenaud:



And I returned to the camping to make a high-altitude video from up above:



Nothing got seriously broken and it's great to see the videos to improve my flying skills. The video was also transmitted live to my netbook on the ground, but I didn't use that for navigating around (yet). I first need to check into an automatically adjusting tripod setup that will track the plane for a patch antenna. That will ensure, usually, a very good video link.

Thursday, August 05, 2010

Hauppauge USB Live 2 & Ubuntu

I'm running Ubuntu and purchased a USB Live 2 stick from Hauppauge to visualize some direct composite video coming from a 5.8Ghz receiver. This video is transmitted from an RC plane to see what's going on up there on a netbook. I'm not flying it FPV for lack of goggles and because I want to keep track of where the plane is. Basically, the intention is to put the family behind the netbook to see what the plane sees and I'll stare at the dot in the distance.

The USB stick arrived yesterday in the mail and after plugging it in, nothing happened. USB devices get recognized by their ID's and as soon as you register a driver for it, the kernel will visit all eligible drivers to see if one wants to step up to communicate with the device. Apparently the support for USB live 2 is not available in the stock distribution of Lucid yet. After searching around I suddenly hit a post made on the 3rd of August (sic!) that support for USB Live 2 was just completed on a development branch in v4l2. So the day before I got the stick development just finished with the first version of the driver.

Blog: http://www.kernellabs.com/blog/?p=1445&cpage=1#comment-1632

I managed to install this on both my netbook and general PC. These are a 32-bit Lucid Lynx distribution on a Samsung N210 and a 64-bit installation on a more powerful machine with ATI HD5850 and i7 920. You should make sure that you're not holding back any linux packages, since I got screen corrruptions with kernel 2.6.32-23. The latest version now is 2.6.32-24 and there it worked (or it was something else, who knows?). After the clean install, you need to grab gcc, do an update/upgrade of all packages and make sure the latest kernel headers are present:
> apt-get install gcc
> apt-get install linux-headers-generic ( <-- ensure it's the latest & greatest @ 2.6.32-24 )
Then I used the entire v4l2 source tree available here (at 05-Aug-2010 that is, things may change rapidly here)
> hg clone http://kernellabs.com/hg/~dheitmueller/polaris4
> cd polaris4
/polaris4> sudo -s
/polaris4> make

( then edit v4l/.config:
1. find CONFIG_DVB_FIREDTV=m
2. change this into:
3. CONFIG_DVB_FIREDTV=n
4. (notice the n instead of m at the end, that's all).
5. This essentially deactivates the build of a problematic module, so if you have a problem there
you can deactivate it.

/polaris4> make
( yes again ).

If all went well:
/polaris4> make install

And then reboot. The reboot will ensure you're not using any old drivers. The rollback procedure for this is to reinstall the linux-image-...version... you were using. That will replace all your modules with the stock Ubuntu Lucid distribution.

Any time you get a new linux-image installed, you have to do another make, make install in this custom directory to overwrite the module files again. Remember that!

As you can tell, after doing this some video-related things may not work properly. For my netbook, I'm only going to use it in the field and some simple stuff. So far things haven't broken, so that should be relatively safe. It looks pretty stable so far.

I've noticed that the image when there's no signal may be plain blue. That is usually the case when the signal hasn't been tuned at all, but in this card you must ensure there's a video signal going into it.

The USB Live2 is a great little gadget with quite good image quality and zero lag on the Linux drivers. In Windows it's possible you get lag up to 3 seconds even, but that's because your driver must be configured to use "GAME" mode (if you're flying or gaming with this that is, otherwise it doesn't matter too much).

In order to visualize things, I now use tvtime (apt-get install tvtime). There's a handy configuration XML file in /etc/tvtime.xml where you can make all the default settings. The coolness about this utility is that you can change a large number of settings without restarting and adjust the image quality, brightness or contrast itself. Great for outdoors flying and getting a bit more out of the display.

The USB Live 2 uses the cx231xx kernel driver.

Sunday, August 01, 2010

Mesh networks

An interesting technology to be playing with are wireless self-healing mesh networks. Mesh networks are characterized by a rather chaotic characterization and where the data sent by one node is not necessarily sent directly to the receiver, but may make a number of hops before it gets there. This allows you to introduce a number of routes between the source of the data being generated and the coordinating node where the data needs to go.

A lot of propositions offer mesh networking for near real-time video display and those types of applications, instantly pushing the limits of the capabilities of bandwidth and network stability. I think the low-speed networks are slightly more interesting myself due to the low-cost ability to set this up and the speed at which such networks can be realized. This makes it very interesting for situations in which you need to cover a certain area for monitoring of some type. As long as the modules being placed have the right kinds of sensor and logic unit, you can start collecting data from this environment in no time.

Sometimes you want to collect more data than the sensors can give you, for example due to bandwidth constraints on this technology or the sensors that the installation is offering. In that case the cooperation of other mobile sensors that can be directed towards positions can help. Think UAV's being directed to that location, but still have means to be 'part' of the network as they move around a larger area of say 10 km to assist with the sensors they offer. The whole idea should be to plot interesting data about this larger area in no time and to do this as autonomously as possible.

Saturday, May 22, 2010

Joystick pong (how to write custom usb drivers for the nanoboard)

I've just worked out how to write custom drivers for the nanoboard to extend the capabilities of the platform through different USB devices. It isn't really that difficult for similar devices (you could just copy things across), but for more complicated devices you need to understand how the USB protocol works. The nanoboard USB host driver already takes care of a lot of the details for you. The specific device driver that you are writing only has to indicate if it wants to be a device driver for a particular detected device. The device driver call basically does a test using the data that is passed in. This data comes straight from the interface and device descriptors that were received from the bus. This is sometimes where the problems start. My joystick on Windows isn't recognized as a joystick per se. It's a Human Interface Device without a boot capability. It's working properly in games, but that's about it. The HID protocol isn't passed by it (which should be 04, for joysticks). This causes issues for people writing device drivers, because you can't know what type of device something is.

Also, not all joysticks pass the same ranges of data. The USB HID descriptor does indicate the ranges for USB, but this complicates things a bit for the device driver writer.

Anyway, the sample joystick driver is here and a new version of the pong game is here.
( the joystick driver should be put in the "Library/Software Platform/services/usbhost" directory of Altium designer).

In order to write drivers for other devices, it's helpful to boot into Linux and inspect the descriptors that are sent across the wire. A useful page comes from a guy who has rewired his old joystick to make it USB compatible. Other useful pages are the HID tools page and a page explaining how to use usbmon software to analyze the USB in more detail. Wireshark can also capture things from the USB. (usbmon on my lucid ubuntu seems to have been compiled into the kernel already. Just see if the /sys/kernel/debug/usb tree is there).

You can then use the kernel debug interface to inspect what's going on in the system. Under linux, cd'ing to:
/sys/kernel/debug/usb
will give you a devices file, which is useful to find out how a device is recognized. My joystick is incorrect, because it doesn't provide subclasses or protocols, as can be seen here:

T: Bus=03 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#= 2 Spd=1.5 MxCh= 0
D: Ver= 1.10 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=046d ProdID=c215 Rev= 2.04
S: Manufacturer=Logitech
S: Product=Logitech Extreme 3D
C:* #Ifs= 1 Cfg#= 1 Atr=80 MxPwr= 30mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=00 Prot=00 Driver=usbhid
E: Ad=81(I) Atr=03(Int.) MxPS= 7 Ivl=10ms

Compare that to the mouse (but notice how the same driver is used):
T:  Bus=07 Lev=01 Prnt=01 Port=00 Cnt=01 Dev#=  2 Spd=1.5 MxCh= 0
D: Ver= 2.00 Cls=00(>ifc ) Sub=00 Prot=00 MxPS= 8 #Cfgs= 1
P: Vendor=046d ProdID=c018 Rev=43.01
S: Manufacturer=Logitech
S: Product=USB Optical Mouse
C:* #Ifs= 1 Cfg#= 1 Atr=a0 MxPwr=100mA
I:* If#= 0 Alt= 0 #EPs= 1 Cls=03(HID ) Sub=01 Prot=02 Driver=usbhid
E: Ad=81(I) Atr=03(Int.) MxPS= 5 Ivl=10ms
Another cool thing to do is to look under:
/sys/kernel/debug/hid
This will show a couple of weird ID's, but those are the currently attached devices. In those directories, you can inspect the rdesc file for each of them. The rdesc file describes the format of the data, so indicates to the host device driver how it should interpret the data stream.

Devices may have multiple interfaces. The keyboard and mouse typically have a 'boot' interface, which allows the devices to be configured in the boot sequence. Notice that under linux, the same 'usbhid' driver takes care of most HID devices. This is because of the rdesc file, indicating the way how the driver should interact with the device. I'm not exactly sure at the moment how the driver would communicate this to the applications or HAL layer above it in a generic way.

Notice that HID are not always strictly input devices. Some HID's have outputs (device input) which allow the setting of LED's, force feedback, etc.

So how does one read these HID files to discover the data format? Let's look at a simpler example, the mouse:
Field(0)
Physical(GenericDesktop.Pointer)
Usage(3)
Button.0001
Button.0002
Button.0003
Logical Minimum(0)
Logical Maximum(1)
Report Size(1)
Report Count(3)
Report Offset(0)
Flags( Variable Absolute )
Field(1)provides
Physical(GenericDesktop.Pointer)
Usage(3)
GenericDesktop.X
GenericDesktop.Y
GenericDesktop.Wheel
Logical Minimum(-127)
Logical Maximum(127)
Report Size(8)
Report Count(3)
Report Offset(8)
Flags( Variable Relative )
The logical minimum and maximum determine the value range. This could also be used to rescale the values if you want a consistent output. The "report Size" is the size in bits of one individual field. "Usage(x)" indicates the number of fields that are being described. Report Count(x) does the same. The Report offset(x) describes the offset of these fields within the entire data stream. So, this mouse protocol uses the three bits in the first byte to describe the state of up to three buttons. It uses 3 bytes after that, indicating X and Y motions and the motions of the wheel.

This is basically how I figured out how my joystick worked. You could also specify your own rdesc / hid file using the HID tools mentioned above. Of course, computers don't need to communicate in ASCII, they'd use the compiled HID information as an array of bytes to convey the same information. The manufacturer and product ID are 16-bit fields that need to be looked up in a file on the host somewhere, if one cares about it.

Update: Here's another version using a lower resolution and lower color palette. Because of the USB code and the other drivers, the generated ROM image is larger than 32k and doesn't fit in local processor memory. This requires the use of a small amount of RAM, which constantly reads in new code to execute whenever required from memory. This memory (SRAM) is the external RAM on the nanoboard, which is shared with the VGA driver. Because the VGA driver gets priority, the game slows down whenever the processor tries to update the frame (because the processor cannot read in code to execute from SRAM memory at the same time the frame is being drawn to the monitor).

Thursday, May 20, 2010

Pong!

This is a late-night shot of the game Pong!, running on a soft-core TSK-3000 RISC processor on the nanoboard. You control the paddle with the remote left and right. There aren't that many examples on the Internet on how to use the actual VGA display for the nanoboards. Actually, I found none. There were two examples from the tutorials shipped with Altium designer that demonstrated how the VGA connector should be used. There are a number using the TFT display on the board, but that's too small for a couple of things.

Pong! on the nanoboard goes public domain. It's imperfect and inefficient, but it does show how to render things on the VGA monitor (not the TFT). This implementation uses double-buffering, which in embedded devices is very costly because of memory requirements.

The display is not yet stable, it's flickering due to issues with VSYNC. I haven't figured out yet how to use the interrupts properly and let the framework driver rely on them, or whether the API calls have been used correctly. I'm hoping for some feedback in the forums, after which I could provide some updates here and there and show better practices in doing this.

Another thing I'm looking into is the best practice for writing one's own drivers for USB. There's a software stack available that can already inspect USB signals and packets that tell a host device what a connected device is about. There's very likely going to be a point where someone wants to write their own USB device for interfacing with the nanoboard, but is wondering whether to start from scratch at the signal level, or whether the usb-host sw platform can be used in any way. Without hacking into the standard altium designer library that is.

Well, plenty of ground to cover still with this device. It's a lot of fun and I'm starting to find my way around it already. I'm feeling quite confident about my abilities to prototype using the hardware on and around the board. It's just so easy. The difficulties start to arise when more complicated designs are required, especially those requiring more memory or specific hardware protocols or interfaces (custom designs). As with the above, my next goal will be to find out how to connect a USB joystick (and I'll opensource that as well). And from there... onwards...

Wednesday, May 19, 2010

Tutorials finished!

Well, I got things up and running like a charm in the meantime. After the inital GB downloads (which may get fixed ? see comments previous post! ), I've completed most tutorials of the Nanoboard today. There were only three that I couldn't run due to some interoperability issue with the Xilinx tools, but that happens sometimes. It's been logged, noted and people are working on it!

So far... I can say it's truly amazing and a pleasure to work with this board, especially for those who are newbies in the field of electronics. The tutorials provide a very basic overview of what the board really can do, so keep that in mind. Of course those applications can be done quite easily on Arduino boards or whatever.

But then have a look at the extensive royalty-free library... you'll discover 119 subdirectories loaded with microprocessors, circuits, memory blocks, opamps and plenty of other electronics that can be inserted in the schematics diagrams. People at work sometimes do use some exotic hardware and this makes it likely I can find the same chips and IC's they work with. In combination with the other tools and outputs, you can generate all kinds of testbeds for running their code on this FPGA, but analyzing the signals or some other things to help out.

It wasn't very clear to me that the real use of the board is probably about trying out different processors and designs up-front, before you solder things together. But now that I think about it, this certainly makes sense. At work some people work on UAV's for example. They require very small, light-weight boards that provide lots of functionality and a good amount of processing power. Everything is embedded and hardware supported. You couldn't put a nanoboard in one of those planes due to weight and power cable concerns :). But simulating a particular board or processor, or just having a platform where you can run embedded ideas from is a great nice-to-have. Since it's very close to the PC that could run a simulator like FlightGear, you could just hook up this board to a FlightGear stream of simulation data, where the board must attempt to fly the plane level or other kinds autopilot functions.

So yes, I am certainly pleased with my purchase. If anybody is ever thinking of going into FPGA programming, this is the board you want. It's probably twice the price of a regular board, but you get three times the value back for it. The extensive library of 'soft-design' hardware, the ability to still run VHDL code on the chip, the way how it interfaces with your computer, the Altium Designer software (only for a year though, so check out the conditions) and the overall hardware that is attached to the board (TFT touch, PS/2, S/PDIF, USB, SD-card, MIDI, audio, RS-485, RS-232, ethernet, VGA-out).

Definitely recommended! It's Arduino++.

Monday, May 17, 2010

Altium Nanoboard 3000

I've managed to get my hands on a really cool FPGA board from Altium. It's very promising with a TFT touchscreen display, RS485, RS232, 3x USB 2.0, S/PDIF in-out, SD-card reader, headphones/line-in/line-out, 4-ch DAC, 4-ch ADC, 4x relays, PWM, SVGA output, MIDI and a TSK-3000A RISC 32-bit processor.

Unfortunately, where this technology is really amazing, getting things to work on your computer is not so. Your mind will dazzle from all the license files, registrations, threats about non-compliance with export restrictions and whatever else these companies come up with to make your life difficult. For someone having gotten used to Ubuntu and the software it brings through straight installs, getting a minimal "Hello World" out of this board is proving to be extremely challenging for a newbie. And I'm saying that as an experienced programmer.

The biggest crap factor are the Xilinx tools. They offer a "webpack", but the download is around 2.6GB (not much of a "webpack" if you ask me). The 12.1 version is incompatible with Altium Designer, so that's where problems are starting. So then I downloaded 11.1 as required, but that is not supported on Windows 7. Altium Designer so far has no particular problems with Windows 7. So I upgraded Altium Designer as much as possible, but that didn't improve the chances of compatibility with 12.1.

Basically, I got a dreaded "Xilinx ISE not found" message in red above my FPGA chip, which was actually due to a missing environment variable (no longer set in 12.1?). Altium Designer just picks up the "XILINX" path variable, which should point to the "ISE" subdirectory of the Xilinx ISE installation. If XILINX is not there, it will show the above message. Populating XILINX as the env variable by itself is not enough, as even a very simple example won't compile due to differences in compilation options.

If you get: "No Process Flow", then you should simple "configure" the project by right-clicking on the nanoboard icon in the devices view and generate the constraint files.

The information about what to do next is not really available on the Internet. Most suppliers lock down their forums entirely, so you need a login to find out if others have had the same problem. Since most companies probably follow the instructions on what OS to use and so on, this doesn't seem to have occurred much. Luckily, I found one solution that seems to be going to work. You need a lot of patience and flick your common sense in "off mode" for this to work:
  1. Download the ISE Webpack 11.1 anyway (2.6 GB or so).
  2. Download the ISE Webpack 11.3 as well (another 2.7 GB..... *sigh*). Downloading only 11.3 will not work, because the installer asks for the 11.1 install directory (hooray!). Even though the size of the installation file clearly shows otherwise.
  3. Then install 11.1, but not from the main folder. Go into "bin/nt" and start "xsetup.exe" from there.
  4. Wait for this to install. Takes a while. Feel free to *not* install "webtalk", because that just sends how you use the tools to xilinx and why'd you want to do that?
  5. Then install 11.3. It will ask for where you installed 11.1 to. 11.3 is luckily compatible with x64 already.
  6. This upgrade takes quite some time (apparently it checks every file if it needs upgrading?).
  7. Restart Altium Designer... and now it should show up. ( See "XILINX" environment variable if it doesn't ).
Another word on what these companies do that I find very strange. Altium Designer and Xilinx Webtalk basically monitor the way how you use the tools and send this over to their servers "for improving your experience". So you've got basically a hidden spy on your computer now that indicates to them what you use, how long you use it, on which days etc... ugh!

I'm certainly not some experienced FPGA designer, I just decided that I wanted to learn about this technology and play around with it. My intention is to grab a board that could do a number of interesting things, rather than starting from the bottom-level basics. Altium Designer allows me to focus on certain high-level topics, such that I can create some truly interesting marvels first before having to delve into the low-level details first. I prefer it that way, because I don't get hit by the low-level nit-picky details in the face immediately. Eventually however, I already noticed that one needs to gain the knowledge about electronics, wiring and so on in order to use these things effectively and knowledgeably.


My install got finished and it's all compiling now. I'm going to check through the tutorials, see if I can write a couple of things myself, play around with things a bit. Given the software that Altium provides, if you are a learner like me, I can certainly recommend what they are offering in these nanoboards...

Wednesday, May 12, 2010

Field Programmable Gate Arrays

I've been looking atFPGA's and ordered my own board to arrive in the mail pretty soon I hope. The difference between a normal CPU and an FPGA is best explained here. Notice how FPGA's are independent and act directly on the signal, whereas the CPU typically executes one instruction per 'clock cycle', but then may need to retrieve values from memory, put this into a register, execute another instruction, push back from register to memory and so on. Once you think about it, it's already pretty amazing that a single CPU can be so darn fast.

FPGA's however do not typically need to do this. It requires a totally different thinking about computing, but benefits from using much simpler logical elements wired together in different ways. This configuration of logic elements is what provides it with an application.

The FPGA's limitations are more the number of elements (and thereby the functionality it can possibly embed), because it's program is embedded in hardware and isn't read from memory and then executed by the same device. This is also how they are very different. FPGA's are also not programmed with a standard programming language (since it's inherently parallel and the program is basically the configuration how logic elements wire together). Another language called VHDL is used for this purpose, which does not require you to think about all things in parallel (one of the reasons why computers are easy to program is because we can think about events serially, as happening one-by-one. Multi-threaded computing is already getting more complicated, because you need to imagine how threads and processes may interact together and the results these may create).

You can build a host of very interesting things on FPGA's. One is an M&M sorter :), but a not too complex board can already simulate a C-64 and run the game Commando.

Of course, the FPGA gets very interesting when you need to process a large, complex signal. Think about video signals for video compression for example or speech recognition. Lots of research is undertaken there at the moment. But simpler implementations are also possible, for example PID controllers for temperature regulators etc... I do think though that FPGA's are slightly overkill and possibly unnecessarily complicated.

An alternative to FPGA's are Arduino boards, which are basically CPU's again and can also be programmed in C. So a lot of fun when you want a new kind of hobby.

Sunday, March 14, 2010

AI Challenge progress





This video shows some different progress with the AI Challenge. The previous video demonstrated how the computer was directly manipulating the joints through a neural network. In this video, there's a proportional controller attached to each joint, which only tries to get the angles of each joint to some particular value.

These values are set by a joystick that I attached to the computer. I've tried to control the arms directly, but that's basically hopeless. Besides just looking at the position, you also need to control the angular velocities at the same time for three arms at a time. This implementation therefore reduces the "cognitive stress" and already it's starting to make it possible to make predictions and expectations and to (sometimes) actually hit the ball. It remains somewhat difficult however.

So far, I haven't used IK solvers or any complicated math theories to do this, just one observation of angles and a direct reaction to whether that angle is desirable or not. The intention is to see how far I could take this and see if that is actually useful. Right now, I am supplying the angles directly, but progress can still be made to possibly focus on controlling something else (the hand?) and see if the simulation can iteratively figure out how to get there or something. The rest of the solution can then be given to understand the trajectory of the ball in a really simple way, find out when it's in range and where that will be and finally project a path (over time) where the joints actually need to start doing something.

Monday, March 08, 2010

Inductive vs. imperative programming

For work I'm currently looking at LISP programming. Lisp is one of a family of functional programming languages like Haskell, OCaml, Erlang and Scheme. Lisp itself is the oldest of these and it is based on the manipulation of lists (..of lists...(...of lists)). If you look at Lisp code, you'll quickly get dizzy from all the parentheses on the screen.

One interesting property of Lisp is that it can be a huge stream of code intermixed with data, or data becoming code (messages), or code producing more data (recursion etc.). There have been some libraries that were written for Lisp, which gave it more capabilities including screen widgets and so forth. Standard Lisp however doesn't have unification and backtracking abilities like Prolog does. So, even though Lisp has been used in AI applications, it isn't directly comparable with Prolog for example.

This article is a still relevant consideration about the use of Prolog and why it hasn't taken off so much as it could have. Most programmers work out particular problems procedurally themselves (sometimes giving rise to very costly and sneaky bugs), many times due to incorrect control code statements and so on.

Logic programming is an area where you inductively reach a conclusion. When you state a fact, the interpreter confirms that this fact may be stated (is true). If you state a relation with a variable (a query), the interpreter tries to find all possible valuations that do not contradict with any other logical facts or statements made about these valuations. The result can be either null / nil / zero / no or a number of valuations that the interpreter knows about.

Logic programming is inductive programming. This means that some facts are declared ahead of time and then the program builds up some execution tree and finds out the rest. Imperative programming on the contrary means that the programmer decides the entire flow of what the program does, when it does it and how. This is the most common way of programming (C, PHP, C#, VB, C++, python, Java, etc.). So there is no 'hidden' code in any imperative programming besides the grouping of CPU instructions through assembly language -> 2nd generation languages -> 3rd generation languages and upwards.

A recent area of interest is called constraint programming, which is quite similar to logic programming, except that you don't really derive facts from other facts or prove them right/wrong. There are libraries available for a host of different programming languages, including the imperative programming ones.

Now, without a lot of very intelligent optimizations, these solvers would basically run loops over loops over loops and take a very long time to compute queries. This may have a large impact on the usefulness of inductive programming in real-world scenarios. Also, considering the article above, the success of some language doesn't really depend on its capabilities, but on how easy it is to get started with it and how well/fast someone can verify that some intention is working out correctly as intended. In that light, imperative languages are easier to follow and verify, because the entire execution diagram is right in front of you (except for the funny race conditions, deadlocks, non-reentrant code, library errors, static variables and so on).

Constraints are both problematic to code for correctly, but incredibly helpful for coming up with solutions within your own lifetime :). Some article I read used the example of a number of ships for which a schedule needs to be developed. Any berth can be taken at any particular moment in time. Scheduling problems are the best example for constraint programming, because they can have a large number of constraints associated with them and often have a very large number of substitutes (multiplying the number of loops in total).

The idea is that through constraints, you can decrease the number of items that are under consideration, but this is not the whole story. Sometimes constrains are imposed on the combination of values from domain R with domain S. In such cases, the rule can consistently be firing over some iteration mechanism that dumbly retries other valuations, continuously hitting the constraint. The general thing here is that research is focusing on smarter algorithms to bring down the number of iterations that are required.

Why is this all so relevant? Because planning and reasoning systems with formal declarations still depend on this brute-force mechanism of trying out combinations of different values. For very complex problems, it is very difficult to write imperative software that always computes the correct solutions and results for all cases, given an expanding set of constraints that may be imposed on them. The idea is that, once you have a generic iteration mechanism and a generic method for declaring rules and properties of objects, you only need to extend a so-called knowledge base and the system does the rest.

I think however that it is wise to start thinking about blends of programming languages. Either by expanding the compiler to embed the inductive code into the imperative code or by creating embeddable interpreters that can be loaded with particular objects, exposed inside the interpreter runtime and then fired off with a query to find any objects that apply. But certainly, sometimes by restating the problem or by starting off with an intelligent choice made by a human, one can sometimes just resolve the problem directly with procedural code. For schedules however, I don't see that happening so quickly.

Check out the following libraries and projects:

Python: http://labix.org/python-constraint

Minion: http://minion.sourceforge.net/cases.html

C++: http://research.microsoft.com/apps/pubs/default.aspx?id=64335

Java: http://www.emn.fr/z-info/choco-solver/index.html

Saturday, February 27, 2010

AI Challenge



Simon Funk put an AI challenge online, where you need to control two mechanical hands and flap a ball from right to left. The simulation itself is all in python and getting started is really easy.

My approach is extended from some ideas I am looking at with a colleague. The video above are some initial results of my implementation. The best performance is seemingly at the start I reckon, although you can definitely see that the left hand is replaying its strategy once it is getting into the same situation (the ball slowly rolling towards it).

The research is highly focused on how intention, (intrinsic) reward and perceptions from the external environment all work together to hopefully do something useful in the end. It's a great challenge to work on, there are great dynamics in this physical simulation.

I'm using an ATI GPU for the computation, which I hope to extend further in the future to get better results. Notice in the video how the arms don't really move very determined in all cases. For a large amount of the time, they are fighting the gravity and seem to have trouble generating enough energy to overcome the counterforces playing on their 'muscles'. They don't really need to much about the state of the entire world in order to execute some "good" actions (once again, 'good' is in the eyes of the beholder and depends on how much fun something is, social interaction, the benefits it "feels" it gets, etc).

Anyway, these are the results after one day so far. Now let's see if it can be made better.

Monday, February 15, 2010

FlightGear hacking

On the right is an image of a free flight simulator called FlightGear. It's used a lot for research purposes, but certainly also just to have fun and it is licensed under the GPL. You can fly anywhere in the world with the planes provided and the entire framework is reasonably extendable. There is actually a choice for the Flight Dynamics Model that you wish to use. Each FDM has different strengths and weaknesses. One focuses on airflow around the body parts and weight and another one more on the steering and so forth. The objective is realism and trying to simulate how things behave prior to real life development and tests. Thus, that cuts down on the costs of development significantly really. Its objective is not to compete with consumer-level flight simulator, nice flashy graphical details and so on, but the focus is on correctness of the flight model and other items around it.

For example, the airports are correct, the runway placing, approach lights, the sky and environment model are accurate qua stars, sun and moon given the time of day, the handling of the instruments are correct (the magnetic compass lags behind a bit just as in a real airplane), some planes may break when put under too much stress (although the pilot is likely to break before that!). The scenery uses the SRTM data that I also used to do the hillshading in mapnik (see previous post).

There are a lot of customization capabilities for FlightGear too, making it very suitable for research. The way it works is pretty simple. You specify an option parameter that states a direction of input or output (if input, then the simulator accepts an external file or socket for instructions to control ailerons, rudder, etc. ). More details can be found under /usr/share/games/FlightGear/Docs/README.IO if interested. The option looks roughly like this:
--generic=socket,out,10,localhost,16661,udp,myprotocol
So, this chooses a socket transport, outgoing data, 10 times per second, localhost, port 16661, udp protocol using the protocol as specified in the myprotocol.xml file. Easy!

The receiving application can then start processing a stream of data coming from the flight simulator. It can also send back a number of commands to control the aircraft, the environment, sounds, AI models or whatever. Basically, it's quite a nice way to try out a couple of concepts before having to dig too deep into the bowels of the flight simulator package itself. The same methods are actually used to store a flight path of a plane and then replay the flight later (at the specified frequency intervals). The same methods are used to connect flightgear instances together and do some multiplayer flights or track the positions of flightgear users on a large map.

Sunday, February 14, 2010

Hill shading OpenStreet maps


I've been fooling around with OpenStreetmaps again, this time just trying out a couple of experiments that others did and hopefully in the process develop some interesting ideas to use the data. I've blogged about Openstreetmaps before. A couple of things have changed as Karmic came out. Some build steps require you to download more software and some packages may have been removed since then. I've had bigger problems getting mapnik to work, but that was related to the projection of the import of OSM into Postgis. When starting 'osm2pgsql', don't use the "-l" flag, because that indicates conversion to latlong. The standard mapnik projection however is mercator. Most of the times, when nothing shows up in the rendered image, it's a projection problem somewhere. Just verify it all makes sense going backwards from the mapnik process and you should find it quick enough.

Anyway, a very interesting experiment I tried relates to hillshading. This is an effect where elevation data from different sources are merged (nowadays people use 'mashed') with map data in order to shade particular areas of the map to show where the hills are located. Elevation data for most of the world can be downloaded for free from the Shuttle Radar Topography Mission. You should get version 2.1. For the US, there's elevation data available with 30m horizontal accuracy, the rest of the world only gets 90m (or 3 arcseconds). Some tools exist to help you out in managing that data: srtm2osm (I didn't use this) or a script called srtm_generate_hdr.sh (which I did use). Downloaded the data first, then produced the HDR files.

Then run a simple script:

cd /home/gt/srtm/
for X in *.hgt.zip
do
yes | /home/gt/srtm/srtm_generate_hdr.sh $X
done

This basically generates a number of TIF files for each particular region. These TIF files are height maps. When you look into them, you may be able to recognize certain parts of your country, but don't over-interpret the images you see, because the actual height doesn't really show up there.

In the Ubuntu repositories, there is a package called "python-gdal", which is a set of utilities in python to drive gdal utilities. This can easily be used to stitch the generated TIF files together to generate one huge height map for the entire region. I've used this to get a height map for the Benelux for example, resulting in a 55.0MB file.

Problem is that the projection is incorrect, so you need to assign the latlong projection first, then warp the image, reprojecting it to mercator (what mapnik uses) and in the process attempt to take out any invalid data points (set to 32767).

#> gdal_translate -of GTiff -co "TILED=YES" -a_srs "+proj=latlong" combined.tif combined_adapted.tif
#> gdalwarp -of GTiff -co "TILED=YES" -srcnodata 32767 -t_srs "+proj=merc +ellps=sphere +R=6378137 +a=6378137 +units=m" -rcs -order 3 -tr 30 30 -multi combined_adapted.tif warped.tif

Cool! So we now have a warped.tif in mercator projection that is basically an elevation map of the terrain. This is however not yet an image which uses the elevation data to 'shade' particular areas of the map. Think of putting the elevation data under a spotlight and then moving the spotlight to some particular origin (somewhere NW), located high above the map. This would create shady areas on the parts of the map where there are hills facing away from the lightsource. The other sides would be normally visible.

Perry Geo luckily did this work for me. You can download his utility here. I had to modify the Makefile to set the GDAL include path (-I/usr/include/gdal) and modify the included gdal library (gdal1.5.0). These tools create a 400-500MB hillshade file (18555x24128 pixels) if you use it for the entire Benelux region. That's still manageable, but in the process of getting there you may need 4GB of memory and a fast processor. The following image shows a minute detail of the Dutch coastline (scaled down 33%).

So that's cool. This image can be used as a bottom layer for some mapnik generated tiles. If mapnik then paints other layers above it slightly translucent, the shading will slightly shine through the image, creating a sense of height throughout the map.

A standard mapnik image from a region in Belgium, close to Maastricht which has a number of hills looks like this:

The same region in Google Maps, rendering terrain data, looks like this:

So, my rendered image looks different from Google's, but the styling wasn't optimized for terrain data in the mapnik renderer.

There's also a reason why the zoom level wasn't increased to about 18 or so. Remember that we downloaded the SRTM3 set, which provides 90m accuracy in the horizontal plane. The height map therefore interpolates between subplanes of equal elevation. This doesn't necessarily improve quality :). Google Maps doesn't go beyond zoomlevel 15, which is a reasonable one. Trying to render images at increased zoomlevels creates pixelated images that don't look nice at all. The height map can improve slightly with better algorithms, but no matter what you do, it will never be perfect. Google Maps even has a couple of areas with hills that look a bit blotchy, irregular or pixelated. The idea is just to get a sense of height of a mountain range anyway and drawing the contours around this map certainly helps to find out where the mountains are (especially for hiking and cycling maps, which use these techniques regularly).

Original sources with the tutorials are here and here.

Friday, January 29, 2010

ATI Stream on Ubuntu 9.10 Karmic

Just as Nvidia has CUDA for GPU programming, the ATI cards also have an SDK to get those hardware-threads revving for solving complex, scientific or brute-force problems, called ATI Stream. I have a 64-bit OS with a quad-core Intel i920 and one HD5850 ATI Radeon on Ubuntu Karmic 9.10. On the 27th, some new drivers for the ATI card were released on the ATI website, which I think together with the nopat flag have resolved my problems getting the SDK to run.

After downloading the SDK, you need to set the LD_LIBRARY_PATH for the system to find the opencl shared libraries and whatever else is in lib. It's actually not as easy to find the installation documents, they're hidden 2-levels deep in links, but here's the full documentation for the SDK (the link to which could be stated more visibly on the ATI Stream page).

Officially, ATI Stream is not yet supported for Ubuntu 9.10. I initially got only segfaults for any application or it just wouldn't find devices even when the latest Catalyst drivers from the ATI site (27-Jan-2010) were downloaded and installed and a full restart was performed. However, when the "nopat" option is supplied as a kernel boot parameter, things work a lot better :). Right now, most samples seem to run except for one specific one that my card doesn't seem to support. Because Karmic uses grub2, the location for modifying kernel boot parameters changed. You need to modify /etc/default/grub instead of /boot/grub/menu.lst. I inserted nopat here:

GRUB_CMDLINE_LINUX_DEFAULT="quiet splash nopat"

After these modifications, the /usr/lib/OpenCL/vendors links and the environmental changes for LD_LIBRARY_PATH, yours should be working as well.

There is some more information about OpenCL, which I think is a very nice advance into ensuring portability of GPU code to other platforms. A very good explanation about CPU vs. the GPU can be found here :).

I'm planning to use it for some really new and innovative experiments involving different perspectives on neural networks, network spiking and so on. The idea is that I need a large number of parallel processors, which can be very modest in processing power, as they only need to move a very bit of data and perform extremely simple processing steps. The details and the complexities of the work is in the synchronization, so I'll take some looks into that :).

Wednesday, January 27, 2010

What knowledge may actually be about...

I've been cycling in the rain today and suddenly got this awesome thought train. Nothing much to do with rain, but I guess that the cooling characteristics of the cold rain with the cold weather probably caused some superconductivity somewhere. I can't get into too much details what I've come up with to resolve the below general and (as I argue) incorrect assunptions, but I can at least discuss the problems I perceived that might restrict the ability to develop more intelligent behaviours in computer programs. :)

To give you a starting frame of thought, I'm arguing that there are many assumptions about the origin, extent or representation of knowledge in many artificial intelligence reasoning models, in neural networks and whatever else is there. Here is why.

Most computer programs function by taking some parameters from an environment, file or whatever as input and based on that perform some action. A program without input or output is not a computer program. The general idea is thus that by applying some function F(X) on a range of input parameters X, one can derive an action or actions Y that should most logically ensue. The diagram here helps to illustrate this further. It is a depiction of a so-called Markov diagram. These are often used in A.I. to reason about and between states. One can move from state to state along the transitions, but the arrows also restrict movement to just any other state. The diagram need not be statically defined a priori, there are sometimes ways to dynamically extend the diagram at execution time, most of the times determined by a set of rules. M here is the entire world, consisting of possible transitions or relations R, states S (which is more of a placeholder in this case) and measurable parameters T from which you determine the current state S.

The above model works very well for a set of discrete parameters, since they always fit into one single state. For continuous parameters however, it becomes more difficult, because if every single value is considered, the number of states in the model would become infinite. Hence, classification is needed to reduce the number of states, or the development of some kind of 'probability distribution', where one is actually a little bit in all states at once, or one can come up with a fuzzy reasoning method for reasoning between just two states S1 and S2, which are closest to the current 'continuous' state.

The huge assumption made here is that all information leading to some desired action can be derived from a snapshot of the external world, just by inspecting some range of percepts X. Reasoning and intelligence is then reduced to the application of some function F(X), even though this can be quite a complicated affair when there are a possibly very large number of percepts X or a wide range of possible actions Y. The complexity due to the dimensionality of the problem is irrelevant for this conclusion however. Even more worrying here is that there's only one single assignment of intention or purpose in this entire system. The purpose is the definition of the function F(X) in itself, but it'll be difficult to change this as soon as the system has been constructed or trained... Hmmm... :). So one cannot expect this system to generalize a bit and then specialize further into other things.

So, resuming... having a function F(X) implies a direct, causal relationship between (a range of) perception(s) and a most logical (range of) action(s), which only holds if the purpose is fixed and pre-defined and doesn't change. Or worse... the context does not change. Also, knowledge is then only defined as the function that needs to be applied to the percepts in order to derive the action Y, it is not contextual knowledge about what is required in which context. In effect, the only way to make the system more able to deal with situations is to measure more and more in that single snapshot and then trying to fit the function F(X) to suit those measurements.

However, instead of considering that it is the state(s) embedding the information, one should consider that it is the transitions that allow one to collect the real knowledge about events, since transitions embody relationships. The transitions maintain the real information about some state S1, the next state S2, the difference in the percepts, the action(s) that was undertaken and whether S2 is actually a better state to be in when compared to S1, so deriving whether the action was desirable or not, given a certain context. Note that this doesn't yet require much information about a goal state Sg, so one might as easily conclude that there is no direct need to know about the eventual goal state or have a real conception about what it looks like, we can at this point still assume we're slowly and gradually moving towards the goal state and there's still a capability to change direction or impact the environment to reach the goal anywhere (but this is getting too complicated at this point).

This is why I think that discarding the thought that there is a causal relationship between percepts and most likely or desired action should be a first objective in order to develop more intelligent systems. Knowledge is more likely some kind of imagination or dreaming of the effect of actions from any given particular 'general state' and the kind of changes in perceptions how one can measure such progress, all this framed into a particular context. This should allow systems to reason with shorter horizons or reason at different levels with different horizons, but always reason with specific and particular contexts at each level. The definition of how many transitions you allow before making conclusions, or the extent of correlation between events is then part of the game and part of the experience...

Monday, January 25, 2010

Cybernetics

For my work, I've been looking at neural networks in more detail, but specifically how they may be applied to problems with temporal properties. Most artificial neural networks do not store their values or activations as some kind of remanent activation very well. Such neural networks can only work in situations where the input applied to the network is complete enough to derive conclusions from it. In that case, it doesn't matter if there is a known formula for the correlation between input and output values or whether there is one, albeit a complex one, that is being approximated. Such direct correlations after one single frame of observance is the typical neural network that you get today. More recent developments also give you recurrent networks or LSTM cells, but those model patterns or 'data' over time. Thus, they establish correlations or relations between sequences of events. For all these networks, you'd generally expect a mathematical explanation or approach to back up the learning methods applied for it (if they haven't been trained with evolutionary algorithms).

Even in the case of evolutionary algorithms though, there is significant complexity involved in training the network so that it performs well. Unless the input/output correlation between classification or pattern recognition is very strong, which makes any problem quite easy. Basically, this means that in the same way that a formula calculates a set of output value(s) in a deterministic way (and 1+1 is always assumed to equal 2 and never changes), a neural network is just a very deterministic approximator. Given a trained network, any two inputs yield always the same output. This is true, unless you use an RNN. But the RNN is designed to work on temporal problems, so given the same sequence, this yields the same output to classify or reproduce the sequence.

The picture above shows a neuron receptor that is involved in a process called chemo-taxis. This process allows the worm to navigate in an environment where food is available. The worm has no eyes, can feel heat (thermotaxis), and wriggles its way within some environment. If the worm is wriggling towards a food source, it's climbing up an increasing gradient where the chemicals picked up by the neuron increase. When it climbs up an increasing gradient, the worm is less likely to make sharp turns. If the worm is on a decreasing gradient or doesn't detect any food source, it is more likely to make sharper turns.

Such a problem sounds very simple to resolve, but remember that we have eyes. How do you locate a particular source of smell if you only have a nose? You need to move around in a room, being careful not to cause any harm to the body. Depending on the sensitivity of the olfactory sense and the distance of the smelly source, the distance between one sample and another must be larger or may be smaller. The samples also must be taken within a certain amount of time, otherwise no significant difference can be observed.

The above shows how some organism, actor or agent must interact with the environment in order to sense it and make conclusions about the layout or composition of the environment. Without the ability to perform actions in the environment, I don't think there can be any development of intelligence at all.

Such statements are derived from a particular field of knowledge called 'cybernetics'. This sounds like some science fiction term I'm sure, but it's not just related to cyborg, cyberspace, the internetz or what have you.

Cybernetics is a recent term from the 40's and 50's defined by Norbert Wiener. The word is derived from the greek "kybernētēs", which means helmsman, rudder, etc. and has the same root as government. It was initially intended to study self-regulatory systems, but quickly expanded to other areas like management (Stafford Beer), biology and also computer science. The science is quite broad in scope now and poses questions about how systems make sense of their environment by interacting with it. Finding out what an environment is about isn't exactly the same as just perceiving it.

The difference with Artificial Intelligence is quite strong. Cybernetics is more theoretical, whereas A.I. has basically just gone ahead with a lot of assumptions, trying to wrap reality into mathematical models and executing them on a computer. My criticism of A.I. until this point is that it is simply too deterministic for anything 'new' to come out of it. The term A.I. has been a bit bold as well. Sure, we have large-scale systems analyzing emails and other kinds of data and knows how to extract information from it to make predictions, classifications or specific groupings of data. But those capabilities have been intended by designers. There is nothing that such algorithms or machines can ever do different but execute those particular implementations.

In that sense, expecting anything truly intelligent to come out of A.I. as it is currently approached (through mathematical formulas) is very hopeful at best. A better understanding of knowledge, its roots and how it may be represented over time and interacts with new environments is needed.

That is not saying that A.I. is useless. It's saying that A.I. certainly has approaches for doing pseudo-cognitive work by helping out massaging details out of very large mountains of data or finding specific correlations that we cannot even imagine. So there's certainly room for the A.I. as we know it now and some new kind of vision on what truly intelligent machines can bring us. Those kinds of machines however need a different basis than just mathematics and strong correlative behaviour. They need to find out for themselves what is important and have their own ways of interacting with the environment (which is how they find that out :).

Monday, January 11, 2010

Neural network dynamics

The picture to the left is an LSTM cell that can be used in some neural networks to 'remember' sequences of previous inputs. It can therefore re-create similar outputs as have been observed in previous runs or it can be used to associate one thing with another in temporal terms. Anyway, the reason for posting today is that there are particular dynamics that one should understand to choose the right 'kind' of network or even if one should use a neural network anyway. The more obvious design criteria are related to explain-ability of certain classifications or outputs. If you expect a neural network to give you reasons for why it indicated a certain classification or output, you're out of luck. So they have limited use in knowledge based systems where there must be traceability of the observations that lead to some conclusion or the observations that need to be taken in order to derive a certain final conclusion (enrichment and convergence towards a certain diagnosis for example). So in such cases, you should definitely use different technology.

Input signals can be interpreted or preprocessed in many ways and the exact method that you choose to model your network may have complicating effects on the design you require in the neural network that is supposed to resolve the problem. For example, if you have a mine sweeper as in http://www.ai-junkie.com/, then it is given its own orientation and the direction to the closest mine as input. Then you have a couple of weights and the end result is the output at two terminals, which is defined as the activation of the right and the left track of the mine sweeper. The overall goal is to get mine sweepers that consistently reorient their own direction to match the direction of the closest mine, such that they can clean up the mines as fast as possible.

However, another possible design choice is to use the distance to the closest mine instead. This really changes the entire problem scope, because a single 'frame' of the entire situation doesn't immediately provide all the information that is necessary such that the tank can be directed to the tank. Maybe this reorientation of the tank isn't successful from frame 1 to frame 2, but certainly in the direction/orientation approach, you can rest assured that you can guarantee convergence to match the two together and the ability to train a network to exhibit this obvious correlation (and basically behaviour).

In the case of distance however, the mine may be in a radius around the tank at any distance. The only way in which the tank can find out more about the actual location of the mine is to choose a single action and observe the difference in the distance. This particular action therefore is a very important key decision that determines the action that the tank should take in the frame thereafter (the time between frames in a simulation isn't necessarily 0.0000001 seconds, we could easily take 1 second and be happy with it. It does determine the resolution and accuracy of the end solution, but even minor fluctuations should provide this information).

So, the reasoning that takes place here cannot be executed successfully by observing a single frame of information. In other words, you need changes in the external environment, sometimes induced by your personal actions, in order to determine what happens next. This often occurs in robotics or other controller situations, where the relation or 'directionality' is not always known. Or sometimes you can derive it, but you don't know how you should react to it. Also, changes induced by other forces in that environment will then allow the system to react to those in similar terms, since the observation is changing.

The point is that there are certain dynamics in real-life scenario's that standard feed-forward neural networks can never deal with. Because FFN's must have full information available in a single frame that conclusively can result in the output situation to converge to some expected result. In cases where the external environment has a larger reaction period... for example the temperature of cooling water for a very large diesel engine, these neural networks will very likely never be able to react successfully, because they do not understand or embed the concept of memory.

This is why the type of the network is important and why there has been so much research into Recurrent Neural Networks. These RNN's have the capability to store observations of a number of past events into the memory of the network, such that the observations made in history impact the actual decisions that are taken at the output. Standard RNN's can remember information for about 10 timeframes (whatever the time resolution is you've chosen), whereas LSTM's have the capability to remember significant events up to 1000 timesteps. The idea is that significant reoccurrences of some events cause these cells to suddenly behave different and indicate to output neurons that some event is reoccurring, inducing a different kind of response than in other, more regular or random situations.

Now... there's a worm on this earth called Caenorhabditis elegans, which has exactly 302 neurons. This worm reacts to the smell (chemical concentration) of bacterial residu, because it knows that it can feed on the bacteria that are necessarily present there. Some bacteria infect the worm and harm it, whereas others are excellent feeding grounds. It innately avoids the smell of some types of bacteria that are harmful, but there are two types of harmful bacteria that it is especially attracted to. Lab research has shown that after exposure to these two harmful bacteria, it learns to avoid them later. Other behaviour includes social feeding, where worms gather together on large piles of food, up to some threshold determined by the amount of oxygen that these worms observe by one or two sensor neurons that detect oxygen.

If you ever wonder what a neural network in biology looks like, here's a full description of such a network. You can trace the network from sensor neurons to motor neurons and the actual muscle. But beware! You'll also see that this type of network is extremely intricate.

This shows that the dynamics of particular problems aren't necessarily obvious. Those things you can observe and how they interact with other dynamics of the problem interact together to which a solution has to be found that doesn't violate critical constraints, but still allow the problem to converge to some optimal solution.

Monday, January 04, 2010

Fitness functions

I'm reading up on Genetic Algorithms and the most important thing for these algorithms is to choose a correct fitness function. This is a function that determines a score for the performance of a certain instance or candidate for the solution or closest approximation of a given problem.

For some mathematical problems, if you have a set of data that you wish to approximate, this fitness function can be given by, for example, the root mean square error of the differences of the calculated result and the known result. A neural network wouldn't be used if the actual function was available, so let's assume that the problem is somewhat hard and cannot be approximated appropriately with either a rule or a function approximation.

Neural networks are sometimes trained using genetic algorithms by gencoding of the neuron weights, randomizing these in the first generation and then incrementally mutate, mix, pair and select these network instances until one network is found that seems to perform appropriately.

Eventually, after 50 generations or so, networks emerge that exhibit the desired behaviour expressed in the fitness function. But if we take this as an analogue to the biological world (where both ann's and ga's come from), then this fitness function isn't a single expression.

If what Darwin says it's true, imagine the time it must have taken to evolve from simpler organisms into more complex ones and the evolutions and changes that must have occurred in populations. The genetic effects are measured over the entire population (not on individuals).

For computers, we assume the role of overall biological system, but I argue that this is only suitable for the simplest of cases (assuming this role actually means defining the fitness function).

Besides considering plain survivability of a particular instance, the social behaviour of the overall group should also be considered (the generation that the individual net is part of). Some animals for example increase their survival rates by working together on occasion, which may leave room for other developments to occur that are highly favourable (although negatively impacting survivability). And if one individual succeeds in subverting or influencing another individual to their own gain, then this is one thing that should be taken along in the fitness function.

Come to think of it; many GA's are only used during a training session, but discarded otherwise. Most neural network training so far has been about pursuing a particular unknown function with a large amount of observational data. But each network generally is constructed as a lone individual in the entire population. still, there is at least some research that has been undertaken in the area of neural network ensembles, where cooperation is sometimes used to solve sub-problems, or in the application of environments where multiple objectives are present. As such, successful combinations of neural networks are what count most, not individual results. So, cooperation becomes an important factor for individual survival.

As with the previous post, for anything interesting to come out of neural networks, it may be necessary to find a fitness or cost function of a very complex environment in which this neural network is supposed to execute actions. This sounds really easy, but consider an example of a robot that needs to find a way through a corridor as fast as possible.

A simple fitness function is a measure of the amount of time taken to reach the end of the corridor. We may now feed the robot some sensory data, for example when it bumps into a wall. We always start off a robot in the correct direction. The robot can rotate two tracks on either side. Rotating a track faster than another makes the robot turn to one side, such that it gets a steering ability. Rotating both tracks to the same speed make it go forward.

You may think that the robot that goes fastest wins, but then the scientist sees that the robot has so much speed, it hits the wall with unforgiving force and breaks off a track. So a very stern measure would be to restrict the speed of the tracks, such that none of the individuals can move at that speed. A different solution however is to somehow factor in this speed or wall-hitting force and penalize those robots where this occurs often. Then we may have two different kinds of winners:
  • Robots that still maintain a very high speed, but hit the walls sometimes
  • Robots that maintain lower speeds and gradually arrive at the end of the corridor in good time.
Both strategies have their advantages and disadvantages. The one that is faster can also run faster from danger and therefore can maybe survive better. The one that is more careful has less chances of considerable harm.

So the judges are out on all of this technology. For specific tasks, they work because we can think of a suitable fitness function for them. As soon as things get tougher and wider though, the environment needs to penalize and reward those individuals appropriately. Good environments also allow for diversity in the population. And then one wonders whether such diversified elements continue to specialize in their own populations and wander away from their original ones. A bit like evolution outside of their normal populations.