LÆGØLÅB-IT

Wednesday, 16 January 2008

End Course Project - 2nd robot, map building, ..., 3rd sound sensor...END!


Date: 16.01.2008
Duration of activity: 4 hours
List of participants: Alessandro, Daniela, Samuele


Goal: finish the last details and set up the presentation for tomorrow

Plan:
  • build an exact copy of the robot;
  • implement and debug MapBuilding;
  • test the communication between the two robots;
  • prepare a demo-show for the presentation.
After we have retrieved all the Lego bricks (borrowing from everyone the missing pieces), in less than an hour we succeeded in cloning our robot.


MapBuilding
In our idea every robot has to keep the positions of all the party that it visited.
Every party can be considered just a couple (x, y) in the absolute coordinates system. We implemented this idea as an instance of the class Localization.
A map is then simply a list of these locations.
The problem of building the map is strictly connected with that of communicating the position of the party discovered.
This allowed us to merge the implementation of the management of the Bluetooth connection and the building of the map in the same class.

Subplan:
  • add a 3rd sound sensor on the rear of the car
  • test if this modification improves the performance
3rd Sound Sensor
We noticed that sometimes our robot behaves in an unwanted way. When the robot is directed on the opposite side of the sound source, and close to a wall, while trying turning it would see the wall with the ultrasonic sensor, and avoid that continuously, while actually going far from the sound source.
We thought that we could avoid the problem by putting a third sound sensor on the robot's back, and using it only when there is a sensible difference between front sensors and rear sensor readings.

We implemented a new behavior, called Party Behind, which is connected to the Sound Perceiver as input, and is activated only when a sound source can be heard from behind the robot louder than on front.
We had then to had some more tricks to add. We previously had moved motors in the back of the robot in order to reduce noise on sensors. By putting a sound sensor on the back we made the robot continuously spin.
We then tried increasing the threshold needed between front and read sensors, but in this case, when the robot was going slowly, this behavior didn't work.
Then, as final solution, we added a trick inside the Sound Perceiver class. The Sound Perceiver class queries motors to know if they are moving or not. If they are, a fixed value is subtracted from rear sensor, otherwise not.
This is not an accurate solution, and therefore we couldn't use that for front sensor, that need to be accurate, but we decided to keep it for this experimental behavior.



Conclusion:
The Party Locating capability of our robots is ok, although it works better only for some kinds of sound.
We completed a working prototype of our original idea, but we still miss some details.
We should have worked more on motivations, to make robots less deterministic, and we should have tested the behavior of a big flock, but we didn't have time to test (and request enough NXTs).

File (all the project - under license GPL3):
PartyRobotsProject.rar

Sunday, 13 January 2008

End Course Project - Software Design


Date: 13.01.2008
Duration of activity: 6 hours
List of participants: Alessandro, Daniela, Samuele


At this point we completed testing and implementing almost every small component for our robot. We then tried to put everything together.
We had already agreed on a motivation-based architecture, because we want our robot to have different behaviors, depending on its wills (i.e. internal states, motivations).
We had still to define implementation details. We discussed many points, and we summarize here our final decisions and their motivations.

Architecture discussion
We defined four behaviors, which can be seen in the chart below, in a subsumption style.



Modules:
Each of those four behaviors gives its output to the Navigator, which is an adapter class for motors.

The lowest priority behavior is Party Searcher: its responsibility is to drive the robot toward the nearest sound source. We will use the Braitenberg strategy, already implemented and tested in previous sessions. It only receives input from Sound Sensors.

The second behavior is Party Reacher: it drives the robot toward a known sound source, when a new source is received from other agents. It receives locations from incoming bluetooth communications.

The third behavior is Avoider: it makes the robot go back when encounters some obstacle, helping it keeping track of its position. It uses the Ultrasonic Sensor.


The highest priority behavior is At The Party: it is activated only when the robot is close to a sound source, hence it uses the Sound Sensors and some sound level threshold. It acts by stopping the robot and communicating its coordinates to any other robot in range for a bluetooth communication.

Suppression order:
The Party Reacher behavior must have higher priority than the Party Searcher behavior, because if some party location is already known and not visited, there is no need for wandering and looking for sound.

The Avoider behavior has higher priority than the Party Searcher and Party Reacher behaviors, since when moving, the robot must always be careful about obstacles, in order to keep track of its position.
When stopped inside a party, instead, it is better it remains stopped, in order to avoid losing the party position. In addition to this, the only cause of the avoider detecting some obstacle when stopped inside a party is when new robots arrive to the same party. It will be other robots' responsibility to not hit the stopped robots.

The At The Party behavior must have a priority higher than the one of the Party Searcher behavior, to obviously stop the search when successful. It also must be higher of the Party Reacher behavior priority, because even if the party where the Party Reacher is leading the robot is not perfectly reached, and the At The Party behavior recognizes the sound level of a party, it could only be because of some error in Navigation class; if the reasonable sound threshold is reached while driving to some known party coordinates, instead, there is no need to continue going toward the specified location.

As already specified in previous lab sessions, Navigator class we will use is similar to the one from lejos packages, being able of keep track of robot position, but it accepts motor powers as input, instead of simple coordinates, in order to work with our Braitenberg-like sound follower.

In addition to those modules, a Map must be implemented, which is basically a collection of landmarks (in this case party locations) to remember, and some helper methods.

Motivations
As pointed out before, we want our robot to have a motivation based architecture. In the discussion above the architecture seems to be working and functional only using a simple subsumption architecture. Why do we want then to use motivation functions, instead of simple boolean activation?
What we want to obtain is the behavior of an artificial creature, so we want the motivations be conditioned by some internal state. But after defining the agents' behaviors, we noticed that those four behaviors are not concurrent, in their simple interpretation, but they must be in that precise order, to work coherently.

The idea of building a flock of agents that locates parties must then be explained. It is true that an agent which locates sound must follow a precise deterministic strategy, in order to get to one of its goals. But then, when some party locations are known to the flock, and when many robots are inside a sound source, then a complex flock behavior can be imagined.
After having found a sound source, agents could evaluate their motivation of remaining at that party according to
  • the number of mates in the same party and their personal willing of be in company
  • the time of having been stopped and their personal willing of walking a bit
  • the time spent and the music volume of that party and their personal willing of listening to music
  • the kind of music of that party and their personal taste in music (although we already decided that the capability of recognizing some features of a sound is too hard to implement).
In addition to this, not only behavior arbitration could be affected by internal motivations, but also the intensity of behavior actions.
If some agent has a low motivation for walking, it could wander slowly, or stop, even if it is not inside a party.
If some agent has an high willing of listening to music, it could low down the party sound threshold, or speed up motors, in order to more easily end up listening to some music.


Then, although a simple subsumption architecture could be enough for our project, this is why we chose to implement behaviors with motivation functions: we want our architecture to be scalable to further experiments.

Data flow
The diagram below can illustrate better data flows between modules.



Modules are the same as in the previous diagram. Arrows show directions of data flow.
This layout helps to see how inter-agents communication works.

First part of the communication - an agent founds a party:
When the "At The Party" behavior receives from Sound Perceiver (an adapter for two sound sensors) a sound level over some threshold, the robot knows it is in the range of a party. Then it tells Navigator to stop, and saves current location inside the Map. The map, then, automatically notifies the Communicator module, which broadcasts the new location to any other agent around.

Second part of the communication - an agent receives a party location:
When a Communicator module of some agent receives an incoming communication about some party location, it sends it into the Map.
The Party Reacher behavior, which polls the Map, will notice the new landmark added by some external agent, and will communicate those coordinates to Navigator module, which will drive up to that location.
When arrived to the location, Party Reacher will lose its motivation, and Party Searcher will do the rest of the job to correct possible errors in position tracking, up to when the At The Party behavior will detect a party.


We proceeded then implementing (or adapting some older classes) the most of the discussed architecture, and we left debugging and testing to the following day.

Friday, 11 January 2008

