Friday 5 September 2008

NXT Programming, Lesson 1



Date: 05 09 2008
Duration of activity: 2 hours
Group members participating: all group members


1. The goal.

The goal of this first lab session was to install relevant software, build a robot from LEGO bricks with a light sensor, tryout a program that makes the robot to follow the black line on the white surface, experiment with the robot and start a blog to document the results of the work.

2. The plan:
  • while one of the group members is installing the software to the laptop computer, the other is starting the blog and the third one is starting to assemble the LEGO robot (in the mean time the batteries are being charged)
  • after the blog is created, one of the group members is still trying to make things work with the software and the other two are building the LEGO robot further
  • when the robot is done and the system seems to be working, a sample program code is transferred to the robot using USB cable
  • the robot is started to check if it indeed follows the black line on the white surfice
  • some efforts are made to start the bluetooth connection
  • some experiments are made with the LEGO robot
3. The results:
  • the blog has been started with the name: http://www.legolabblog.blogspot.com/
  • the LEGO robot has been built that looks exactly like this one, as is was built using the manual of this particular model:

  • the leJOS Java system has been installed and the sample source code has been taken from the course page

  • the sample code has been uploaded to the robot using USB cable, bluetooth technology does not yet work for us (but we will make effort so it would) Read more about programming and flashing in part 3.1.

  • the robot works fine with the sample source code, it follows the black line successfully oscillating from the black surface to the white via the use of a light sensor. The readouts on the LCD-screen from the lightsensor clearly depicted the amount of light the sensor is picking up, to everyones satisfaction. Read more about our observation of the robot in a environment 3.2.

  • we experimented with the robots behavior by changing the parameter: samplingtime, and making less correction. Read more about tinkering with parameters in 3.3



3.1.Programming and flashing

As a part of the first day's agenda, we were to install the lejos system on the NXT brick. This blog posting concentrates on how to get started from scratch, in Debian.

Overview of the measures taken

  • Permissions and software, host-side

  • lejos firmware upload


Permissions and needed software

Everything that has to do with Java is a real pain to get working in a free software environment. Generally, people have written towards the Sun implementation of the language, and that has until recently been non-DFSG. Therefore, Java has had a nasty habit of winding up in the ``contrib'' portion of Debian.

The software in the lejos PC code is seemingly spread over a spectrum from C to Java. In a bit of a gamble, we've tried using lejos from a free platform, and seemingly succeeded.

