CS 444 - Week 4 Lab - 2015-02-13

*   lejos.robotics.navigation
    lejos.robotics.subsumption
    *   packages we are working our way towards...!

*   discussed the types a given Java object is
    considered to be;
    *   can be a pretty big set of types!
    *   includes the class it is an instance of,
        AND all of its ancestor classes;

*   in lejos.robotics.navigation,
    there is class CompassPilot
       which is a subclass of DifferentialPilot
          which is a subclass of Object

    CompassPilot compy = new ... uh oh its deprecated,
    		       don't use it BUT...

    what are compy's types? CompassPilot, DifferentialPilot,
        and Object

*   NOW -- Java does NOT permit multiple inheritance --
    a class can only extend 1 other class
    (can only be a subclass of 1 other class)

    BUT: Java has another option, called
    INTERFACES -- an interface is not a class,
    but a set of requirements for classes that want
    to be known as conforming to that interface.

    *   a class can IMPLEMENTS 0 or more interfaces

        public class Blah implements A, B, C

        ...then Blah is expected to IMPLEMENT every one
	of the requirements for all the interfaces
	it is implementing;

        *   and then an instance of this class is
	    ALSO considered to have as additional
	    types those interfaces --

	    an instance of Blah is of considered to
	    be of type Blah, type Object,
            *and* type A, type B, and type C

        (see the beauty of it? Any method that expects
	an argument of type A, can also now handle
	an argument of my new type Blah...

	...it KNOWS that object has the methods that
	A requires...

...enter in Java events and event listeners...
*   Java 1.1 event handling model

*   an action like clicking a button is an
    event -- Java will tend to have classes for
    events

    *   we have event SOURCES --like a button, a motor,
        etc.

    *   we have event LISTENERS -- objects interested
        in receiving events (or receiving notice of
	events, if you will)

        *   an event source maintains a list of listeners
            that want to be notified when an event occurs;

            when they are notified, they can DO something
	    based on that event.

        *   to put it another way:
	    do you want something to happen when
	       a button is clicked?
	    IF SO, you register an event listener
	       with that button,
            and each time the user clicks that button,
	       control is passed to EACH of its
	       registered listeners, and its appropriate
	       methods will be called

*   attempt an example...
    *   package lejos.nxt has class Button
    *   Button has an addButtonListener method --
        I can add a specified ButtonListener to 
	a button,
	and then when that button is clicked,
	   the APPROPRIATE method of EACH registered
	   buttonlistener will be called

   *   OK, what is a ButtonListener?
       an interface, with 2 methods that are expected
          to be implemented:
	  public void buttonPressed(Button b)

          public void buttonReleased(Button b)

*   AFTER CLASS: *did* get a version of ButtonEventPlay
    running!
    *   includes a main method that creates an instance
        of the class itself (using its default constructor,
        in this case), and then calls a local non-static
        method that adds a listener instance to each
        button
   
    *   why are there *5* versions posted? Because I went
        overboard checking something out...!

    *   if you only look at one, look at ButtonEventPlay.java!
        *   uses a single private inner class, within the public class
	    ButtonEventPlay, to create the four button listeners
	    for the four buttons on the NXT brick

        *   this private inner class implements ButtonListener --
            so it indeed implements the required buttonPressed
	    and buttonReleased methods;

            ...since it implements interface ButtonListener,
	    an instance of this class if considered to be of
	    type ButtonListener, and so CAN be the argument
	    to the addButtonListener method,

	    ...which can be called on a Button instance to make it
	    sensitive as desired to user actions;

        *   its ButtonEventPlay.nxj's size on NXT brick: 9100 bytes

    *   ButtonEventPlay2.java: uses *anonymous* inner classes for the 
        ButtonListener arguments of the addButtonListener calls;
        *   its ButtonEventPlay2.nxj's size on NXT brick: 9356 bytes

    *   ButtonEventPlay3.java: uses *4* private inner classes,
        an instance of each being used for one of the addButtonListener
	calls;
        *   its ButtonEventPlay3.nxj's size on NXT brick: 9432 bytes

    *   ButtonEventPlay4.java and ButtonEventPlay5.java: UH-GLY versions
        of ButtonEventPlay3.java to test something about nxjc-and-nxjlink
	resulting file sizes
        *   their .nxj's sizes on NXT brick: also 9432 bytes each

    *   fair to ask: was there a POINT to all those versions?

    *   readability usually should trump minor memory
        savings, in MANY settings (for example, personal computers,
        workstations)

        ...BUT with small memory-challenged devices like
        NXT bricks, memory needs to be considered
        more than one typically would nowadays, I *think*;

    *   IF, with some abstraction, an "only useful for THIS
        class" listener can be shared by MORE than one object,
        I think a private inner class, as in ButtonEventPlay.java,
        is the better course (and it does turn out the be
        the smallest here -- BUT the water might get considerably
        muddier if the 4 button's actions weren't identical,
        I think.)
        *   I'd still go with the reused private inner class
            if it can be used by more than 1 object in the same
            class (and even go PUBLIC if more than one *class*
            might actually be able to use...!)

            ...this seems more robust and more readable;

    *   IF a listener is SHORT -- so readability really isn't
        impacted TOO much -- and only one object can use it,
        this little experiment I think provides some supporting
	evidence that the anonymous inner class may take less
        memory, and since it is short, readability should not
        take TOO big a hit -- BUT I *do* think you have
        to be CAREFUL how you indent it, to improve readability;

    *   but if complex/long -- I'd still consider the private
        inner class over the anonymous inner class, I think.
        *   easier to write, to read, to debug, to maintain, etc.

    *   (and, by the way? The UH-GLY ButtonEventPlay4.java and 
        ButtonEventPlay5.java suggest what 
        I suspected -- nxjc does indeed strip out comments
        in the compiled result, and the original source code's
        spacing, indentation, white space matter NOT A WHIT
        in the resulting bytecode. So, DON'T go thinking that
        omitting comments or good indentation and use of white
        space in your source code is buying you ANYTHING with
        regard to space on your brick...!)
        *   ButtonEventPlay3.java -> ButtonEventPlay3.nxj, size: 9432
        *   ButtonEventPlay4.java -> ButtonEventPlay4.nxj, size: 9432
            (all comments removed)
        *   ButtonEventPlay5.java -> ButtonEventPlay5.nxj, size: 9432
            (all indentation removed, { and } moved to previous
            lines)
            ...try it if you doubt it... 8-)

