CS184 Lab exercise 4 - due Wednesday 9/23/98 at 10pm

Notes on the lab:
To submit the lab, create a directory called lab4. As explained later, you should have files called "record.wrl", "playback.wrl" and "joint1.wrl" up to "joint4.wrl" and possibly more depending on your robot design.

To submit, cd to the lab4 directory and type "submit lab4".

This lab is the last individual lab. You should do it and hand it in on your own.

Keyframing using an interactive model

In this lab you will use the robot model you built last week to define some keyframe configurations to be saved in a file. These keyframe files will contain VRML interpolators which will be read in by another model to animate the motions you defined. In other words, you will use one world to record an animation, and another to play it back. The first world is called "record.wrl" which we describe now.

Recording the joint motions will require a Java script node. This script node should be placed on the ROUTE between one of the control levers and the robot joint transform which it controls. Let's call this script node Joint1Recorder. That way, whenever the joint angle is changed, the script node knows about it and can record it. Normally, it just forwards the changed angle to its output, so the robot continues to move as normal.

Internally, the Joint1Recorder node should have a field which tracks the current joint angle. It should also have an array of say 100 values to remember keyframes. The Joint1Recorder should accept a "recordNext" eventIn. When it receives such an event, it should store the current angle in the next free array location, and increment a count of locations recorded.

The Joint1Recorder node should also accept a "saveFile" eventIn. When it receives this event, it should write all the keyframes it has received to a file. The format of the file should be that of a complete OrientationInterpolator node that can be inlined by another file later. That is, you should start by writing text to the file that begins "DEF joint1 OrientationInterpolator {  key [....". Then you should write the key fractions. If the Joint1Recorder has recorded N keyframes, the keys field should contain N fractions equally spaced from 0 to 1. That is, 0, 1/(N-1), 2/(N-1),... 1. Then write out the text "] keyValue [" and the orientation values for the keyValue field. Since all the robot's angles are rotations about local Y axes, all the interpolator keyValue's should be of the form

    0  1  0  angle

Finally, write out the close parentheses and close the file. For better human readability, you should use newlines and indentations to make the OrientationInterpolator file look like it had been written by a human. This will also prevent obscure bugs later. Although in principle VRML 2.0 doesnt depend on whitespace characters, you will probably find that it breaks if the file format is very different from the format you normally see.

You should define a different recorder script node for each joint, but they can also use the same Java program. You will pass the name of the file to be saved to the script using a field, and also the name of the interpolator that is DEF'ed inside the file. So the definition of a typical recorder node would be like this

DEF Joint1Recorder Script {
	url "recorder.class"
	field SFString filename "joint1.wrl"
	field SFString nodename "joint1"
	field SFRotation currentRotation 0 1 0 0
	eventIn SFRotation set_rotation
	eventIn SFBool recordNext
	eventIn SFBool saveFile
	eventOut SFRotation rotation_changed
	eventIn SFBool step_back
	eventIn SFBool step_forward
}

We didnt say what the last two eventIn's do. They are there to allow you to do some editing of the robot's path before you save the file. The step_back eventIn should move the array pointer back one location and output the array contents through the rotation_changed eventOut. Similarly, step_forward should increment the array pointer and then output the contents to the rotation_changed eventOut. If you get a recordNext eventIn, you should store the angle at the current location and step to the next one (if it exists). In this way, you can create a path, step back to review it, change one or more of the keyframes, and then write out the whole set of keyframes.

There should be one JointRecorder script for each joint. The name of the node and the name of the filename field should depend on the joint number.

Buttons

You should add four buttons to the world. Each button is a cylinder or other suitable shape with a TouchSensor attached. One button each for recordNext, saveFile, step_back, step_forward. Each button should generate a boolean eventOut that is sent to the corresponding eventIn of all four of the JointRecorder nodes. Label your buttons so that its clear what each one does.

Recording

