This question is about deriving a mathematical function that returns pairs of values based on arrays of data - two-dimensional values from two-dimensional values.
I have created a Python library that drives a pen-plotter using cheap servo motors.
From the x/y position of the pen, I obtain the required angles of the motors, and from that the pulse-widths that need to be fed to them.
These cheap motors are of course rather non-linear and the mechanical system as a whole exhibits hysteresis and distorting behaviours.
The library can calculate the required pulse-width values in different ways. One way is to determine some actual pulse-width/angle measurements for each servo, like so:
servo_angle_pws = [
# angle, pulse-width
[ 45, 1000],
[ 60, 1200],
[ 90, 1500],
[120, 1800],
[135, 2000],
]
and then use numpy to create a function that fits the curve described by those values:
servo_2_array = numpy.array(servo_2_angle_pws)
self.angles_to_pw = numpy.poly1d(numpy.polyfit(servo_2_array[:, 0], servo_2_array[:, 1], 3))
Which would look like this:
Now I'd like to take another step, and find a function in a similar way that gives me me the relationship between x/y positions and pulse-widths rather than angles (this will provide greater accuracy, as it will take into account more real-world imperfections in the system). In this case though, I will have two pairs of values, like this:
# x/y positions, servo pulse-widths
((-8.0, 8.0), (1900, 1413)),
((-8.0, 4.0), (2208, 1605)),
(( 8.0, 4.0), ( 977, 1622)),
((-0.0, 4.0), (1759, 1999)),
(( 6.0, 13.0), (1065, 1121)),
My question is: what do I need to do to get a function (I'll need two of them of course) that returns pulse-width values for a desired pair of x/y positions? For example:
pw1 = xy_to_pulsewidths1(x=-4, y=6.3)
pw2 = xy_to_pulsewidths2(x=-4, y=6.3)
I believe that I need to do a "multivariate regression" - but I am no mathematician so I don't know if that's right, and even if it is, I have not yet found anything in my researches in numpy and scipy that indicates what I would actually need to do in my code.

