Wednesday 21 January 2009

End-project. PART XIV



Date: 21 01 2009
Duration of activity: ?
Group members participating: all group members



1. The Goal



The goal of this lab session is to make final adjustments to the structure, and code, and try to write correctly the whole alphabet.

2. The Plan




  • Write correctly robot's name 'THOMAS'.

  • Practice to write the whole alphabet.

  • Work further on the idea of string passing via bluetooth connection.



3. The Results



3.1. Writing the name



Last time time we (PC-side-)plotted ``THOMAS'' and it showed that this word is written correctly. This time we tried actually writing it. It still needs some adjustments for the equal alignment of the letters and some adjustments so the pencil would be placed on the paper on the right time.



After making the robot writing it's name in a correct fashion, it was time to see how precise the letters are each time, which can be done using the technique of multiple overlapping drawings.



3.2. Writing the alphabet



We got the idea that we should make the robot be able to draw general English words. Implementing this idea, all English alphabet letters and a 'dash' symbol were (excruciatingly!) defined.

Before trying each letter with actual pen-on-paper, an evaluation was done using the GradientInterpreterPCSideDumper, which can be used in stead of the actual GradientInterpreter implementation, when driven with the PCDriver. The alphabet looks like this (note that the Z character couldn't fit, and that the algorithm left it out.):




There are some results of testing made over all these letters.


3.3. Handler layer


The Handler layer, currently filled by a BogusHandler and various other not-similarly named classes, is the user of the layered architecture (which is also the reason there's no interface for it, nor any naming convention). This has been extended with an:

InteractiveHandler

  • write(String string) The parameter is a string to be put to print. Returns after the movement has completed.

  • move(float[] change) The parameter 'change' signed change in position (in mm) to move. Returns after the movement has completed



ShapesCatalog
The definitions of shapes began to become complicated, and the raw definitions were moved into their own class, the ShapesCatalog. Most shapes are parametrized by an offset-vector, at which they'll set their origo.


  • drawAShape (float[] at) draws a letter 'A'.

  • etc.

  • drawZShape (float[] at) draws a letter 'Z'.

  • drawDashShape (float[] at) draws '-' shape.



3.4. LetterHelper


The LetterHelper handles issues specific to letter shapes. Those of course include that of easily printing them in sequence, and to have an easy interface for entering new strings for printing.


  • printString(String what, float[] at) prints a string at a given offset, compensating for necessary line breaks and out-of-space conditions. Uses printChar() as a delegate.

  • printChar(char what, float[] at) prints the character given as it's drawn with the appropriate draw?Shape() method of ShapesCatalog.




3.5. Remote controlling



An effort was made to try to remote-control Thomas, and in particular, to be able to have Thomas draw strings that are entered from a Bluetooth connection. But this turned out to be much more troublesome than expected. (Note, though, that this was declared to be a bells-and-whistles extension to our project).

BTCmdSender

  • BTCmdSender(String nxtname, String addr, String cmd) a class constructor dealing with connecting to an NXT via Bluetooth; sending bits; closing connection. nxtname and addr are for communication with the right NXT, and cmd is one String containing the command with parameters to be send to the NXT. The class will terminate after sending cmd, use multiple instantiations of this class to send multiple commands.



BTCmdReceiver

  • startRececeiving() tries start listening, if it does not succeed, an error message is printed.

  • startListening() starts the looping of listening on the BT line, parse command and listening again.

  • readLine() reads chars on the BT line until '\n', and return a string version of the line.

  • openConnection() opens all used connection needed.

  • closeConnection() closes all used connection that has been opened.



3.6. Various drivers



  • BTCmdRecDriver is the receiving end of the Bluetooth communication. Thus, the lejOS-side of things.

  • PCCmdBTDriver is the host side of the Bluetooth communication, which is run on the PC side.



The lejos sourcecode is shipped with some examples, two of these being a receiver and sender of integers via a BT line. Those two examples were the primary inspiration for making our BT communication classes. But it turns out that using BT to do anything else then exactly the same as their examples do, is extremely difficult (and time consuming).

There is basically two classes we are interested in:
java.io.DataInputStream
java.io.DataOutputStream

These are the ones containing all the method for sending and receiving ones the connection has been established (and the ones not working like one would like).

The goal for this BT communication is to be able to communicate with the NXT via a simple protocol and be able to execute commands on the NXT through the sent data.

The protocol is textual and line based, first line being the command itself and the next lines being the parameters to the command. From this it is clear that every command must have a fixed number of parameters, so that the receiving end knows when to stop trying to receive.

That was the protocol, now for the sending and receiving. According to the API we should be able to use the method public final void writeChars(String s)[1] which writes the whole string (ending with a '\n') on BT line. And in the receiving end use public final String readLine()[2] to read a whole line, thereby effectively sending strings between the PC and the NXT.

But as it turns out, this is not fruitful. This just doesn't work. A guess to why, is because we are actually trying to send a java.lang.String object (presumably serialized as a Java object), and what the receiving end is trying to parse is a sequence of chars forming a line.

So after a whole night of trying to get the obvious to work, this method was rejected. Instead we defined our own readLine() method:
private String readLine()
Which basically puts chars on the BT line into a buffer until a '\n' is received, and returns this buffer as a String.
On the sending end, each string needing to be send is converted into a char-array and sent one char at a time.

This approach worked, somewhat.

As a general observation, the BT functionality seems to be working best is nothing else is taking up CPU cycles.

BTCmdSender's BTCmdSender(String nxtname, String addr, String cmd) is supposed to take the cmd-string (let us say cmd.equals("write MY-NAME-IS-THOMAS")), convert it into an array of String, splitting on whitespace, and use this array of string,

String[] lines = cmd.split(" ");

to send string as a separate line to the NXT. This will not work. Hard coding a array of strings into the java file,

String[] lines = {"write","MY-NAME-IS-THOMAS"};

and use this as a command to be send to the NXT, works.

In the end, we got a somewhat working implementation of ``remote control'', but it was really frustrating to get anything to work as it was supposed to. Especially considering that this was some last minute extras we made in the end of the project.
After some communication with other groups about BT communication it seems like the only reliable method of communication is not using any of the fancy defined methods in the API, but fall-back to public final int readInt()[3], and cast each value to char afterwards.

Update: Since we implemented the BT communication the lejos has updated their API to reflect the newest version of lejos. And what will you know, there has been made major changes to the DataInputStream and DataOutputStream classes. readLine() is deprecated, and instead public final String readUTF() is available.

3.7. Other drivers




  • PCDriver is the PC-side driver for testing ShapesCatalog-calls before trying them on Thomas.

  • LetterDriver this is for printing letter strings on Thomas using the LetterHelper.

  • PlotterDriver this one was for printing various non-letter shapes on Thomas. Currently, it draws the rounded square shape.




4. Conclusion



The best thing that comes after this lab session is that we now are able to make the robot to write a whatever word that is made of letters taken from the English alphabet. It is done in a rather precise fashion even if the same letter is written on top over and over again. What is more, the idea of passing a string via a bluetooth connection is getting better, although not yet exactly working.

References


  1. http://java.sun.com/j2se/1.5.0/docs/api/java/io/DataOutputStream.html#writeChars(java.lang.String)

  2. http://java.sun.com/j2se/1.5.0/docs/api/java/io/DataInputStream.html#readLine()

  3. http://java.sun.com/j2se/1.5.0/docs/api/java/io/DataInputStream.html#readInt()




No comments: