Friday 16 January 2009

End-project. PART VIII



Date: 13 01 2009
Duration of activity: 3 hours + (4 hours homework + 7 hours of homework)
Group members participating: all group members (Anders D. of homework + Anders B. of homework)



1. The Goal



The goal of this lab session is to make further adjustments to the motor-, calibration- and navigation- layers, and to test out the gradient interpreter and some implementation of bogus handler layer.

2. The Plan




  • Make further necessary adjustments to the motor layer.

  • Make further necessary adjustments to the calibration layer.

  • Make further necessary adjustments to the navigation layer.

  • Run tests on the methods of the gradient interpreter layer.

  • Run test on the bogus handler class.



3. The Results


3.1. Motor layer




  • MotorSpeed() has the idea if the lower most border is hit, the tacho count is reset.

  • setSpeed(MotorPort motor, int speed) now before setting a speed, it is explicitly (as opposed to before, where consistency of the data structure was relied upon) checked if no borders were reached (no push sensors were pressed).



So basically the new thing for this motor layer is that we explicitly check if we are not at any border before starting to move (trying to move towards the border whenever we are at it would be opposite of what we are trying to achieve with these touch sensors). What is more, when we know that we are at the border which indicates min values of x-axis, we reset tacho counts to be zero to increase precision in a best-effort approach: When the lower endpoint is hit, we're at 0 by definition---so let's make it so, if it wasn't already.


3.2. Calibration layer


This outlines the changes in the layer, not the layer's cumulative behaviour.

  • getCoordinate(MotorPort motor) now actually returns cached values.

  • reCalibrate() assigns values to be cached.

  • reZero() handles all re-zeroing process together with writing intermediate values to the screen.



The calibration layer caches coordinate values, so it would be easier to deal with them. The re-zeroing process is actually working now. This is all about going forcefully all the way to the min of x-axis and re-zeroing the tacho count. The same thing applies to the y-axis as well.


3.3. Navigation layer



The significant thing is that in all the methods in the navigation layer that was suppose to use double but ended up using int's, was changed to float as double is not supported in lejos, and int's do not give the required precision. This change to this interface also prompted changing all the underlaying layers use of int, where more precise type was needed, to float. Floats are only 32-bit types, compared to doubles, which are 64-bit, but they will suffice for our needs.


3.4. Gradient interpreter layer


This newly added layer implementation does a high-level job. It handles a queue of operations (which are expressed throgh the gradientlayer.GradientGiver interface) and runs through those in order. The algorithm is based on parametric functions, where the parameter is the time. Thus, a line segment (gradientlayer.LineGG) is drawn at a certain speed, and at n milliseconds from the start of the line segment drawing, the line segment should be n / linesegment.getDuration() done. Thus, the gradient interpreter layer---which has a NavigationLayer at its disposal for the ugly work---only needs to derive the relative time since start-of-movement and throw the (GradientGiver-given) vector of ideal coordinates after its NavigationLayer-reference. This is a mean and clean way to use separation of concerns, and indeed this does significantly beautify the GradientInterpreter implementation:

GradientInterpreterStandard is responsible for layer handling.

  • GradientInterpreterStandard(NavigationLayer nav) is the constructor of the class.

  • assureMaintainerRunning() runs one operation at a time.

  • interactivelyRunOperation(GradientGiver operation) runs an operation from start to end. Precondition/postcondition is that the robot will have been controlled to be at the specified position for the movement.

  • enqueue(GradientGiver newone) pushes a new object to the queue.

  • wipeQueue() clear the queue.

  • reZero() not yet implemented.




ArcGG handles arc drawing.

  • ArcGG(float[] start, float[] centerpoint, float[] end, int total_time) is a class constructor where some rules regarding drawing arcs are defined.

  • float[] coordinatesAt(int time) returns coordinates following the arc segment, takes time parameter as input, that is in milliseconds, returns an array of x,y,z-coordinates to be at.



LineGG handles line drawing.

  • LineGG(float start[], float end[], int total_time) is a class constructor.

  • float[] coordinatesAt(int time) returns coordinates following the line, taking a time parameter as input, that is in milliseconds. Returns an array of x,y,z-coordinates to be at.



PCDriver

  • main (String[] args) drives the PC-side dumping, as detailed later.



The gradient interpreter layer is a layer on top of the navigation layer. Classes gradientlayer.LineGG and gradientlayer.ArcGG contain the rules of how to draw a line and how to draw an arc. The gradient interpreter layer is responsible for dealing with operations: Enqueueing them, performing them one by one, and checking that they make sense. These operation in our case basically means going from one point in the coordinate system to the other, in some fashion that is specified throug GradientGiver (which is abbreviated ``GG'', as in ArcGG).

3.5. Bogus handler layer




  • main (String[] args) is assigned some test case that suppose to draw a square with round corners.



This class currently basically only contains a definition of a square with rounded corners. The definition for a line is all about its starting and ending points. The definition for an arc requires the center coordinates of the circle that the arc would form if it would go around. This would change significantly, later on.

4. Conclusion



During this lab session the three lowermost layers were adjusted. The most significant things are that the motor layer---before setting the speed value---checks if no borders were reached (no touch sensors touched) and the calibration layer caches coordinate values. The gradient interpreter layer contains rules for drawing arcs and lines, and the BogusHandler has a method with a definition of a square with rounded corners.


No comments: