Plotter module reference#
The Plotter module#
- class Plotter#
A base class for the BrachioGraph and PantoGraph subclasses.
This class provides all the interfaces you’ll need for the plotter in normal use.
All the classes (Plotter, BrachioGraph and PantoGraph) can be
instantiated without any arguments and will work for testing.
For testing with turtle graphics, you will need to use one of the subclasses.
Methods in general#
Hierarchy#
This table shows how the methods in the class Plotter depend on each other.
Each named method calls the method in the cell below it.
Order of arguments#
Many of these methods accept a similar set of arguments. For consistency, they always appear in the same order. Note that not all are available to all methods. They are:
what to draw:
filenameorlineswhere to draw:
boundsprecision and speed:
angular_step,wait,resolutionwhether to draw:
drawdirection and repetition:
repeat,reverse,bothimage transformations:
flip,rotate
Initialisation#
- Plotter.__init__(virtual=False, turtle=False, turtle_coarseness=None, bounds=[-10, 5, 10, 15], servo_1_parked_pw=1500, servo_2_parked_pw=1500, servo_1_degree_ms=-10, servo_2_degree_ms=10, servo_1_parked_angle=0, servo_2_parked_angle=0, hysteresis_correction_1=0, hysteresis_correction_2=0, servo_1_angle_pws=(), servo_2_angle_pws=(), servo_1_angle_pws_bidi=(), servo_2_angle_pws_bidi=(), pw_up=None, pw_down=None, angular_step=None, wait=None, resolution=None)#
- Parameters:
virtual (bool) – A virtual plotter will run in software only, and doesn’t expect any attached hardware. This allows work and development on a machine other than a Raspberry Pi, and to run automated tests.
turtle (bool) – Produces a graphical representation of the plotter and its behaviour using Python turtle graphics, as well as or instead of a physical plotter.
turtle_coarseness – For use with
turtle; a factor, in degrees, to represent the resolution of the servos by rounding values. Defaults to 1˚ if not specified.bounds (tuple) – Four numbers, indicating the area that the plotter should treat as its available area for drawing in. The numbers represent, in order the left, top, right and bottom boundaries. Defaults to usable values in the default subclass definitions.
servo_1_parked_pw (int) – The pulse-width of servo 1 when parked.
servo_2_parked_pw (int) – The pulse-width of servo 2 when parked.
servo_1_degree_ms (float) – Milliseconds pulse-width difference per degree of movement.
servo_2_degree_ms (float) – Milliseconds pulse-width difference per degree of movement.
servo_1_parked_angle (float) – The arm angle in the parked position.
servo_2_parked_angle (float) – The arm angle in the parked position.
hysteresis_correction_1 (float) – Servo 1 hysteresis error compensation.
hysteresis_correction_2 (float) – Servo 2 hysteresis error compensation.
servo_1_angle_pws (tuple) – Pulse-widths for various angles of servo 1.
servo_2_angle_pws (tuple) – Pulse-widths for various angles of servo 2.
servo_1_angle_pws_bidi (tuple) – Pulse-widths for various angles of servo 1, collected in both clockwise and anti-clockwise directions. This is introduced in the tutorial.
servo_2_angle_pws_bidi (tuple) – Pulse-widths for various angles of servo 2, collected in both clockwise and anti-clockwise directions.
pw_up (int) – The pulse-width for the pen’s up position.
pw_down (int) – The pulse-width for the pen’s down position.
wait (float) – A time in seconds that the plotter will rest after making a movement. If not specified, will be initialised as 0.01, or 0 for a virtual-only plotter.
angular_step (float) – An angle in degrees that determines how big each discrete step in a series of movements of the arm servos will be. If not specified, will be initialised as 0.1.
resolution (float) – A distance in centimetres. When drawing between two points, any line longer than
resolutionwill be broken down into a series of points no more thanresolutioncm apart. This allows the plotter to approximate straight lines by drawing a series of shorter curved lines (all the lines the plotter naturally draws are curved). If not specified, will be initialised as 0.1.
In all the methods below, arguments that are also attributes of the plotter class need only be used to override those values (which is generally not required).
Image-plotting methods#
These methods draw an image (as a series of lines, encoded in JSON).
- Plotter.plot_file(filename='', bounds=None, angular_step=None, wait=None, resolution=None)#
Plots and image encoded as JSON lines in
filename. Passes the lines in the supplied JSON file toplot_lines().
- Plotter.plot_lines(lines=[], bounds=None, angular_step=None, wait=None, resolution=None, flip=False, rotate=False)#
Passes each segment of each line in lines to
draw_line()
Pattern-drawing methods#
- Plotter.box(bounds=None, angular_step=None, wait=None, resolution=None, repeat=1, reverse=False)#
Draw a box marked out by the
bounds.
- Plotter.test_pattern(lines=4, bounds=None, angular_step=None, wait=None, resolution=None, repeat=1, reverse=False, both=False)#
- Plotter.vertical_lines(lines=4, bounds=None, angular_step=None, wait=None, resolution=None, repeat=1, reverse=False, both=False)#
- Plotter.horizontal_lines(lines=4, bounds=None, angular_step=None, wait=None, resolution=None, repeat=1, reverse=False, both=False)#
- Plotter.draw_line(start=(0, 0), end=(0, 0), angular_step=None, wait=None, resolution=None, both=False)#
Draws a line between two points
Drawing methods using x/y co-ordinates#
All of the methods above call xy:
- Plotter.xy(x=None, y=None, angular_step=None, wait=None, resolution=None, draw=False)#
Moves the pen to the xy position; optionally draws while doing it.
Nonefor x or y means that the pen will not be moved in that dimension.
Drawing methods using servo angle values#
- Plotter.move_angles(angle_1=None, angle_2=None, angular_step=None, wait=None, draw=False)#
Moves the servo motors to the specified angles step-by-step, calling
set_angles()for each step.Nonefor one of the angles means that that servo will not move.
Pen-moving methods#
- Plotter.set_angles(angle_1=None, angle_2=None)#
Moves the servo motors to the specified angles immediately. Relies upon getting accurate pulse-width values.
Nonefor one of the angles means that that servo will not move.Calls
set_pulse_widths().Sets
current_x,current_y.
- Plotter.park()#
Angles to pulse widths#
A plotter needs to move its arms to the correct angles, by providing the appropriate pulse-width to each servo.
- Plotter.angles_to_pw_1()#
- Plotter.angles_to_pw_2()#
These methods - one for each servo - take the angle as an argument and return a pulse-width.
The methods themselves stand in for functions that do the actual calculation; which function is
assigned to the angles_to_pw_1/angles_to_pw_2 attributes depends upon how much
information is provided about the servos when the plotter is initialised.
Naive calculation#
The default is to use “naive” functions (naive_angles_to_pulse_widths_1 and
naive_angles_to_pulse_widths_2), that assume linearity (1˚ of movement corresponds to a 10µs
change in pulse-width), will be used.
- Plotter.naive_angles_to_pulse_widths_1(angle)#
A rule-of-thumb calculation of pulse-width for the desired servo angle
- Plotter.naive_angles_to_pulse_widths_2(angle)#
A rule-of-thumb calculation of pulse-width for the desired servo angle
Sophisticated calculation#
In practice the response of servos is not linear. If a series of
pulse-width/angle values are supplied, then numpy (numpy.poly1d(numpy.polyfit)) will provide a
polynomial funtion that matches the curve corresponding to those values.
Line processing#
- Plotter.analyse_lines(lines=[], rotate=False, bounds=None)#
Analyses the co-ordinates in
lines, and returns:rotate:Trueif the image needs to be rotated by 90˚ in order to fit betterx_mid_point,y_mid_point: mid-points of the imagebox_x_mid_point,box_y_mid_point: mid-points of theboundsdivider: the value by which we must divide all x and y so that they will fit safely inside the bounds.
linesis a tuple itself containing a number of tuples, each of which contains a number of 2-tuples:[ [ [3, 4], # | [2, 4], # | [1, 5], # a single point in a line # | a list of points defining a line [3, 5], # | [3, 7], # | ], [ # all the lines [...], [...], ], [ [...], [...], ], ]
- Plotter.rotate_and_scale_lines(lines=[], rotate=False, flip=False, bounds=None)#
Rotates and scales the lines so that they best fit the available drawing
bounds.
Physical control#
- Plotter.set_pulse_widths(pw_1=None, pw_2=None)#
Applies the supplied pulse-width values to the servos, or pretends to, if we’re in virtual mode.
- Plotter.get_pulse_widths()#
Returns the actual pulse-widths values; if in virtual mode, returns the nominal values - i.e. the values that they might be.
- Plotter.quiet(servos=[14, 15, 18])#
Stop sending pulses to the servos, so that they are no longer energised (and so that they stop buzzing).
Calibration and manual driving#
- Plotter.capture_pws()#
Helps capture angle/pulse-width data for the servos, as a dictionary to be used in a Plotter definition.
The controls are:
-10 µs
-1 µs
+ 10 µs
+ 1 µs
Shoulder
aAsSElbow
kKlLPen
zxCapture pulse-width value
cShow captured values
vExit
0
Reporting methods#
- Plotter.status()#
Provides a report of the plotter status. Subclasses should override this to report on their own status.
Trigonometric methods#
- Plotter.xy_to_angles(x=0, y=0)#
Return the servo angles required to reach any x/y position. This is a dummy method in the base class; it needs to be overridden in a sub-class implementation.
- Plotter.angles_to_xy(angle_1, angle_2)#
Return the servo angles required to reach any x/y position. This is a dummy method in the base class; it needs to be overridden in a sub-class implementation.
The BrachioGraph module#
- class BrachioGraph#
- __init__(virtual=False, turtle=False, turtle_coarseness=None, bounds=[-8, 4, 6, 13], inner_arm=8, outer_arm=8, servo_1_parked_pw=1500, servo_2_parked_pw=1500, servo_1_degree_ms=-10, servo_2_degree_ms=10, servo_1_parked_angle=-90, servo_2_parked_angle=90, hysteresis_correction_1=0, hysteresis_correction_2=0, servo_1_angle_pws=[], servo_2_angle_pws=[], servo_1_angle_pws_bidi=[], servo_2_angle_pws_bidi=[], pw_up=1500, pw_down=1100, wait=None, angular_step=None, resolution=None)#
Parameters are as for the
Plotterparent class, except for:- Parameters:
inner_arm (float) – The length of the inner arm, in cm.
outer_arm (float) – The length of the outer arm, in cm.
virtual (bool) –
turtle (bool) –
bounds (tuple) –
servo_1_parked_pw (int) –
servo_2_parked_pw (int) –
servo_1_degree_ms (int) –
servo_2_degree_ms (int) –
servo_1_parked_angle (int) –
servo_2_parked_angle (int) –
hysteresis_correction_1 (int) –
hysteresis_correction_2 (int) –
servo_1_angle_pws (tuple) –
servo_2_angle_pws (tuple) –
servo_1_angle_pws_bidi (tuple) –
servo_2_angle_pws_bidi (tuple) –
pw_up (int) –
pw_down (int) –
wait (float) –
angular_step (float) –
resolution (float) –