Monday, February 15, 2010

Beep, Beep!

There is a feature of GvR that we haven't yet explored, beepers. In this first look at beepers we will simply have GvR place some beepers on the map. But we'll also build on what we've learned so far as we do it.

Two rooms, No View
To start with we'll need a map for our program. Two things you'll notice about the following map code that is different than what we've had before. First the last number in the robot line is not zero. This indicates the number of beepers in GvR's beeper bag. We'll start with 8, because there will be eight corners on this map. The second change is the addition of a number at the end of the wall statements in the map file. These numbers indicate the length of the wall, up or to the right, from the starting position, up for NS walls, right for EW walls. Enter the following into the world editor and save it as tworooms.wld

robot 2 2 N 8
wall 2 2 W 8
wall 2 9 N 8
wall 9 2 E 8
wall 2 2 S 8
wall 6 2 W 3
wall 6 7 W 3

Once the code is entered and saved, click the reload button. You should have something that looks like this:
 
The plan is to have GvR place a beeper in each corner of the room. One of the sample programs provided on the GvR site shows how to have the robot hug a wall on its right as it moves around. We'll do something similar but hug the wall on the left. When we hit a corner we'll need to turn right so we'll include our turnright definition in this program. So let's break down the steps:
1. Place a beeper in the corner that we are starting in.
2. Move forward along the wall until we hit the corner
3. Place a beeper in the corner
4. Turn right
5. Repeat steps 2-4 for each of the remaining corners on the map.

Seems simple enough. We'll make use of some of the conditions that GvR can test. These are listed on the Language Reference tab of the GvR interface. To start with we'll need the left_is_blocked and front_is_clear conditions.

Let's get started. First thing we do is define the turnright command.

define turnright:
    do 3:
        turnleft

The first step in our list of steps is easy. You place a beeper by using the putbeeper command.

Following the left wall is done by making sure that the left side is always blocked, using the left_is_blocked condition. The next thing we need to know is whether we can move forward. To move forward the front must be clear. So we check front_is_clear and move if it is. If the front is not clear then we are in a corner. So place a beeper and turn right. Here's the code for that.

while left_is_blocked:
    if front_is_clear:
        move
    else:
        putbeeper
        turnright

We've seen the while command in our first exercise. It will loop will that condition is true. The if command is what we call a flow control statement in programming. It will allow us to do a group (or block) of commands based on the results of the conditional test. In this case we check if the front is clear, if it is we move. If it's not then the else clause is executed. In this case we put a beeper and turn right.  Seems simple enough.

Don't for get to include the turnoff command at the end of your program.

Once you've got your code in, save it then click Reload and Execute.
Did the program do what we wanted? Not really, did it. There's one piece missing from our initial analysis and from this code. What do we have the robot do when it reaches the opening in the wall? If we want to follow a wall on the left then when we reach an opening we know we can move to the left. So while there is no wall on our left we turn left and move forward. Use the following code:

while left_is_clear:
    turnleft
    move

Place this code before the turnoff command and save your program. Then Reload and Execute to see what happens. Better? GvR should have made it around the wall and be ready to follow the left hand wall again. How do you start him up again? Since we know we'll hit the opening twice we could try putting everything inside a do 2: loop. Give that a try and see  what happens. We're getting close. GvR stops after making back into the first room. But he still has one beeper to place to finish the task. You could up the loop to 3, but I'll tell you that an error would be generated when we attempt to place a beeper with none in the bag. What follows is my final version of this program that will place beepers in every corner and shutdown the robot when it returns to its starting place. There's a repeat of the check on beepers when we hit the corner. Again if we attempt to place a beeper and there is none the program will error. Also this shows that the end of the program, the turnoff command, isn't always at the end of the code.


define turnright:
    do 3:
        turnleft

putbeeper
while any_beepers_in_beeper_bag:
    while left_is_blocked:
        if front_is_clear:
            move
        elif any_beepers_in_beeper_bag:
            putbeeper
            turnright
        else:
            turnoff
    while left_is_clear:
        turnleft
        move