End Course Project - Location saving


Date: 11.01.2008
Duration of activity: 5 hours
List of participants: Alessandro, Daniela, Samuele


Goal: Make the robot able to describe, in a two dimensional system, the location of the party where it is "dancing".

Plan
:

  • figure out how to use the tachometer of the NXT motors;
  • understand how TachoNavigator works;
  • implement a specific Navigator to make the robot move "according to Braitenberg" and localize the resulting position;
  • add a function to make the robot go in a specific position in the map.
  • test the accuracy of our Navigator
leJOS API
The only tool we can use to determine the distance covered and the direction of the robot is the tachometer included in the NXT Motors. The leJOS API provides the interface Tachometer (implemented by MotorPort) to interact with it, containing these methods:
  • getTachoCount() - returns the rotation count of the wheel connected with the motor in degrees [0-360[
  • resetTachoCount() - resets the tachometer count to 0;
The class TachoNavigator allows the robot to travel in a specified position or along a specified distance or to rotate of a specific angle and keep track of the position: the values are updated after every movement is complete.

The central idea of this lab session is to merge the concepts of "navigation" and "Braitenberg movement": using the Navigator API provided by leJOS the only way to make the robot move is imposing the distance or the angle that the robot has to drive. On the contrary we need that the robot remembers its position after a movement imposed just setting the speeds of the motors and the driving time.

The prototype of our "BraitenbergNavigator" consists of the following methods:
public void driveArc(int speedL, int speedR);
public void stop();
public float getX();
public float getY();
public float getAngle();
The first one will be the core of the class that we are going to implement: it asks the robot to move along an arc just imposing to it the speeds of the motors and to keep track of its position. This is the main difference with the leJOS TachoNavigator and the reason why we are going to rewrite it.
The second method interrupts the movement of the robot and updates its position.
The last three trivial methods return in every moment the position and the direction of the robot.

Implementation
The driveArc method sets the speed of the motors as requested from the caller and imposes them a forward movement. Since the speeds requested as input can be negative values and the function setSpeed doesn't accept any negative values, we just flip the sign of the speed before passing it to the motor and use the method backward() to impose the movement.
When the stop function is invoked, the motors are stopped and the position of the robot is updated.

Therefore the core of the new class is the function updatePosition(). The aim of this method is to calculate the coordinate of the arrival position of the robot after it covered a bend.
The values t1, t2 in the code and in the picture below are the distances covered by the two wheels calculated from the values returned by getTachoCount() multiplied by the known diameter of the wheels.
 t1 = motorLeft.getTachoCount() * wheel_diameter / 2;

Because the distance beetween the wheel is also known, it's easy to calculate the angle and the radius of the circumference which the robot is driving on.
 
alpha = (t1 - t2) / wheel_distance;
r = (t1 + t2) / (2 * alpha);

Thanks to trigonometric functions we obtain the distance covered on the axes, relative to the starting position.
 
relative_y = r * Math.sin(alpha);
relative_x = r * (1 - Math.cos(alpha));

A rotation and a translation are sufficient to obtain the new position on the absolute coordinate system.



The next step is to add a method
public void goTo(float newX, float newY)
that makes the robot move to a position indicated by the absolute coordinates newY, newX.
We tried to implement this function using the corresponding one provided by leJOS Navigator: instancing a "normal" Navigator in the constructor of "our" navigator, resetting its position every time we call our goTo method and calling its goTo method with the position updated.
An easy test,
ournavigator.drawArc(300, 500);
Thread.sleep(2000);
ournavigator.stop();
ournavigator.goTo(0, 0);
, discloses some mistake on the code of the goTo method: the travelled distance is correct, but the car is driving in a wrong direction. It reveals that the coordinate systems of the two Navigators are not compatible. We think about two solutions which can resolve the problem:
  1. convert the coordinate system of the new navigator to those of the old one (it seems that the angle is rotated of 90°);
  2. rewrite enterly the code of our goTo without using the "old" Navigator.
We chose the second option after an observation: using the TachoNavigator.goTo inside our goTo, if the thread is interrupted during the execution of the latter, the position are not updated. We get the inspiration from the source code of TachoNavigator to rewrite our goTo and the resulting code is the following:
definitiveUpdatePosition();
rotate(angleTo(getX(), getY(), newX, newY) - getAngle());
float distance = distanceTo(getX(), getY(), newX, newY); // cm
int speed = 500;
driveForward(speed); // degrees per second
Thread.sleep((int) (1000 * cmToDegrees(distance) / speed)); // milliseconds
stop();
where rotate and driveForward are written using our coordinate system, thus we resolved also the first problem.

Files:
BraitenbergNavigator.java

Conclusion:
At the end of this session we have at our disposal a shiny navigator that can be used to move the robot indicating just the speeds of the motors and the travelling time.
Simple tests like that one described above proved that the error is <10 cm out of a distance of 200 cm: we think this accuracy will be sufficient for our purposes, because it's important that the robot goes in the proximity of the party and not exactly in the same position of the other robots.

Further development
Adapt the coordinate system to that one used in standard leJOS API.

References:
  1. leJOS API (particularly the section about Motors and Tachometer) - http://lejos.sourceforge.net/p_technologies/nxt/nxj/api/lejos/nxt/Tachometer.html
  2. Brian Bagnall, Maximum LEGO NXT - Building Robots with Java Brains (Chapter 12 - Localization)

Sunday, 16 December 2007

End Course Project - Sound follower


Date: 16.12.2007
Duration of activity: 8 hours
List of participants: Alessandro, Daniela, Samuele
Plan of the day:
  • Design and build a prototype of sound follower robot.
  • Test the effectiveness of its implementation
  • Test sound sensor capability of working in presence of multiple sound sources.
In this session we must build an important part of our project, the component which will drive the robot toward sound sources.
We considered different options, similar to the ones met within the course.
Among those, we considered of using a single sound sensor per agent and making the robot periodically stop and rotate 360° to sample around and choose the direction to follow.
We also thought of using two sound sensors, and interpolating their readings, estimate the direction from which the sound could come.

As a first try, we chose to implement a simple robot similar to the Braitenberg's vehicle, which uses sound sensors as inputs; we made this choice because, as we have seen during the course, this model seems to be the simplest and better working model for moving according to some kind of input.
As Braitenberg states: "Braitenberg's vehicles consist of the simplest sort of wheeled robots in which sensors that are sensitive to different stimuli are wired directly to motors that drive the wheels".
Valentino Braitenberg also makes an important comment, that we must be aware of: "In these models, we assume that the sensor generates a signal that is proportional to the stimulus".
As said in previous posts, we experimented that within some range of frequencies the sound level is almost proportional to distance of sound sources.

In Braitenberg's model we must connect sensor outputs to motor inputs, but before of doing that, sensor readings must be normalized with some function.
We defined the following normalizing function:
public int normalize(int value) {
final int MIN_VALUE = 0;
final int MAX_VALUE = Utils.LOUD_VALUE;

value = Math.min(MAX_VALUE, Math.max(MIN_VALUE, value));

return Math.max(0, Math.min(MAX_SPEED, (value - MIN_VALUE)
* MAX_SPEED / (MAX_VALUE - MIN_VALUE)));
}
This function implements a linear mapping between two ranges, the first related to sound values [MIN_VALUE, MAX_VALUE] and the second to motor speeds [0, MAX_SPEED].

where:
  • MIN_VALUE represents a threshold value for ambient noise, in this case 0.
  • MAX_VALUE represents the threshold for loud sounds. Like said in previous post, the value we used is around 70. Everything above that threshold must be considered equal.
  • MAX_SPEED represents the maximum speed that we want the robot's motors to have.

We built a simple robot with two sound sensors and two motors and we tried the above software.

We spent a lot of time to test, but the robot only went straight, with some random steering.
We tried changing some implementation detail, but, after a deeper analysis, we identified (at least) two major problems:

  1. The robot always went forward. It was because the difference between the sound sensors readings was too small, compared to the difference between motor powers needed to steer toward the sound.
  2. The robot always drove, even when there was no sound. It was because of the motors' noise.
As solution to the first problem we decided to amplify the difference between the two readings, in order to make the vehicle more sensible on sound sensor's values.
We then added twice the difference between the two readings to the maximum of the two values, obtaining a difference three times larger than it was.

About the second problem, we noticed that the motors were too close to the sound sensors, as it can be seen from the same photo as above.


As partial solution to this problem, we decided to move motors, trying to put them as far as possible from the sound sensors, to reduce their noise.

After having rebuilt our robot, and updated the code several times, we got a robot able to go toward sound.
We then performed some tests on it.

We tried at first with beeps played by old RCX bricks, but they were basically too quiet, and weren't heard from this robot.
We then tried with the frequencies we established with previous tests. Robot didn't seem to react as expected.
But when trying with those frequencies, we noticed that the robot rather followed our voices, instead of pure frequencies generated by our laptops.

We started then some tests on music, and we got better results, because of their wide range of frequencies. We also noticed that songs with electric guitars worked even better. This can be explained by the fact that the overdrive effect on guitar makes the sound wave squared, which spreads the energy of the sound among more frequencies.

Conclusion
We obtained good results and we are happy with that, we will proceed in this direction.
Next time we will try to plug into the robot some location saving capability.


References
Tom Dean, Introduction to Machina Speculatrix and Braitenberg Vehicles

Thursday, 13 December 2007

End Course Project - Sound sensor general tests 2


Date: 13.12.2007
Duration of activity: 4 hours
List of participants: Alessandro, Daniela, Samuele
Goal of the day: investigate on multipath fading problems of previous tests, and on frequency discerning capability of sound sensors.

In previous session we thought that the unreliability of sound sensor for certain frequencies was due to multipath fading. Since this strange behavior showed only for some frequencies, we thought that using sounds with more than a single frequency we wouldn't get the same effect.
So, we tried a test similar to the previous, but using square waves, because they are made up by more frequencies (all odd harmonics).
We used our pc as sound source again, but this time with a synthesizer software, configured with a square wave sample.

These are results we obtained with the sound source distant 50cm from the sensor
do3 -> 5
re3 -> 6
mi3 -> 7
fa3 -> 9
sol3 -> 9
la3 -> 12
si3 -> 13c

do4 -> 11
re4 -> 11
mi4 -> 11
fa4 -> 17
sol4 -> 12
la4 -> 14
si4 -> 20

do5 -> 15
re5 -> 17
mi5 -> 19
fa5 -> 17
sol5 -> 17
la5 -> 20
si5 -> 21

do6 -> 21
re6 -> 14
mi6 -> 20
fa6 -> 19
sol6 -> 17
la6 -> 20
si6 -> 17

and these at distance of 100cm
c4 do -> 4
c4 re -> 7
c4 mi -> 7
c4 fa -> 8
c4 sol -> 9
c4 la -> 11
c4 si -> 11

c5 do -> 11
c5 re -> 19
c5 mi -> 23
c5 fa -> 15
c5 sol -> 7
c5 la -> 13
c5 si -> 14

As it can be easily seen, even if these sounds are not made up by a single frequency, they are affected by the same problem, since there is no smooth change between values.
For some reason with square waves we got very low values, even if we used the sound volumes of the previous test.
We obtained constant values for a wide range of notes, and then we got changes that don't seem to follow any regular function.
In addition to this, sometimes sampling continuously same certain notes, we got really fuzzy results.

Conclusion
Using square waves we got worst results than the previous test.
We think that it is not possible to recognize the frequency range of a sound source, by computing only sound sensor readings in a naive way.
If we still want to do that, we must implement a Fourier transform algorithm, but then we should face some other hardware restrictions, like NXT sensor sampling frequency, or computational capability.
Then we decided to drop the idea of discerning sound sources according to their frequency, even if we could come back to it later. We will use only amplitude of the signal as indication for distance and direction of sound.
Next tests to be done with sounds are only tests with multiple sound sources. We plan to do these tests with a sound follower robot we will build in next sessions, since its results will be easier to understand.

References
http://en.wikipedia.org/wiki/Square_wave

Friday, 7 December 2007

End Course Project - Sound sensor detailed tests


Date: 07.12.2007
Duration of activity: 6 hours
List of participants: Alessandro, Daniela, Samuele
Goal: Determine which frequencies will be produced by our sound sources, in order to maximize the sound following capability of our robots.

In this test session we wanted to do an extensive test of NXT sound sensor response on a wide range of sound frequencies. We hoped to discover some properties of some range of frequencies that can be useful for our project.
We needed at least to find some frequencies which yield sound sensor values proportional to the distance from the sound source, such that the robot can have some indication about the proximity with the sound source, using only sound sensor readings.

In this test we measured readings of sound sensor values, through pure frequencies sounds from 100 Hz to 10 kHz and were repeated putting the sensor at three different distances from the sound source, at 50, 100 and 200 cm.
As sound source we used speakers of a laptop, and we generated wanted frequencies using a small tone generator software - (NCH Tone-Waveform Generator).


The tests were performed by using a plastic cup on the sensor. As said before, plastic cups will help improving the directionality of the sound sensor, and since we will only use sound sensors with plastic cups, we performed tests under the same condition in which we will use sensors.


Values we used are not directly raw values, but they are the mean value of all samples taken during 1 second; we had to use mean values because of the very noisy lego sensor.
In some cases we also repeated tests, when we got "suspicious" readings, so oscillation of values must not be attributed to random sensor noise, it is always an almost reliable mean of values for the specified frequency.

Those are test results:
frequency: Hzvalue
at 50cm
value
at 100cm
value
at 200cm
100211
200412
400949
45016148
500301811
550412314
600533038
650523138
700501513
750851437
800814311
850917422
900906745
950937793
1000906329
1500938137
2000816243
2500907657
3000754139
350093476
4000754210
4500939360
5000724820
5500936539
6000937247
6500805029
7000813410
706267323
712552226
718836134
725033124
73751351
7500853
7750733
80004131
9000440
10000410

As it can be seen from this table, we sampled with high density where small variations in frequency gave big changes in readings, while skipping where responses were uniform.

These are two graphs obtained from the values above:

2D version


3D version


From the graphs above some sounds sensor features come out:
  • The three shapes in the graph are similar in some way, and there is a decay of readings while the sound source gets far, which is an expected result, and a required condition for our robot to work. This means that near sources will give values higher than distant sources.
  • It is better if we use frequencies between 1kHz and 7kHz, because sensor responses are more uniform and proportional to sound source distance.
  • We can notice, by looking at the red line (which corresponds to the test with the closer sound source, 50cm) that the sensor response is not precise, when pushed to high levels, which means that we must consider every sampling above 70 as "loud sound" indistinctly, i.e. using threshold around 70-80 for loud sounds.
  • It also comes out that there are some frequencies which are still perceived loud by the sound sensor even if they're distant (2.5kHz, 4.5kHz, 6kHz), while others fall down too fast (3.5kHz, 5kHz).
Even if this test pointed out some good characteristics of NXT sound sensor, we noticed the non uniform distribution of values, which makes us worry about the possible capability of recognizing different frequencies.

After some speculation during the tests, we figured out that the problem of that oscillation was given by the environment under which we performed tests: our small office. The sensor readings were probably affected by a phenomenon which in telecommunications field is called multipath fading.
The same sound waves that come out from the sound source arrive more than once to the sensor: first time the waves with a straight path, and immediately afterwards with a different path, after having bounced on the walls. These signals are identical, but with a phase shift, which in some cases can cause them to cancel out partly or completely.


Conclusion
We got some good results, like hints about frequencies to use for sound sources.
We will do further investigation on sensing different frequencies, and avoiding multipath fading, to clarify whether the frequency discerning capability is implementable or not.

References
http://www.mediacollege.com/audio/microphones/directional-characteristics.html
http://en.wikipedia.org/wiki/Multipath_fading

End Course Project - Bluetooth general tests




Date: 6.12.2007
Duration of activity: 3 hour
List of participants: Alessandro, Daniela, Samuele


Goal: trying to get NXT bricks to communicate each other via Bluetooth©.

Plan
:

  • get used with leJOS Bluetooth API
  • activate bluetooth on NXT brick and assign a name to each robot
  • get two NXT bricks to communicate via Bluetooth
  • (only if the above test fail) get the NXT brick to communicate with PC
leJOS Bluetooth API
The package that provide all the NXT communication classes is lejos.nxt.comm.
Particularly we are interested in the classes Bluetooth, BTRemoteDevice, BTConnection.
These classes are poorly documented, so we expect for hard work...

It follows a brief description of each class:
  • Bluetooth - it is the main class of this package and it provides all the methods to activate the own bluetooth device, to discover other devices, create connections and communicate with them;
  • BTRemoteDevice - the methods in this class allows to change the parameters of the robot connected with the bluetooth: the address, the friendly name and the class which the device belongs to;
  • BTConnection - it represents a connection with another device: using a BTConnection instance you can open streams to write and read data from that device (on the documentation you can read that this classes are "not yet implemented", but we used them with success!).
We activate bluetooth on the devices using simply the option Bluetooth --> On/Off on the leJOS interface.

Then we try to assign a name to both of the robots, using the function Bluetooth.setFriendlyName: first of all the function gets as argument a byte array, so we build an function to convert the string into a byte array (all the utility functions and the constant variable are in the file BTUtils.java).
Applying the setFriendlyName using as input the simple string converted into an array we get a strange exception during the execution of the program...ok, no panic...let's go into the source code of the function:


public static void setFriendlyName(byte[] name) {
byte[] reply = new byte[32];
byte[] msg = new byte[32];

friendlyName = name;

msg[0] = MSG_SET_FRIENDLY_NAME;

for(int i=-0;i<16;i++) msg[i+1] = name[i];
...


We just figure out that there is a magic number that the argument must comply with.
After the appropriate modification to the function that convert the string, we check if the robot changed its name: yes, it works!
To trick to know the name of the robot is to search it from another device: on the screen of this one will appear the name of all the found devices.

Subplan:
  • send an integer from a robot to another one
  • send a real time produced stream of data
At this point, after we have stolen some ideas from the leJOS forum, we write the code of two program that are supposed to run in the two robots: the initial idea is just trying to send an integer value from the transmitter to the receiver. We use the stream abstraction implemented (according to the documentation they are "not yet implemented"...) on a BTConnection: openDataInputStream() returns a DataInputStream that can be used to receive data and the symmetric openDataOutputStream() returns a DataOutputStream useful to send data.
Thanks to the streams we are allowed to send any type of data: boolean, byte, char, short, int, String; all our test will be based on byte type.
Obviously we don't succeed at the first trying, but fortunetly only because of two small errors: we forgot to flush the stream after sending the byte and more stupid to refresh the screen on the receiver. After fixed these problems, it works, so we can try the second step of our subplan.
The idea is to generate a stream of data produced by a sensor of a robot, send this stream via bluetooth to the other robot and control a motor of this one using the values received. We are using the MotorPort abstraction, so at the first trying we don't perceive any movement because the scales of values are different: a normalization on the values received makes the system working.

Files:
BTTransmitterP.java
BTReceiverP.java

Conclusion:
We met the first deadline!
We succeeded to get two NXT sending data each other. This will be useful when the robots will have to communicate each other the positions of the sound sources detected. For this purpose other tests will be necessary, i.e. sending a "big" data amount and store it in one of the robot, but the goal of this session was just to prove the feasibility of the idea.

References:
  1. leJOS Forum - http://lejos.sourceforge.net/forum/
  2. leJOS API (particularly the section about the communication package) - http://lejos.sourceforge.net/p_technologies/nxt/nxj/api/lejos/nxt/comm/package-summary.html