Archive for 2013

Spiking Neural Network driving a car in 2D environment

This time I would like to present one of my projects that I did as an assignment for “New trends in neural calculations” and “Soft Computing”. The objective of the assignment was to create an application that solves some problem using advanced type of neural network trained by a differential evolution algorithm. As the topic says, I chose to create a simulation of a car in 2D environment with top-down view which was driven by a driver based on a simplified spiking neural network and trained by a differential evolution algorithm. The chosen problem was based on a paper Evolutionary Spiking Neural Networks as Racing Car Controllers by Elias E. Yee and Jason Teo[1] in which they did the same thing but in 3D environment and with more sensors.

SNN application windowThe application is based on the SDL[2] and Box2D[3] as a base components. SDL is used to handle key events and to initialize the context of an OpenGL with a window. Box2D is used to create physics environment in which the car will move. To simulate the car I used a ready-made solution that implements top-down car[4] which matched my needs perfectly. Other elements like implementation of spiking neural network, differential evolution, plots, sensors and the race track I wrote by myself. I plan to describe them in details in further posts.

The final application is presented in the attached picture. It is controlled from main window but all informations (about current mode, keys, time) are displayed in console window. Application runtime is divided into two modes. The first is used to test the simulation with arrows and the second is used to control the neural network driver training and the third to see the results of that training.

The results of the project are quite surprising. Although the implementation of spiking neural network was as simple as possible, it managed to complete the S-track presented on the screen in reasonable time (~8s), after 3468 generations of differential evolution.

The source code is available at github and binaries are here.

References

  1. Yee E. and Teo J. 2011. Evolutionary Spiking Neural Networks as Racing Car Controllers.  11th International Conference on Hybrid Intelligent Systems (HIS 2011), pages 411-416, Melaka, Malaysia, December 2011. []
  2. http://www.libsdl.org/ []
  3. http://box2d.org/ []
  4. http://www.iforce2d.net/b2dtut/top-down-car []

Reading RFID tags on Android

As promised some time ago, this post will be about Android.

About half year ago I bought Samsung Galaxy Nexus as my first Android phone and I found one thing interesting – the Near Field Communication (NFC).

Near field communication (NFC) is a set of standards for smartphones and similar devices to establish radio communication with each other by touching them together or bringing them into close proximity, usually no more than a few centimeters.[1]

In short, this is a technology based on RFID[2] tags that allows smartphone to do 3 things:

  • read and write RFID tags,
  • emulate RFID tag,
  • send small amount of data between devices in small proximity.

The first one can be used to read tags that matches MIME types on the device to activate some functionality, configure the device or just to read cards that uses the RFID technology. It’s also possible to write to those tags. The second enables the device to behave as RFID tag for another devices. And the third is used for communication between two devices, mostly to setup another, more powerful connection type such as Bluetooth or WiFi.

In this post I will show how to read data from the RFID tags since I don’t have any available card to write to. Fortunately this task is quite well covered by Android SDK[3] documentation so I will just write a quick setup of the basic project. I assume that an empty project is created with basic implementation provided by Eclipse or Android tool from SDK.

Enabling NFC in the project

First of all, to enable NFC in the project the modification of the AndroidManifest.xml file is required. The NFC is available since version 10 and requires special permission – android.permission.NFC. To enable it just add following code to the manifest node:

1
2
3
4
5
6
7
8
9
10
11
12
13
<uses-sdk 
   android:minSdkVersion="10" 
   android:targetSdkVersion="15" 
   />
 
<uses-permission 
   android:name="android.permission.NFC"
   />
 
<uses-feature 
   android:name="android.hardware.nfc" 
   android:required="true" 
   />

uses-feature entry means here that the application requires NFC and won’t work without it.

Since RFID tags are read and dispatched by the Android, application must register an Intent filter and a Techlist to get them. To do this add following code to activity node in manifest file:

1
2
3
4
5
6
7
<intent-filter>
   <action android:name="android.nfc.action.TECH_DISCOVERED"/>
</intent-filter>
<meta-data
   android:name="android.nfc.action.TECH_DISCOVERED"
   android:resource="@xml/techlist"
   />

There are free types of actions that can be used with NFC – android.nfc.action.NDEF_DISCOVERED, android.nfc.action.TECH_DISCOVERED and android.nfc.action.TAG_DISCOVERED. I chose the android.nfc.action.TECH_DISCOVERED because none of my RFID chips had NDEF messages and TAG, as the documentation says, is too general. Also TECH just worked.
As you can see the code also specifies the techlist xml file. This file contains a list of NFC technologies supported by the application. @xml/techlist means that this file has name techlist.xml and lies in res/xml/ directory. Following code shows an example of my file:

1
2
3
4
5
6
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
   <tech-list>
      <tech>android.nfc.tech.MifareClassic</tech>
      <tech>android.nfc.tech.NfcA</tech> 
   </tech-list>
</resources>

This covers basic setup of NFC but requires the user to specify the application which will handle the Tag everytime it is read by Android. It is quite annoying so Android allows to register an Activity in the foreground to be the default one for handling Tag intents. To do that add following code to your Activity class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
private NfcAdapter mAdapter = null;
private PendingIntent mPendingIntent = null;
private IntentFilter[] mIntentFilters = null;
private String[][] mTechLists = null;
 
public void onCreate(Bundle savedInstanceState) {
   /* ... */
 
   mAdapter = (NfcAdapter)NfcAdapter.getDefaultAdapter(this);
 
   // Creating PendingIndent for foreground dispatching
   mPendingIntent = PendingIntent.getActivity(
         this, 
         0, 
         new Intent(this, this.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 
         0);
 
   IntentFilter tech = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);
   try {
      ndef.addDataType("*/*");
   } catch(MalformedMimeTypeException e) {
      throw new RuntimeException("fail", e);
   }
 
   mIntentFilters = new IntentFilter[] { tech };
   mTechLists = new String[][] { getTechList(this.getResources()) };
 
   /* ... */
}
 
public void onResume() {
   /* ... */
 
   mAdapter.enableForegroundDispatch(this, mPendingIntent, mIntentFilters, mTechLists);
 
   /* ... */
}
 
public void onPause() {
   /* ... */
 
   mAdapter.disableForegroundDispatch(this);
 
   /* ... */
}
 
private static String[] getTechList(Resources resources) {
   ArrayList<String> list = new ArrayList<String>();
   XmlResourceParser xml = resources.getXml(R.xml.techlist);
 
   // Assumed simple parsing because of simple file structure
   for(;;) {
      int eventType = XmlPullParser.END_DOCUMENT;
      try {
         eventType = xml.next();
      } catch (XmlPullParserException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
      } catch (IOException e) {
         // TODO Auto-generated catch block
         e.printStackTrace();
      }
 
      if(eventType == XmlPullParser.TEXT) {
         list.add(xml.getText());
      } else if(eventType == XmlPullParser.END_DOCUMENT) {
         break;
      }
   }
 
   return list.toArray(new String[list.size()]);
}

In short, this code creates an instance of PendingIntent, IntentFilter for TECH_DISCOVERED action and all MIME types (see */*), and loads list of supported technologies from file specified earlier. Those objects are then used in onResume and onPause methods to enable and disable foreground dispatching so the application could handle the Intent before others.

Handling NFC intent

Reading NFC tags is easy. Android provides classes to read tags from some technologies such as those specified earlier in techlist.xml. In this post I will also show an example that utilizes the MifareClassic class. MIFARE Classic[4] is a standard that defines tags with blocks of data that can be written to. The one that is commonly used is a MIFARE Classic 1K which can hold 1 KB in 16 sectors with 4 blocks each. Each sector is secured by pair of 48-bit keys – first for read access and second for write access. There are 3 commonly used keys that by default protect all sectors and allow the access to them if hadn’t been changed – KEY_DEFAULT, KEY_MIFARE_APPLICATION_DIRECTORY and KEY_NFC_FORUM.

Ok, lets try now to handle an Intent with RFID tag. First of all, there are two moments when Activity can handle an Intent. First is when Activity is registered as a handler for this type of intents and second is when Activity is already on the screen. To handle both situations add following code to your Activity class:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Override
public void onCreate(Bundle savedInstanceState) {
   super.onCreate(savedInstanceState);
 
   /* ... */
 
   // Passing intent
   Intent intent = getIntent();
   resolveIntent(intent);                 // This handles first situation
}
 
@Override
public void onNewIntent(Intent intent) {
   resolveIntent(intent);                 // This handles second situation
}

When Activity is created because of the NFC Intent it can be retrived in onCreate, but when Activity is already on the screen and handles this type of Intent you must override the onNewIntent method to handle it.

Ok, but how to exactly handle the tag Intent? Following function does that for MIFARE Classic tag:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
private void resolveIntent(Intent intent) {
 
   if(NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction())) {
 
      Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
      MifareClassic mfc = MifareClassic.get(tag);
 
      try {
         mfc.connect();
 
         mLogger.pushStatus("");
         mLogger.pushStatus("== MifareClassic Info == ");
         mLogger.pushStatus("Size: " + mfc.getSize());
         mLogger.pushStatus("Timeout: " + mfc.getTimeout());
         mLogger.pushStatus("Type: " + mfc.getType());
         mLogger.pushStatus("BlockCount: " + mfc.getBlockCount());
         mLogger.pushStatus("MaxTransceiveLength: " + mfc.getMaxTransceiveLength());
         mLogger.pushStatus("SectorCount: " + mfc.getSectorCount());
 
         mStatus.setStatus("Reading sectors...");
 
         for(int i = 0; i < mfc.getSectorCount(); ++i) {
 
            if(mfc.authenticateSectorWithKeyA(i, MifareClassic.KEY_MIFARE_APPLICATION_DIRECTORY)){
               mLogger.pushStatus("Authorization granted to sector " + i + " with MAD key");
            } else if(mfc.authenticateSectorWithKeyA(i, MifareClassic.KEY_DEFAULT)) {
               mLogger.pushStatus("Authorization granted to sector " + i + " with DEFAULT key");
            } else if(mfc.authenticateSectorWithKeyA(i, MifareClassic.KEY_NFC_FORUM)) {
               mLogger.pushStatus("Authorization granted to sector " + i + " with NFC_FORUM key");
            } else {
               mLogger.pushStatus("Authorization denied to sector " + i);
               continue;
            }            
 
            for(int k = 0; k < mfc.getBlockCountInSector(i); ++k)
            {
               int block = mfc.sectorToBlock(i) + k;
               byte[] data = null;
 
               try {
 
                  data = mfc.readBlock(block);
               } catch (IOException e) {
                  mLogger.pushStatus("Block " + block + " data: " + e.getMessage());
                  continue;
               }
 
               String blockData = Common.getHexString(data);
               mLogger.pushStatus("Block " + block + " data: " + blockData);
            }
         }
         mfc.close();
 
      } catch (IOException e) {
         mLogger.pushStatus(e.getMessage());
      } finally {
         try {
            mfc.close();
         } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
         }
      }
   }
}

At first the tag is retrived from the Intent by method getParcelableExtra with argument of NfcAdapter.EXTRA_TAG. Then using static function from MifareClassic the object of this class is created from tag. The next step is to use connect method to establish the connection. At the time of connection the card must be close to the reader till the end of this method.
To actually read the data of any block the sector that this block belongs to must be authenticated with matching key. This is done with method authenticateSectorWithKeyA which expects an index of the sector and 6-byte authentication key. After authentication it is possible to read all 4 blocks from this sector which is done by method readBlock that expects an absolute index of the block (not relative to sector). Finally after doing all operations the close method should be invoked, even if an Exception occurs because it doesn’t close the connection by default and may cause a problem when trying to read the same tag with other technology.

Summary

Reading an RFID tag is pretty easy on Android devices as the SDK provides some high level API to do that. As I read the Android Beam is also supported with nice easy to use class. Unfortunately there is a problem with emulation of RFID tags because there’s no official API to for this kinds of operations as some people say[5]. On the other hand the device supports that and it is possible to build an Android with some support of this[6]. I shall try it when I would move to CyanogenMod.

The actual code of what I am doing with my phone and NFC can be found on GitHub here.

References

  1. http://en.wikipedia.org/wiki/Near_field_communication] []
  2. http://en.wikipedia.org/wiki/Radio-frequency_identification []
  3. http://developer.android.com/guide/topics/connectivity/nfc/nfc.html []
  4. http://en.wikipedia.org/wiki/MIFARE []
  5. http://forum.xda-developers.com/showthread.php?t=1368907 []
  6. http://forum.xda-developers.com/showthread.php?t=1281946 []