To record a path, start the world. Click the recordNext to save the zero position of the robot as the first frame. Then use your control levers to move the robot to the first point on a complex trajectory. We leave the trajectory to you, but e.g. you could simulate the robot picking up an object, or waving, or throwing something. Remember that "animation" means "bringing to life", even when applied to robots. Click on recordNext, then move the robot a little again etc.

When you're done, review the whole trajectory by stepping back through the keyframes and then forward again. Change any keyframes that you want to. Then click on the saveFile button. That button should be routed to all the JointRecorder nodes, and they should all write out their array contents to distinct files names "jointn.wrl". You should have at least 10 keyframes along your trajectory.

Playback

Playback happens in a different world called "playback.wrl". This world should have your robot model, but not the control panel. You may want to put the robot model into a separate file that can be inlined in both the recording and the playback worlds. In the playback file, define interpolators for each joint angle which include the interpolator files written out by the recording phase, something like this:

Inline {
	url "joint1.wrl"
}

Define a global time sensor, whose fraction_changed events are routed to all the joint interpolators. Then route from each joint interpolator to the corresponding joint of the robot.

Finally, create a button (shape plus TouchSensor) in the world labelled "playback". Clicking on this once should enable the time sensor, while clicking on it again should disable the time sensor.

Using Java under MS Windows

Accounts have been created on the Windows NT instructional machines for you. The account name is the same as your Unix class account name, and the password is the same as the original password (the one printed on the account form you got). If you dont have that password any more, see the instructional staff in the office opposite 330 Soda. There will be examples of Java code in the online versions of lecture 10 and lecture 11.

Using Java with Internet Explorer is somewhat tricky. By default, Explorer saves Java class files away the first time it finds them, and will refuse to reload them, even if they have changed and you clear the cache etc. We recommend that you use Netscape for Java development and testing. If you use Explorer, make sure you configure Explorer (under the "Internet" icon in control panel) under the "General" tab and "Temporary Internet Files", select "Settings" and under "Check for newer versions..." click on "Every visit to the page". Even so, you may still find that it has an old version. Also, explorer seems to have trouble will local file urls like "recorder.class". If you give it an absolute path without the "C:", it seems to work: e.g. url "file:\\\CS184\lab4\recorder.class"

The online documentation page for CS184 now includes links to the Sun and Microsoft Java Development Kits (JDKs). Both have a Java compiler, and are free to download for home use. If you use the Microsoft SDK, it should automatically find the VRML classes, which are normally placed in \WINDOWS\JAVA\CLASSES\MSVRML.ZIP when you install Cosmoplayer 2.1.

If you use the SUN SDK, you will need to tell the compiler where the VRML classes are. Normally, you could set the global CLASSPATH variable to include them. But unfortunately, Netscape uses this variable to find classes and has its own VRML classes which are different (because they include browser access). Setting CLASSPATH to include the MS VRML classes therefore breaks Netscape's VRML browsing. You could set global CLASSPATH to point to the Netscape VRML classes (which may break explorer's VRML ability) but we suggest instead you specify the classpath in the compile line. It looks like this:

javac -classpath C:\java\lib\classes.zip;C:\WINDOWS\JAVA\CLASSES\MSVRML.ZIP  file.java

You need to include the main Sun java class file, which in this example is in c:\java\lib\classes.zip. You also need to set the global PATH variable to include the Java bin directory, which in this example would be C:\java\bin. To save typing this every time, you can put it in a batch file.  The batch file contents might therefore look like this:

javac -classpath C:\java\lib\classes.zip;C:\WINDOWS\JAVA\CLASSES\MSVRML.ZIP %1

To cause a java file to compile by double clicking on it, pick any folder window and select View/Folder Options/File Types. Find Java source files (or create a new type with extension .java), and edit it. Add an "open" action which is to invoke the batch file above, say call it "javav.bat". The command line should look like this

C:\java\bin\javav.bat "%L"

The "%L" ensures that long filenames are correctly passed to the batch file, which javac requires.