The build process is essentially simple: Download the (NXT!) lejos .tar.gz, untar it, and move the resultant directory somewhere semi-convenient (in the author's case, as a subdir of his homedir). Call that location NXJ_HOME. For the archive, this guide was written using the 0.6 Beta version of lejos.

The build itself is ant-based (`aptitude install ant`) and simply consists of going to the $NXJ_HOME/build/ directory and running `ant`. This of course requires a working Java compiler (and I'm assuming that more than this was actually also needed). For the author, that was solved using `aptitude install openjdk-6-sdk`, which exists in Debian Sid.

The nxj compiler (`nxjc`) needs LEJOS_HOME to exist in the environment. Also, the nxj package builds various executables that end up in the bin/ dir, which one may want to have in $PATH. Therefore, to go into NXT programming mode, the following piece of shell code can be sourced (i.e. `source my_nxt_env.sh` or `. my_nxt_env.sh` from a sh-compatible shell). You're smart enough to figure out which parts to customize, yourself.

#!/bin/sh

export NXJ_HOME="$HOME/lejos_nxj"
export PATH="$PATH:$NXJ_HOME/bin"

After the build and the shell fragment-sourcing, the command `nxjflash` should be available. This however, doesn't run directly out of the box, since it needs write access to the relevant USB device on the host.

This shows the situation in my system after several reconnects of the NXT brick. Note the rather high last number in the USB identification; this is a consequence of the number incrementing upon reconnection.

root@moldover,11:03:~# ls -la /dev/bus/usb/00*/*
crw-rw-r-- 1 root root 189, 0 20080905 11:39:08 /dev/bus/usb/001/001
crw-rw-r-- 1 root root 189, 128 20080905 11:39:08 /dev/bus/usb/002/001
crw-rw-r-- 1 root root 189, 151 20080905 11:04:10 /dev/bus/usb/002/024
crw-rw-r-- 1 root root 189, 256 20080905 11:39:08 /dev/bus/usb/003/001
crw-rw-r-- 1 root root 189, 257 20080905 11:39:09 /dev/bus/usb/003/002
crw-rw-r-- 1 root root 189, 258 20080905 11:39:09 /dev/bus/usb/003/003
crw-rw-r-- 1 root root 189, 384 20080905 11:39:08 /dev/bus/usb/004/001
crw-rw-r-- 1 root root 189, 512 20080905 11:39:08 /dev/bus/usb/005/001

As can be seen, all these character devices are owned root:root and chmod'ed so that others than root cannot write to them. This is a problem for using USB programming of the device, since that obviously needs write access.

The clever way of doing this in a modern Debian system is to use custom udev rules. A sample one is given in $NXJ_HOME/README.html:

skrewz@moldover,16:14:~/lejos_nxj$ cat /etc/udev/rules.d/70-local-lego-rules
BUS=="usb", SYSFS{idVendor}=="03eb", GROUP="lego", MODE="0660"
BUS=="usb", SYSFS{idVendor}=="0694", GROUP="lego", MODE="0660"

I inserted this, but didn't take the time to make it work (for one because I couldn't be bothered to re-login to effectuate the membership of the mentioned lego group), so running `chmod a+w /dev/bus/usb/002/024` as root (in the above case) was used, to ad-hoc fix the problem.

Update:
Well, yeah. One is supposed to insert files into the /etc/udev/rules.d dir, that have names ending in .rules (as opposed to my -rules). When one does that, the above snippet works.


When the user has gotten write access to the relevant character device, flashing is easy: Just run `nxjflash`. That is, once you find the ``possibly the most well hidden button ever made''.


Assigning a bluetooth device name and program upload

On a less important note: One may, with the aforementioned USB access setup, easily run `nxjbrowse`, from where the device name can be set. There's probably a non-GUI way to do this, too. That GUI, however, provides a way to upload files to the unit, too.

To compile programs, run `nxjc Sourcefile.java`. To upload and run the resultant .class, run `nxj -r Sourcefile`. To do both (which you probably want), sequence the commands with sh's ``&&'' operator.

Bluetooth connection
The major obstacle with the bluetooth connection in Debian is to provoke the initial pairing. (isn't that always the problem?)

In bluez of recent versions, the command-line command is `hcitool cc $addr` with $addr being the colon-delimited MAC address of the device. This will in turn (via sbus, I believe) prompt the user's selected GUI for a passphrase. For my part, that GUI is kbluetooth, which is an annoying resource hog to have running for that purpose alone. However, the skeletal key-agent provided with bluez is of little use in day-to-day use. It is however important to notice that it is needed to have a such agent running, because generally, the pairing is strictly interactive.

It is a flaw that the NXT brick uses a default passphrase in the bluetooth pairing, when it could easily read-out a value and require the authenticated user to enter the randomly generated value, that is displayed in the NXT's display. For bluetooth mice, this is excusable, but even bluetooth keyboards should pair using a non-hardwired value of the passphrase.

3.2.Observation made of the environments effect on the system

When finally we got the bad boy to work, it was with the standard code of the assignment; the linefollower program. Right away it was tested on a small curvy course.
The first thing to noticed was, it works. The second thing to noticed was, it isn't a line follower, but rather a follow-the-course-in-such-a-way-that-you-have-dark-surface-to-the-left-of-you,-and-bright-surface-the-right. The program works by correction the robots direction for every control-loop. The philosophy is: Vary to one side of the threshold, do this, vary to the other side, do the opposite. This makes the controlsystem a Bang-bang controlsystem.

The fact that the software only works by asking, and acting on a binary question: "Does the sensor measure above or below the threshold", and that the physic's of the system only is one sensor measuring light-reflection right below it, the environment has a great effect on the system. As mentioned, the robot worked right away, oscillating from black to white underlay. But move it to the other side of the black line, so that white surface is to the left, and black to the right, the robot starts to go in circles. This was of course because the software relied so heavily on the fact, that when reading white-surface, black-surface is to you left -- so turn left. That, when put in a situation with white surface to the left and black to the right, the algorithm compensates in the wrong direction.

That being said, this approach was very efficient at following the curved course, because the robot just would keep on turning the same way until the threshold was surpassed, effectively dealing with any king of curve the track threw at it. The robot made the course with at fairly good time.

3.3.Different parameters influence on the system

The first parameter we tried having fun with, was the sampling time. Initial thoughts: smaller samples intervals -- quicker advance through the curse. This hypothesis turned out to be true.
But first we sat the sample intervals up, by changing "Thread.sleep(100)" to "Thread.sleep(1000)". As an effect the algorithm was destroyed. The sampling time was so low, that coming from white underlay the robot could surpass the black, and get a "white surface underneath, so you better turn left!"-reading, resulting in the robot starting to turn in circles.
As predicted, when "Thread.sleep(100)" was changed to "Thread.sleep(10)", the robot did go faster forward. The reason for this is that faster reading result in quicker correction of which way to turn, resulting in greater parts of the circular motion of turning to be converted into movement forward.

With the next parameter we had some fun with was the K-factor of the error-correcting algorithm. Instead of only operating one motor at a time -- operate one of the motor on full- and the other at half- capacity. This vastly increased the speed of the robot through the course. As an effect, it also made the difference between quick-sampling and normal-sampling less significant. All tho the fastest way around the course was with quick-sampling and both motors "on" at all time, combining them didn't give double the speedup.

4. Conclusion

The starting sample program with the sample robot worked great. It was interesting to make some experiments and see how differently the robot behaves. We will try to figure out how to work with bluetooth and apart from that we eagerly wait for next assignment.

No comments: