Laboratory 3: Interactive Control Loops
Introduction
This week's laboratory project 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.
This lab introduces you to building a self-animating object fromt he
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 the following topics:
-
Defining a Java Class
-
Constructor Method
-
Creating an Antimacy
-
Behaviors of Entities/Behaviors of Aggregates
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 won.
You may also get comments from other students onall poritons of your write-up
before turning it in, if you wish. Please include the names of anyone
with whome 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.]
This assignment is due at the beginning of calss on Monday, 6 October.
Contents
-
Introduction
-
Pre-Lab
-
Finger Exercises
-
Lab Preparation
-
Laboratory
-
What to Bring to Lab
-
Getting Started
-
Compiling Your Code
-
Things to Try
-
Sample Balancers
-
Before You Leave
-
Post-Lab/Writeup
Pre-Lab
In addition to working on the finger exercises, for this week you should
think through the assignment jand 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.
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? 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?
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 thaking 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 agest 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 on athena.
You can, if you wish, run a demo by typing the following at your shell:
athena% java balance
(This presumes that you've successfully set up your Athena account to run
Java. If you had problems doing so, e-mail the course staff for help.)
Click and hold on the 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)
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
-
define a class that is capable of being self-animated. What interface
must you class implement?
-
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?
-
give that animacy some place to start. Where does an animacy always
start?
-
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
The documentation for the End interface is attached. An End is a
Java object that lets you ask it for its relative slope and tell it how
to move.
If e is an End,
-
how do you ask it for its slope?
-
what does a slope of -5 mean?
-
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:
-
Your agent runs a tight loop: it may be difficult for any other
code to run.
-
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.
We have found that a delay of about 100 milliseconds works well on the
computers in lab. 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 a course staff member.
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
-
your finger exercises
-
some (English) strategies
-
predictions on how these will work
-
an outline or draft of a basic class, including the appropriate constructor
and animacy mechanisms
-
answers to the various questions asked in the pre-lab
-
a development plan, starting with the simplest working code that you can
imagine (e.g., code that compiles, says "I'm here", and doesnt' 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. 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.
-
Log in and start Java Workshop 2.0
-
Under the Project menu, select "View Project Manager"
-
Under the File menu of the project manager, select Add and from there select
Project
-
Click the "Browse..." button ont he top right of the new window that appears
-
Select S:\Balance.prj. If you have problem, as a staff member for
help.
-
Keep hitting the next button until you get to the last screen. On
the last screen there will be a box that asks you where you want the project
file to be stored. In this box Enter:
U:\Balance
After you create your file, save it. Then do the following to run
it:
-
Make sure that Balance project is selected in the Project Manager
-
Under the File menu of the Project Manager, select Add and then select
File
-
Select your file. If you have problems finding your file, ask a staff
member for help
-
Select the Build option in the Project menu to compile your code
To run the Teeter-Totter with you code, you need to do the following:
-
Select Edit under the Project menu.
-
Select the little run tab near the top
-
In the box that says "Program Arguments", enter the name of your calss
twice. 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 one of the course staff.
On Athena
If you want to try working on the lab on Athena, you can do the following
to run your code:
If you class is defined properly, you should be able to compile your
class using javac. At the athena% prompt, type:
athena% javac yourclass.java
Once your yourclass.java file complies, it will create
a yourclass.class file. This file contains the java byte
code that actaully runs. You code will be run when you run Teeter
by typing:
athena% java balance yourclass yourclass
This should start the Teeter-Totter working using your code to control
both ends of the line.
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 srguments
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 ont eh Program Arguments box. On Athena,
you can type:
java Teeter Balancer2 or java Teeter Balancer2 Balancer2
for much the same effect.
-
Balancer1: This is the default balancer. It does a
decent job of balancing the teeter-totter, but the weight gives it problems.
If you give no command line arguments this balancer controls both ends.
-
Balancer2: This balancer handles the weight better than
Balancer1, but is somewhat slow and not all that stable.
Can you make a balancer that stabilizes this one?
-
Balancer3: This is the most stable and robust balancer of
the group. It is able to effectively deal with the weight and it
fairly fast. Even bad balancers look good when run with this one.
Can you make a balancer that produces oscillations when run against this
one?
Before you leave
Before you leave lab, you will need to have you code checked off by a course
staff member. You should allow time for an adequate demonstration
and discussion of what you have done. Please do not wait until the
last minute to be checked off.
PostLab/Writeup
Print out a copy of your code and turn it in along with your writeup.
(A TA can help you print out your code.) 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:
-
How long did it take you to bebug your code? What was the hardes
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?
-
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?
-
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 experimetns to try to figures this out.)
-
How do these observations match your predictions? Why or why not?
-
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:
-
your pre-lab assignment
-
experimentation notes: recorded observations, interesting behavior,
advantages one balancer type enjoys over the other.
-
finger exercises: both #1 and #2.
-
code design notes: at least two strategies for moving in responce to a
slope.
-
answers to the specific questions asked in the lab preparation section.
-
a discussion of how you spent your time in lab.
-
your observations concerning:
-
what actually happened
-
how this compares with what you expected prior to the lab
-
how the behavior of the teeter totter was affected by the strategies of
th two end-controlling agents
-
answers to any questions you were asked during check-out
-
the names and roles of any collaborators in any parts of the project
-
also note the following (briefly):
-
how long did this lab take you?
-
did you work with other students? If so, how helpful was it?
-
did you have problems writing code for this lab?
-
did you have problems running/using this lab?
This course is a part of Lynn
Andrea Stein's Rethinking
CS101 project at the MIT AI Lab
and the Department of Electrical Engineering
and Computer Science at the Massachusetts
Institute of Technology.