CPS4.2
Java for Video Games

Modeling a Unicycle



Introduction

If you are pedalling at 100 radians per second on a unicycle, how fast will you be traveling?  This project models the gears, axle, pedals, chain, and wheel of a unicycle to answer this question.  The diagram on the right is a simplified diagram of how the pedals are connected to the wheel via axles, gears, and a chain.
As you turn the pedal on the left (labeled wheel), it turns the axle at the same rotational velocity.  That is one turn of the wheel will cause the axle to turn once.  Likewise, the angular velocity of the axle imparts an equivalent angular velocity of the gear it is connected to.  The two gears in the middle are connected by a chain.  Because the gears may be of different sizes, the angular velocity of the gears may be different, but since they are connected via a chain, the rolling velocity of the gears is equivalent.  That is if the big gear on the left causes the chain to travel 2 meter on the top part of the chain, the bottom part as well must travel 2 meters in the opposite directions.  The gear on the right is connected to the axle on the right and the axle is connected to the wheel on the right.  Therefore, all parts of the diagram are connected.  Rotating any gear or wheel will cause the other gears and wheels to rotate.  Your job in this assignment is to write classes to model this behavior.  The diagram below shows the classes you'll need to write and the measures you'll need to take into account.

How To

Step 1

Start a new project called Unicycle.  In the unicycle project, create 6 classes: The first five are for modeling the unicycle, and the last one is for testing the first five as you write them.  The wheel and pedal will have the same methods and instance variables, so we'll use the Wheel class to model the pedal.

Step 2

The following methods need to be written for the Wheel class:
Similar methods need to be written for Gear, Chain, and Axle with a few exceptions.  Chains only have rolling velocity and do not have angular velocity.  Also, chains do not have a radius - they are assumed long enough to fit around the gears they are connect to.  Axles only have angular velocity and do not have rolling velocity since they have an idealized zero radius axle.  Add all the applicable stub methods to all the classes.  Stub methods are methods which are not functional, but they do compile.  Two complete stub methods are provided for you below as an example.
Write all of the relavent stub methods for Wheel, Gear, Chain, and Axle.  Your code should compile, but will not yet run.

Step 3

Now you need to declare the instance variables you'll need for each class.  Do not include any redundant instance variables in your class.  For all angular velocities, the units should be radians/second.  For all radii, the units should be meters.  For all rolling velocities, the measures should be in meters/second.  The instance variables for the Wheel class should be:
The axle instance variable is going to be used because the wheel will be attached to an axle.  Rotating the wheel will make the axle rotate at the same angular velocity if it is not already doing so.  Also rotating the axle can also cause the wheel to rotate at the same angular velocity if it is not already doing so.  Notice that the instance variables do not include a variable for rolling velocity.  This is because rolling velocity can be derived from the radius and angular velocity:

Identity for converting a single revolution to the radians traversed
1 rotation = 2 * PI radians
dividing each side by 2 * PI radians yields
1 = 1 / (2 * PI) rotations/radian
Formula for the circumference of a circle
1 rotation = 2 * PI * radius meters
dividing each side by 1 rotation yields
1 = 2 * PI * radius meters/rotation
Starting with aV radians / second, it is now possible to derive rV meters/second rolling velocity
aV radians/sec * 1 = aV radians/sec * 1 / (2 * PI) rotations/radian = aV / (2 * PI) rotations/sec
aV / (2 * PI) rotations/sec * 1 = aV / (2 * PI) rotations/sec * 2 * PI * radius meters/rotation = aV * radius meters/second
Therefore
rV meters/second = aV * radius meters/second
You can also solve the above equation for aV.
aV radians/second = rV / radius  radians/second

Add the relevant instance variables to the remaining classes.  No class should have both angular velocity and rolling velocity variables.

Step 4

Add the following code to complete the method bodies in the Wheel class:

    public void connectAxle(Axle axle)
    {
        this.axle=axle;
    }

    public void setRadius(double r)
    {
        radius=r;
    }
   
    public double getRadius()
    {
        return radius;
    }

    public double getAngularVelocity()
    {
        return angularVelocity;
    }

    public void setAngularVelocity(double v)
    {
        this.angularVelocity=v;
        if(axle!=null && axle.getAngularVelocity()!=angularVelocity)
            axle.setAngularVelocity(angularVelocity);
    }

    public double getRollingVelocity()
    {
        return angularVelocity*radius;
    }

    public void setRollingVelocity(double v)
    {
        setAngularVelocity(v/radius);
    }

    public String toString()
    {
        return "Wheel turning at "+angularVelocity+
            " radians/second and rolling at "+
            getRollingVelocity()+" meters/second";
    }


Notice the method setAngularVelocity does not set the angular velocity of the axle unless an axle is connected and the axle is not moving at the same angular velocity as the wheel.  It's very important that the wheel not set the angular velocity of the axle unless it is different.  Consider the following scenario.  Every time the wheel is angular velocity is set, it sets the axle angular velocity.  Every time the axle angular velocity is set, it sets the wheel's angular velocity.  It's fairly easy to see that if every time Axle calls Wheel that Wheel calls Axle, then the calls would loop infinitely.  For this reason, only set them if they are different.

In the Driver class, add the following code in the main method:

    public static void main(String[] args)
    {
        Wheel wheel = new Wheel();
        wheel.setRadius(0.25);
        wheel.setAngularVelocity(6);
        System.out.println(wheel);
    }

When you run the Driver class, you should get the output:

Wheel turning at 6.0radians/second and rolling at 1.5 meters/second

Step 5

Complete the code for the Axle class by filling in the code in the method bodies.  Test the Axle class individually by adding code to the Driver class in a similar way as the Wheel class was tested.  Then connect the Wheel and the Axle by calling the connectAxle method of the Wheel class.  Also be sure to call the connectWheel method of the Axle class. When connecting Unicycle parts A and B, it is important to connect both A to B and B to A. Now set the angular velocity of the Wheel and see if it sets the angular velocity of the Axle by printing both the Wheel and Axle to the console using System.out.println.  BE SURE TO CONNECT AND SET THE RADIUS OF ALL PARTS BEFORE SETTING THEM IN MOTION.  Make sure the Wheel and Axle when connected work properly before continuing to the next step.

Step 6

Complete the code for the Axle, Wheel, Gear, and Chain.  Test them in the Driver to make sure they work both individually and when connected to other parts.  Hint: add to the Chain class a method with the following method signature:

    public void connectGears(Gear top, Gear bottom)


Step 7

Design and implement the Unicycle class.  You'll need to have methods for setting and getting the radii of all unicycle parts which have a radius (Axles and chains do not have radii).  You should also have methods for setting and getting the pedal angular velocity and getting the rolling velocity of the wheel.  In the Driver class, test the Unicycle class.

Step 8

Post to the class discussion board a set of radii for the sizes of the gears, pedal, and wheel not the same as any which have been posted and with no gears or wheels the with the same radii.  Give two coordinate pairs of (pedal angular velocity, wheel rolling velocity) for different pedal angular velocities.  Compare other results with your results to make sure they agree.  If your results for the same radii and same angular velocities disagree significantly on the wheel's rolling velocity for the majority of results posted, then re-examine your code.  If your results are consistent with the majority of the results posted, then your program is most likely correct.