That's it for now. Here's something to try on your own. Right a program that looks for beepers in the corners of the room and if it finds one moves it to the next unoccupied corner. You can place beepers on the map in a world file using the beeper instruction. It includes the coordinates and the number of beepers. You might want to play with the GvR world builder to learn the syntax.

I'll post a version of this program in about a week so you can check your code against mine. 

Tuesday, February 2, 2010

GvR:Teaching your robot new tricks

We will look at the same topic here that is addressed in Tutorial 5 of the GvR lessons. If you've worked through the lessons this will be review. If not you may want to look at that after you've read this.

As we saw in the previous post on GvR the robot is limited to moving forward and turning left. This may seem like an artificial limitation but I'll give you an example of a simple robot, built with Lego Mindstorms that had the same limitations. The mind storms kit came with two motors. If you wanted a mobile robot that did more than move you had to accomplish the movement with one motor. Working from plans published online and in some Mindstorms books I had, I built a robot that was similar in function to GvR. One motor was used to move the robot and the right (or left) wheel was setup with a "ratchet gear". Basically a piece was used to keep the gear from moving backward. So when the motor ran backward the ratcheted wheel couldn't turn. The result was the robot moved forward and turned when the motor ran backward. Turning a particular direction was a the result of running the motor backward for a certain amount of time.

While GvR has a limited number of commands it does have a define command. The define command allows you to create new commands for GvR by stringing together combinations of the basic commands and those that you have defined. We will define a few new commands, including the one in Tutorial 5, and then put some of them to work.

First things first we will create a simple world file that places GvR in center of the bottom row of the map. (Note: this assumes the default window when you start GvR.) Enter the following into the world editor and save it as bottomcenter.wld:

robot 5 1 N 0

The next thing  we'll do is define the turnright command as done in tutorial 5.

define turnright:
    turnleft
    turnleft
    turnleft

Enter this into the code window. If you were to click the Execute button at this point you would get an out of instructions error with no apparent action. The system behaves the same as when there is no code in the Code Window. So let's have the robot move in a zig zag pattern. We'll incorporate the looping that we did in the last entry and have the robot move ahead a few spaces on the map. Add the following below the define statement in the code window:

do 2:
    turnleft
    move
    turnright
    move

do 2:
    turnright
    move
    turnleft
    move
turnoff

Click the reload button and then the Execute button and watch what happens. The end result is the robot 4 spaces up from where it started.facing north. Let's add another command. Add the following below the last turnleft in the definition of turnright and above the first do 2: in the command group.


define turnaround:
    turnleft
    turnleft


This command will turn the robot around so it can reverse direction. You may want to save the program at this time. Give a name you'll remember. If we Reload and Execute now nothing will have changed. We have defined the new command but we haven't used it. So add the following lines before the turnoff command:

turnaround
do 4:
    move
turnaround


Save your file again (use a different name if you want to preserve the previous program). Click Reload and the click Execute. Hopefully GvR ends up where he started. Remember that if the robot is moving to fast you can select "Set Speed" from the Setup menu and slow it down. If you want to examine what it does step by step use the Step button instead of the Execute button.

We'll define one more new command that will include one of our other new commands, to show that once you define a new command you can use it anywhere you use a built in command. Then we'll add it into our program just to make sure it works.

The new define looks like this:

define backup:
    turnaround
    move
    turnaround


It should be added to the code window after the turnaround define before the movement commands. It is important that it come after the definition of turnaround or it will generate an error.

Once you've done that add the following before the first turnaround command in the existing code.

move
backup

Save the program, Reload and Execute. 

Your final program will look like this:
define turnright:
    turnleft
    turnleft
    turnleft

define turnaround:
    turnleft
    turnleft

define backup:
    turnaround
    move
    turnaround

do 2:
    turnleft
    move
    turnright
    move

do 2:
    turnright
    move
    turnleft
    move

move
backup

turnaround
do 4:
    move
turnaround

turnoff

You might want to save a copy of the program that includes only the defines. This can be useful for adding those defines to other programs. Remember that once you close GvR or reload with a different program, those defined commands will be forgotten.

Experiment with your new commands and maybe add some more. More next time.