FHTW Berlin

FHTW Berlin
Fachbereich 4
Internationale Medieninformatik
PROG1: Programmierung I
Wintersemester 02/03


Laboratory 4: Interactive Control Loops

 

Introduction

It seems to me that we need some more work on interactive control loops. Many people are complaining that they are getting something to work, but they don't really understand what they are doing. So let's get down into animacy, even if we haven't had the lecture on that yet :-)

This week's laboratory project only involves writing a "public void run() { while (true) { ... } }" interactive control loop, this is, an object that acts on its own.  We've designed a teeter-totter (i.e. see-saw) of sorts, and your code will act on its own to balance the teeter-totter.  This lab will introduce you to the concepts of creating a new Thread and using it to create an "animacy", as well as the use of constructors in you code. Threads are something that are built into Java, I suggest looking it up in the JavaDoc to see the kinds of methods a Thread has.

This lab will detail building a self-animating object from the ground up.  It reviews the idea of defining a class - a recipe from which objects can be made - and incorporates the ideas of communities of interactions seen in the previous labs.

This assignment emphasizes and reviews the following topics:

You should read through this entire assignment and complete the Lab preparation section before you come to lab.  Some portions of the Post Lab write-up also require your thinking about them before and during the laboratory portion of the assignment.

As per policy, you are encouraged to discuss in detail this assignment with you classmates, but you should do the write-up on your on.  You may also get comments from other students on all poritons of your write-up before turning it in, if you wish.  Please include the names of anyone with whom you collaborate, in any way, on this assignment, and indicate the nature of the collaboration.  [Failure to include this information is a violation of the collaboration policy.]


Contents


Pre-Lab

In addition to working on the finger exercises, for this week you should think through the assignment and come to lab with a plan that includes at least a partial solution to the problem set and a development plan for how you intend to implement your solutiuon. In the finger exercises we are going to go into detail on the working of some code.

A. Finger Exercises

1. Consider the following code:
class Foo {
    private int bar = 0;
    public void method1() {
                                // line 1: bar is
        bar++;
                                // line 2: bar is
        int bar = 5;
                                // line 3: bar is
        bar++;
                                // line 4: bar is
        if (true) {
                                // line 5: bar is
            int bar = 10;
                                // line 6: bar is
            bar++;
                                // line 7: bar is
        }
                                // line 8: bar is
        bar++;
                                // line 9: bar is
    }  // end method1()

    public void method2() {
                                // line 10: bar is
        bar++;
                                // line 11: bar is
    }  // end method2()
}  // end class Foo

Each line that begins with // is a Java comment.  (This comments begin at the // and run until the end of the line.)

Assume now that the following code is executed:

Foo foo = new Foo();
foo.method1();
foo.method2();
What is the value of bar as each line # comment is reached? For example, if the comment were replaced with
System.out.println("The value of bar is " + bar);
(i.e. this statement came after any code on the line), what would be printed?  Don't program this and have Java tell you the answers!! I want you to think through the flow of control here! Are any of the statements illegal? (If so, say so then ignore them, i.e., pretend they were omitted.)

2. Now assume that the following code is executed (i.e., continuing on after the execution of the code in 1, above):

Foo fooToo = new Foo();
fooTwo.method2();
What is the value of bar when (each of) lines 10 and 11 are executed this time?

3.  In the code defining class Foo, which of the lines bar++ could be replaced by the line this.bar++ without changing the execution of the code?  (You can identify the lines by the line number following.)

4. Now consider the following code, which implements a simple counter:

public class Counter {
    private protected int currentValue = 0;
    public int next() {
        this.currentValue++;
        return this.currentValue;
    }
}
Given this definition, what is printed by the following code, and why? Do not program it, just think and use paper and pencil!
Counted count = new Counter();

if (count.next() > 1) {
    System.out.println("First case");
} else if (count.next() < 1) {
    System.out.println("Second case");
} else if (count.next() == 1) {
    System.out.println("Third case");
} else {
    System.out.println("Last case");
}

B. Preparation for Lab

This week's lab assignment involves a small community of interacting entities.  The field is which they interact is a simulation of a child's playground toy, called a teeter totter or see-saw.  This toy consists of a board placed across a raised pivot; a child sits at each end of the board, and they can spend countless hours taking turns in the air and on the ground.  (At least they could before lawyers discovered that these toys were unsafe....)

In our simulation, there are three (main) entities: the agent at the end of the teeter totter, and the graphical user interface (GUI), which allows the agents to interact with each other and with a user.  Each agent, looking at an end of the teeter totter, sees only the relative slope (up and away or down and away).  The agent can choose to raise or lower the end.  A typical agent will sense the end's slope, perhaps make some calculations, adjust the end, and then go back to sense the slope again.  Your job is to implement such an agent.  But first, to acquaint you with the problem....

