So far we have put all the work towards making a prototype that can do the basic goal we have, and we have more or less succeeded. However the AI that controls the robot has so far been pretty stupid to say the least. Simply put it has gone in a straight line until it gets too close to an obstacle and then turned. Now we have started working on something that can manage a little more than that.
The strategy we've planned for the robot is the following:
Start by either scanning around or simply drive forward until it approaches an obstacle.
Follow the outline of that obstacle until the robot reaches a position it has already visited.
If the first obstacle was an object the robot had driven around then let the robot simply drive in another direction and find a new obstacle. If it was the circumference of the area ( such as the walls of a room) the robot will begin scanning the remaining unexplored area until it's sure it has found all objects.
Eventually we will hopefully implement something which uses the map it has created, such as pathfinding or cover the area in an efficient way (something that could be of use for e.g. automated vacuum cleaners).
This is still a very rough draft and will most likely be subject to significant changes, but it's a start none the less.
Right now we're on the second point: we're working on an algorithm which will follow the curves and turns of a wall or the side of an object. The first iteration will consist of the behavior we already have (turn left when too close to something), a behavior to align the robot parallel to the wall and a behavior to detect when the wall turns away from the robot. If done right this should be enough to work in the vast majority of all cases.
As promised we have constructed a new robot that probably will be the one, or at least very similar to the final product. It is based on the Explorer robot from Nxtprograms.
Our requirements for the physical units was that it has to be able to rotate around its own axis (a requirement for the leJOS navigation classes) and that the IR sensor has to have a 360 degree field of view. A bonus with this model compared to others we have considered is that the IR sensor rotates directly on a motor. In earlier versions we had to convert between the rotation of the motor and the sensor, something we don't have to worry about anymore.
Aside from changing the sensor on top to our IR sensor, we have added a compass sensor and fitted the Ultrasonic sensor in front instead. We also slightly modified the top motor and sensor so that its rotational axis is between the wheels, something that will facilitate calculating the position of obstacles.
Today we have also done several tests to determine how accurate the navigation classes are, and the results are somewhat disappointing. For some reason navigation with the help of the compass sensor is actually less accurate than a simple tacho navigator that only uses the rotation of the wheels to navigate. Also, bugs with both classes severely limits the amount of methods we can use and still maintain a reasonable accuracy. For now we have settled on using Forward(), Backward() and Rotate(), which is accurate enough for our needs. Hopefully we (or leJOS, which is still in beta after all) will solve some of the problems and we won't limited to these forever.
When I first bought the NXT the sound from its speakers were not good at all, at first I thought it was supposed to be like that, it's just Lego and probably a cheap speaker. Anyhow just a couple of days later there were no sound from it at all so for a couple of weeks ago I sent it in to be repaired/replaced and now the new one has arrived :) So that's why we haven't been able to do and write especially much the last time.
PenemuNXTFramework 0.1
Anyhow what I have done while the NXT was gone is that I've written a communication framework that's supposed to be a middle layer between the existing communication classes in leJOS and the programmer. It's based at some interfaces that you must implement and then it will handle a lot of stuff for you.
Some key features are: Queue: Let you to setup a queue of set of data to send. This allows you to send data when the NXT has time, maybe there is much to do at the moment. Priority: Give priority to a set of data, this means that it will be sent first of all items in the queue and it will be processed first at the receiver. Good to use for shutdown commands. Consistent: The syntax and classes used is exactly the same ones at the NXT as at the PC. Choose type: When you setup the communication you specify if to use USB or bluetooth. You only specify it once and you don't have to change anything else.
This is how the base part might look: // Setup data factories // They produce empty instances of the data objects NXTCommunicationDataFactories DataFactories = new NXTCommunicationDataFactories( new ServerMessageDataFactory(), new TiltSensorDataFactory());
// Setup .. NXTCommunication NXTC = new NXTCommunication(true, DataFactories, new NXTDataStreamConnection());
// .. and start the communication NXTC.ConnectAndStartAll(NXTConnectionModes.USB);
// Setup a data processor // It will be given the incoming queue of data and handle it ServerMessageDataProcessor SMDP = new ServerMessageDataProcessor(NXTC, DataFactories); SMDP.start();
//Add some data to the send queue NXTC.sendData(new TiltSensorData(TS.getXTilt(), TS.getYTilt(), TS.getZTilt()))
A data factory might look like this: public class SensorDataFactory implements INXTCommunicationDataFactory { @Override public SensorData getEmptyInstance() { return new SensorData(NXTCommunicationData.MAIN_STATUS_NORMAL, NXTCommunicationData.DATA_STATUS_EMPTY); }
@Override public INXTCommunicationData getEmptyIsShuttingDownInstance() { return new SensorData(NXTCommunicationData.MAIN_STATUS_SHUTTING_DOWN, NXTCommunicationData.DATA_STATUS_ONLY_STATUS); }
@Override public INXTCommunicationData getEmptyShutDownInstance() { return new SensorData(NXTCommunicationData.MAIN_STATUS_SHUT_DOWN, NXTCommunicationData.DATA_STATUS_ONLY_STATUS); } }
And part of a data processor like this: @Override public void ProcessItem(INXTCommunicationData dataItem, NXTCommunication NXTComm) { SensorData SensorDataItem = (SensorData) dataItem;
So it's not finished yet but soon I hope. Anyhow this will make things much easier for us when we want to share data to the computer and back.
Right now we are rebuilding the robot and hopefully we will upload some pictures later this evening. We are basing the new model on the Explorer from NXTPrograms.com, it's much more stable the our previous construction.
Now we've finally begun to build something that with a bit of imagination remotely resembles our ultimate goal. UltrasonicScanner is a stationary robot which is much like the UltrasonicTest, but now we've integrated communication between the computer and the NXT through Bluetooth and we can let the computer do all the calculation and show the results graphically.
The code is more or less CommunicationTest combined with UltrasonicTest. We've established streaming of both the ultrasonic sensor getDistance() and motor getTachoCount() (which returns the angle from it's original position) and then perform all the necessary calculations serverside. We also have a third "channel" streaming data to allow us to give commands in both directions. This means that both the NXT and the JAVA application have the ability to close both programs.
private Point getScreenPos(int Distance, int Angle) { Angle += 90; int x, y; int distx, disty;
This is the algorithm we use to calculate the coordinates on the screen based on the data from the NXT, and it's all straightforward mathematics.
As you can see on these pictures the "map" the robot managed to create isn't totally accurate. Apparently the sensor can't give accurate data when facing at an angle to a flat surface, with the result that flat surfaces seems to be curved around the robot. Once we have the robot mobile a lot of this problem should be solved.
If check out our videos you can also see a version before we implemented Bluetooth for it.
It's astonishing how much you can manage to do in just one day of coding. Or astonishing how long time coding takes, depending on how you look upon it. In one day we've started to familiarize ourselves with the NXT and we've created all kinds of smaller test programs, all of which you can find on our Google Code page.
The first basic program to show that the NXT and leJOS works properly. The same program that every programmer has done at least once during his early career. What it does is to simply write a String on our NXT's screen. The leJOS code for writing on the screen of the NXT is: LCD.drawString("String",x,y);
In this project with its very intuitive name we started playing with the Ultrasonic Sensor. This works like a sonar; it sends out ultrasonic sound and measures the time to the echo. To use the sensor you simply declare the sensor, which then has a number of predetermined methods. Note that you have to specify the port he sensor is located in as well. UltrasonicSensor sensor = new UltrasonicSensor(SensorPort.S1); int distance = sensor.getDistance(); LCD.drawInt (distance , 1, 1);
These lines will cause the sensor to measure the distance ahead of it and write out the distance in centimeters on the display.
We used this to create a program that measures the distance in a 180 degrees radius and then write it out on the LCD screen. Here we also used a motor to rotate the ultrasonic sensor. The motors also have a set of predetermined methods, but you don't have to declare them.
This loop makes the sensor rotate back and forth in a 180 degree arc. In a separate thread we continuously gather data which we then translate into coordinates on the LCD and write it out.
We noted that the sensor isn't very accurate when facing at an angle to a flat surfaces, and when the sensor sweeped over a flat surface the surface would appear curved on the screen. This is something we'll have to take into consideration later on. Also, we noticed the limits of the NXT' computing capacity, as it didn't quite manage to keep up with the data income. Though the most difficult part for it was to manage to write all the data to the LCD fast enough, so the screen flickered.
To solve the problem with the NXT's limited computing capacity we wanted to be able to run most of the computation on a server, in this case a computer. Also we want to be able to show the results on a real screen instead of the very limited LCD of the NXT. Thus, we had to establish a communication link.
The first comm test was just a simple app sending the data from a touch sensor to the computer through USB. When the touchsensor was pressed the computer app should exit. leJOS included some really great examples for rthis so it wasn't that hard to establish the first connection.
We extended the data transfer so that it also transmitted the data from the soundsensor aswell as the ultrasonicsensor in real time. The PC recieved the data and painted it to an applet as a graph. The PC also always sends back a status code telling the NXT if the status is OK or not, if it's not OK everything should shut down.
Then it wasn't that hard to switch to Bluetooth mode instead. The use the same connector but with different protocols:
USB:NXTConnector conn = new NXTConnector(); conn.connectTo("usb://")
Bluetooth:NXTConnector conn = new NXTConnector(); conn.connectTo("btspp://")
Though there are better ways to implement it which we will test later on. Anyhow we missed one important thing in the beginning, we forgot to add the reference to the BT package bluecove.jar. It took us at least one hour to figure out that this was the missing part.
Video of the CommunicationTest:
Summary So what we've learned so far will be really important. Now we will use our know knowledge in BT communication and ultrasonic data to build a simple bot that rotates, collects US data and sends it to the computer to display it.
We have now officially started on our project! PenemuNXT is a project by Josef Hansson and Peter Forss. PenemuNXT means "explorer" in Indonesian, and that's what it's going to be. We are doing this project as our final main project at our school Berzeliusskolan in Linköping, Sweden. The main reason for the project is to learn more about programming and JAVA, but since we wanted a result we could see and feel for ourselves we decided to build a robot in Lego Mindstorms NXT. The robot is in its final form going to be able to, using the UltraSonic Sensor from Lego, scan its environment and then wirelessly send it to a server which then processes the data into a map which will hopefully be reasonable close to how the environment actually looks.
The firmware leJOS provides us with the means to program the NXT using JAVA, a language we are already somewhat familiar with and which can be used in other applications as well. The code wil be open source and available through Google Code.
While we go about on our project you'll most likely see all kinds of different smaller robots and programs we create while we familiarize ourselves with the NXT and learn new ways of programming.
In the third year of Swedish Gymnasium (roughly equivalent to 4th year in high school) every
student has to make a project concerning at least one of the fields he/she studies. PenemuNXT is our
project.