******** moving on! ********

*   different types of robots can be controlled
    by different higher-level classes as well;

*   consider a 2-wheeled robot, where the 2 wheels
    are each controlled by an independent motor;

    This can be controlled using the
    DifferentialPilot class

    these higher-level classes work at several
    levels of abstraction:
    *   at bottom, there are motors that turn
        the wheels, controlled by the NXTRegulatedMotor
	class

    *   The DifferentialPilot class uses the motors
        for elementary moves:

	rotate in place
        travel in a straight line
	travel in an arc

    *   at the NEXT level, the Navigator class uses
        DifferentialPilot to MOVE the robot through
	a path in a plane

        ...to do navigaton, the robot needs the robot
	location, and direction it is heading

        *   it uses OdometryPoseProvider to keep
	    this information up to date.

    *   the control is top down:
        the navigator
	controls the pilot
	whch controls the motors.

	the flow of information is from the bottom up:
	pilot uses info from the motors to control them,
        the pose provider uses odometry info from the
	    pilot to update its current estimate of the
	    robot pose,
	    (the pose consists of the robot's coordinates
	    and its heading angle -- the direction it is
	    facing)
	the navigator uses this data to calculate the
	    distance and direction of the destination.

    *   guess what this flow of info uses?
        events and listeners!!

*   DifferentialPilot
    *   expects to control a vehicle with two driving
        wheels, each with its own motor

    *   this object needs to know the wiring diagram
        of the robot, 
	e.g., which ports the motors are connected to,
              and whether rotating the motors forward
	         makes the robot go forward
        *   it needs know the diameter of the wheels
        *   and the width of the track (the distance
	    between the centers of the tracks of the
	    two wheels

...TravelTest.java