Running the Demo (Optional)
You do not need to run this week's program before coming to lab.  However, if you would like to do so, we have made it available.  Download balance.jar, select Main as the main class, put "balance.Balancer1 balance.Balancer1" in the arguments section, run it, and make the window a bit larger to see the hidden control menu up in the upper left hand side.

Click and hold on that control menu at the top of the screen to get a list of possible options.  Select "Start" from the menu.  The TeeterTotter should level off fairly quickly.  Try playing with the controls at the top of the screen; these controls create a weight that can affect the balance of the TeeterTotter.  Play with these controls a little and see what happens.

Sitting at an End...
The structure of the lab is quite similiar to the Spirograph lab you wrote earlier this term.  As in the Spirograph, you are writing a control rule that determines what to do with one portion of the GUI (in this case, with one End of the line).  This idea is that a second, separate process controls the other End; your joint behavior will make the line balance (or oscillate, or ...) if you build things right.

Unlike Spirograph, your job is not just to write the control rule.  However, in preparing for the lab, you may want to consider what such a control rule would look like.  That is, if you knew the slope of the End, how would you want it to move?  The End's slope is a float; positive means that the line slopes up and away from you, negative, down and away.  Similarly, your command to tell the End how to move gives it an int: positive to rise, negative to fall.  There are also limits to how much pushing you can do, you'll discover these in lab.  Don't worry about the form of the Java code yet; just think of how you would like to incrementally (one move at a time) control your End.  Come up with several rules and make notes (in English or German) about them.

When you get to lab, you will be able to define a few different approaches, which you can test against one another; you can also test your definitions against each other's classes, or against some that we will provide.

Down to Details
In fact, the rules that you have just described will need to be implemented by a self-animating object that you will write.  In order to do this, you'll need to
  1. define a class that is capable of being self-animated.  What interface must you class implement?
  2. ensure (through you class's constructor method) that each instance of your class has its own animacy.  What built in Java type is an animacy?  How do you get it going?
  3. give that animacy some place to start.  Where does an animacy always start?
  4. ensure (through you class' constructor method) that each instance of your class has its own End.  This will be supplied to each instance as it is constructed.  How do you indicated that such information is necessary to make an instance of your class? Given that you're going to need the End later, what should you do with it?
This information should be enough that you can define a skeleton Java class (which sets up an animacy and remembers its End, but doesn't do much with it).  You should do so, and bring this to lab with you.  In the next section, we'll tell you how to connect this to your rule.
About the End

An End is a Java object that lets you ask it for its relative slope and tell it how to move. The interface looks like this:

package balance;

public abstract interface End {

// Methods
float getSlope();
int moveEnd(int p0);
}

If e is an End,

  1. how do you ask it for its slope?
  2. what does a slope of -5 mean?
  3. how do you ask e to rise?
Given this information, you should be able to trun some of the rules defined above into concrete Java code.  Make sure that you know how to write this code and to embed it in your class definition.
Final Details
Sleeping on the Job
If you write your code in the most straightforward way, you will discover two things:
  1. Your agent runs a tight loop: it may be difficult for any other code to run.
  2. The code runs so quickly that it is difficult to see what's happening.  Changes take place before you have a chance to observe them.
To fix these problems, you can add a delay to you inner loop.  The easiest way to do this is with the Thread.sleep method, which takes an int representing the number of milliseconds to sleep.  A delay of about 100 milliseconds often works well, but your mileage may vary.  Thread.sleep also potentially throws an InterruptedException, so you have to include it in a try block:
try { Thread.sleep(100); }
catch (InterruptedException e) {}
This will make the program run a little bit more slowly and will help make some of your changes a lot more visible.
A Little Math...
Depending on how you design your strategy, you may wish to you more mathematics than the basic Java operations.  You may wish to make use of Java's Math class, which contains many more sophisticated mathematical functions.  Sun maintains full online documentation of the java API.   You can find the Math class there.

One particularly useful method you may want to use is Math.round.  This method takes an argument of type float and round to (and returns) the nearest int.  A typical usage could be:

int myInt;
float myFloat;
// ... more code here ...
myInt = Math.round(myFloat);
Publicity
You will probably need to make your class and its constructor public.  You will definitely need to make any methods implemented for an interface public.
Wrapping up
Think of several approaches to balancing the TeeterTotter.  You may wish to define a class that uses a particularly tricky approach.  Alternately, can you get the TeeterTotter to oscillate?  What other things can you do?  Try to anticipate what other people's classes might do, and how you could respond to them.  Think about which approaches will balance most quickly, be most robust to jitters, or be able to handle other balance strategies.  Write down these predictions before testing your code.

Make sure you understand everything in this section before you write any code.  If anything is unclear, please ask!

Beyond the constraints described above, your code and do pretty much whatever you'd like.

Laboratory

What to Bring to Lab

When you come to lab, you should bring
  1. your finger exercises
  2. some (English or German) strategies
  3. predictions on how these will work
  4. an outline or draft of a basic class, including the appropriate constructor and animacy mechanisms
  5. answers to the various questions asked in the pre-lab
  6. a development plan, starting with the simplest working code that you can imagine (e.g., code that compiles, says "I'm here", and doesn't do anything else) and gradually building up to more complex functionality.  Also indicate how you will test each stage.

Getting Started

Begin by building a very simple class. Too often I see you trying to get the complicated stuff to work first! What is the minimal code that you can write and still get it to compile and run?  Once this compiles (and runs to your satisfaction), add functionality until you have some interesting behavior.

The next section describes in more detail how to actually edit, complie, and run your code.

Compiling Your Code

In lab

In order to work on this problem set in lab, you will first need to do a bit of setting up. You will have to make a new project, add the balancer.jar file, set the Main class, and then create your own file. Select new class from the files menu, and make sure that you select the correct directory (there's a little drop down menu for the package name). Setting up class paths in Java is a black art!

Have a look at the interfaces for the files given: Balancer1, Balancer2 and Balancer3. How to look at the interface? Use the Searching menu and search for the classes. Voilá, this is not the implementation, but the interface, and it looks good! This gives you all the fancy import magic you are going to need.

To run the Teeter-Totter with you code, you need to do the following:

  1. Select the project properties menu.
  2. Select the little start tab
  3. In the box that says "Program Arguments", enter the name of your class twice.  Remember to put the package name in front of it! For example, if you were using the Balancer1 you would write
    balance.Balancer1 balance.Balancer1
    This will load your code as both ends of the Teeter-Totter.  You can vary this later, giving other classs names to try out other configurations.
If you have any problems or questions ask a neighbor or me!

Things to Try

If your basic balancer works, you may want to try some of your more sophisticated algorithms.  Try to balance in the presence of the weight, or maybe try to make the teeter-totter oscillate.  After you've tried a few of these, you can set up a competition, by using different classes as arguments to Teeter.  The first argument will control the left side, the second the right.  (Supplying fewer arguments will cause the default balancer to be used.)

Sample Balancers

We have provided three balancers to play with.  To run any of them, for instance Balancer2, change one (or both) of the items in the Program Arguments box.  For example, if it reads
Balancer2 Balancer2
the you will be running Balancer2 on both ends.  See above for detailed instructions on the Program Arguments box. 

The Balancer Fights

Now ask around for other peoples balancers! Take theirs on one side, yours on the other - see who wins! A lot of fun can be had if you have a de-balancer fighting against a balancer! Include the names of the people you competed with in your report! Who wrote the best balancer in the class? The best de-stabilizer?

 


PostLab/Writeup

Print out a copy of your code and turn it in along with your writeup. In addition, be sure you turn in your finger exercises, your development plan and initial guesses at a solution, and an explanation of how your code works and why you chose to implement it the way you did.  In addition, briefly discuss the following questions:
  1. How long did it take  you to bebug your code?  What was the hardest bug to find/fix?  What techniques worked to help you find your bugs?  What was the most helpful suggestion you gto?  What was the most subtle error you made?
  2. How quickly does your original algorithm balance the TeeterTotter?  How robust is it to jitters?  How well does it rebalance?  Can it handle the weight?
  3. How do your different algorithms compare?  Which ones balance best when competing with themselves?  Which ones are most robust to jitters?  Which ones complete well?  Why or why not?  What features matter?  (You can do some additional experiments to try to figures this out.)
  4. How do these observations match your predictions?  Why or why not?
  5. If you tried to do other things, like to get the TeeterTotter to oscillate, how successful were you?  How well did the behavior match your predictions?  Why or why not?
Don't forget to include information about any collaboration you may have engaged in!  As always, your complete assignment should include:


This course is an adaption for the Fachhochschule für Technik und Wirtschaft , Berlin by Prof. Dr. Debora Weber-Wulff of a part of Prof. Dr. Lynn Andrea Stein's Rethinking CS101 project produced while she was at the MIT AI Lab belonging to the Department of Electrical Engineering and Computer Science (EECS) at the Massachusetts Institute of Technology. The copyright for all materials belongs to Lynn Andrea Stein, this adaptation is used by permission. All rights reserved.
A textbook is in preparation by Morgan Kaufmann Publishers


Questions or comments: <weberwu@fhtw-berlin.de>