author=Johnny Rieper, Bent Bisballe Nyeng and Kasper Sohn
title=Marvin - The Balancing Robot.
======Lab report 5 - Bluetooth controlled robot======
**Date:** January 19nd 2009\\
**Duration of activity:** 8-16\\
**Participants:** Kasper, Bent and Johnny\\
=====Project Goal=====
Make robot remote controlled from the PC through bluetooth.
=====Plan=====
* Make a bluetooth client code Behaviour on the Marvin, that can receive numbers and act on them.
* Make PC bluetooth application read from keyboard arrows to determine control direction.
=====Theory====
====The Protocol====
{{ :marvin:bluetoothlogo.png |The Bluetooth Logo}}
From wikipedia: //"Bluetooth is a wireless protocol for exchanging data over short distances"//(([[http://en.wikipedia.org/wiki/Bluetooth|Bluetooth on Wikipedia]])). The NXT hosts a bluetooth communication device, and is capable of communicating at up to approximately 10 metres distance.\\
LeJOS has built an entire framework for bluetooth communication, over normal Java input/output streams.
(([[http://lejos.sourceforge.net/nxt/nxj/api/lejos/nxt/comm/BTConnection.html|The LeJOS Bluetooth class]]))\\
We do not want to go further into the details of the protocol itself, but the way the device is shared can eventually end up in data loss(([[http://lejos.sourceforge.net/nxt/nxj/api/lejos/nxt/comm/BTConnection.html|The LeJOS Bluetooth class]])). We however do not care about this, since we intend to use it to send loads of control keycodes to the robot without worrying whether they will all arrive safely at the destination.
On the PC LeJOS has also made a bluetooth interface. This works exactly the same as the one on the NXT, and we therefore simply had to make a connection (listening on the NXT and connecting on the PC) and then creating input/output streams, to make the communication work as intended.
LeJOS has put a lot of effort into making the bluetooth communication easy to use, and the implementation were therefore quite straight forward. Observe the resulting code below.
We experienced a lot of slowdown in the balancing thread whenever the bluetooth communication was running, and we had to disable it entirely at numerous occasions to avoid the robot falling over.\\
We later discovered that the problem could be worked around by disabling some of the other behaviour threads to release more resources, and make Marvin rebalance itself while driving around remote controlled.
Here is a movie of the resulting remote controlled robot, with all other behaviours disabled:\\
[[http://www.youtube.com/watch?v=CBRJdHbWyV4|{{:marvin:remote.jpg?255x210}}]]
{{youtube>CBRJdHbWyV4?small}}
As it can be seen from the video, Marvin is not exactly reacting real-time to the control changes. This is due to the way the BTControl has been implemented, but also because the tilt reference must be incremented gradually, but still has to reach a certain level before an actual forward or backward motion can be seen. Making this incrementation more rapid (and thereby making the reaction faster) will cause Marvin to nosedive.
=====Implementation=====
====The BTControl Class====
{{ :marvin:bluetooth.png?450 }}
Bluetooth control behaviour. It reads integers from a bluetooth input stream, interpreting them as keycodes.
It reacts only on the keycodes connected with the arrow keys (up, down, left, right) and tells Marvin to drive accordingly.
^ Key ^ KeyCode ^ Variable ^
| left | 37 | directionLeft |
| right | 39 | directionRight |
| up | 38 | directionForward |
| down | 40 | directionBackward |
All exception handlers have been removed to improve on readability:
public class BTController extends Behavior
{
.
.
.
public void run()
{
NXTConnection conn = Bluetooth.waitForConnection();
DataInputStream istream = conn.openDataInputStream();
while(true) {
if(istream.available() > 0) direction = istream.readInt();
else delay(200);
if(direction >= directionLeft && direction <= directionBackward) {
suppressLower();
switch(direction) {
case directionLeft:
left(200);
break;
case directionRight:
right(200);
break;
case directionForward:
forward(200);
break;
case directionBackward:
backward(200);
break;
}
unsuppressLower();
// Empty input buffer... we only want to use the latest keystroke.
while(istream.available() > 1) istream.readInt();
}
}
}
}
====The PCController Class====
On the PC, we use a window (JFrame) to capture keyboard input and redirect their keycode values to the bluetooth stream.
NXTComm nxtComm = NXTCommFactory.createNXTComm(NXTCommFactory.BLUETOOTH);
NXTInfo nxtInfo = new NXTInfo("Marvin", "00:16:53:06:E3:36");
nxtComm.open(nxtInfo);
OutputStream os = nxtComm.getOutputStream();
final DataOutputStream dos = new DataOutputStream(os);
JFrame frame = ...
frame.addKeyListener(new KeyListener() {
public void keyPressed(KeyEvent e) {
dos.writeInt(e.getKeyCode());
dos.flush();
}
public void keyReleased(KeyEvent e) {}
public void keyTyped(KeyEvent e) {}
});
The full source code for both of these classes can be found in the files ''BTController.java'' and ''PCController.java'' in the Marvin code tarball (([[http://wiki.aasimon.org/lib/exe/fetch.php?media=marvin:marvin-1.0.tar.gz|marvin-1.0.tar.gz]])). See the ''marvinController'' script file in the same tarball, to get an idea of how to run the bluetooth client program.