# "Coordinate Transformation Matrix" and "libinput Calibration Matrix" - how are they related?

What's the exact format of "libinput Calibration Matrix" (i.e. what does each of its elements represent) and how is it related to "Coordinate Transformation Matrix"? If "Coordinate Transformation Matrix" is responsible for mapping a touchscreen point to display point, why doesn't it suffice and why is "libinput Calibration Matrix" needed as well? Which part of calibration process is each of the matrices responsible for?

I haven't been able to find a single reference site explaining what elements of "libinput Calibration Matrix" stand for (as opposed to "Coordinate Transformation Matrix"). All I managed to find is the following "definition" of relevant coefficients:

``````a = (screen_x * 6 / 8) / (c3_x - c0_x)
c = ((screen_x / 8) - (a * c0_x)) / screen_x
e = (screen_y * 6 / 8) / (c3_y - c0_y)
f = ((screen_y / 8) - (e * c0_y)) / screen_y
``````

without any explanation of how they've been derived/what they are supposed to represent. To sum up: what's the "official" definition of "libinput Calibration Matrix" and how is it different from "Coordinate Transformation Matrix"?

• Idk offhand what's the difference, but an answer to "what does each of its elements represent" you can find in this section of libinput docs. It is interesting that the section references the Wikipedia article about transformation matrix, which makes me think it indeed does the same thing. Sep 14, 2020 at 17:32
• @Hi-Angel Aren't the matrices for 90 and 270 degrees swapped in the docs you gave a link to (if we decide to stick with "clockwise" direction)? According to wikipedia and other sources, rotation matrix with consecutive elements "0 -1 1 1 0 0 0 0 1" represents rotation by 90 degrees counterclockwise, not clockwise. Also, this website: wiki.ubuntu.com/X/InputCoordinateTransformation seems to erroneously call left rotation "clockwise" instead of "counterclockwise". Is this a matter of some strange convention or are they both wrong in this matter? Sep 15, 2020 at 9:23

I developed xlibinput_calibrator. Here [1] you can find an implementation of the math behind the computation of the "Calibration Matrix".

Basically you need to transform the coordinates from the "touch space" to the "screen space". To do this first you need to collect at least the coordination of 3 points both in the "touch space" and "screen space". [2]

The calibration matrix (C), the coordinates in "touch space" (tx_i, ty_i, where i=1,2,3) and the coordinates in "screen space" (sx_i, sy_i) are related by the following formulas:

```
⎡tx₁  tx₂  tx₃⎤
⎢             ⎥
Ti =  ⎢ty₁  ty₂  ty₃⎥
⎢             ⎥
⎣ 0    0    1 ⎦

⎡sx₁  sx₂  sx₃⎤
⎢             ⎥
Si =  ⎢sy₁  sy₂  sy₃⎥
⎢             ⎥
⎣ 0    0    1 ⎦

⎡a  b  c⎤
⎢       ⎥
C =   ⎢d  e  f⎥
⎢       ⎥
⎣0  0  1⎦

⎡a  b  c⎤     ⎡tx₁  tx₂  tx₃⎤    ⎡sx₁  sx₂  sx₃⎤
⎢       ⎥     ⎢             ⎥    ⎢             ⎥
⎢d  e  f⎥  x  ⎢ty₁  ty₂  ty₃⎥ =  ⎢sy₁  sy₂  sy₃⎥
⎢       ⎥     ⎢             ⎥    ⎢             ⎥
⎣0  0  1⎦     ⎣ 0    0    1 ⎦    ⎣ 0    0    1 ⎦

C * Ti = Si  => C = Si * inv(Ti)

```

where "inv(Ti)" compute the inverse matrix of Ti. The results are (thank Octave):

```     sx₁⋅ty₂ - sx₂⋅ty₁
a =  ─────────────────
tx₁⋅ty₂ - tx₂⋅ty₁

- sx₁⋅tx₂ + sx₂⋅tx₁
b =  ───────────────────
tx₁⋅ty₂ - tx₂⋅ty₁

sx₁⋅(tx₂⋅ty₃ - tx₃⋅ty₂)  + sx₂⋅(tx₁⋅ty₃ - tx₃⋅ty₁) + sx₃⋅(tx₁⋅ty₂ - tx₂⋅ty₁)
c =  ──────────────────────────────────────────────────────────────────────────────
tx₁⋅ty₂ - tx₂⋅ty₁

sy₁⋅ty₂ - sy₂⋅ty₁
d =  ─────────────────
tx₁⋅ty₂ - tx₂⋅ty₁

-sy₁⋅tx₂ +sy₂⋅tx₁
e =  ─────────────────
tx₁⋅ty₂ - tx₂⋅ty₁

sy₁⋅(tx₂⋅ty₃ - tx₃⋅ty₂) - sy₂⋅(tx₁⋅ty₃ - tx₃⋅ty₁) + sy₃⋅(tx₁⋅ty₂ - tx₂⋅ty₁)
f =  ────────────────────────────────────────────────────────────────────────────
tx₁⋅ty₂ - tx₂⋅ty₁

```

The one above is the "general" formula, where are considered also cases like the rotation and axis inversion (and their combination). The one that you posted is a simpler one (which need only 2 points) which may fails in these cases.

You have also to take in consideration that libinput want the matrix in the normalized form (Cn). So it becomes

```                   ⎡        b⋅sy            b⋅dy⋅sy     c     ⎤
⎢ a      ────     a⋅dx + ─────── + ── - dx⎥
⎢         sx               sx      sx     ⎥
⎢                                         ⎥
⎢d⋅sx              d⋅dx⋅sx               f ⎥
Cn =   ⎢────     e       ─────── + dy⋅e - dy + ──⎥
⎢ sy                 sy                 sy⎥
⎢                                         ⎥
⎣ 0       0                  1            ⎦

```

where

• sx = 1/width
• sy = 1/height
• dx = minx
• dy = miny

[2] in xlibinput_calibrator, I take 4 points and the result matrix is the average of the 4 matrices computed by any combination of the points.

• Thank you for your answer. Some time ago I needed to write a custom calibration tool, in order to understand the basic principles of how such tools work I had to analyze source code of xinput-calibrator which took me a great deal of time. Jan 16, 2021 at 12:08
• I tryed to calculate by `The results are (thank Octave):` formulas, but results too big `c` and `f`
– eri
May 21, 2021 at 10:32
• c,f fixed by changing formulas to numpy.
– eri
May 21, 2021 at 11:48