[+cc: systemd-devel] Bounced since I was not a member. On Mon, Jun 27, 2022 at 12:50 PM Gwendal Grignou <gwendal@xxxxxxxxxxxx> wrote: > > In 60-sensor.hwdb, we can specify a matrix to rotate sensor output to > match the expected 'natural' orientation [1]. > > When behind a screen, accelerometers are usually soldered upside down, > so a rotation matrix is needed to rotate their raw output into the > 'natural' orientation when read directly. > > When flat on a table, standalone accelerometers/IMUs report the force > exercised by the table to prevent the sensor from falling down > further. In the 'natural' orientation, this is [0, 0, 1g]. See for > instance the BMI160 specification[2], page 107). > > However, Gnome expects the sensor to return the gravity force itself, > as specified by windows and the HID specification: When flat on a > table, the expected value is [0, 0 , -1g]. > > Therefore, the matrix, in addition to rotating the sensors, should > also invert the axes. > When a matrix inverts the axes, its determinant is -1 [3]. > Out of the 160 matrices defined, 136 invert the axes, 29 does not and > one as a determinant equals to 0. > > That matrix, for Hometech device is obviously not correct: the sensor > input vector X component is is used for both Y and Z axes of the > output vector: > > ######################################### > # Hometech > ######################################## > > # Nobody bothered to use Linux on any device of this manufacturer > # so current marks might be too general and need fixes. > # These values are based on Wi101 model. > sensor:modalias:acpi:BMA250E*:dmi:*:svnInsyde*:pni101c:* > ACCEL_MOUNT_MATRIX=0,1,0;-1,0,0;-1,0,0 > > Remains 29 matrices where axes are not inverted: > 9 (':acpi:BOSC0200*', 1.0) > 3 (':acpi:INVN6500*', 1.0) > 2 (':acpi:KIOX010A*', 1.0) > 2 (':acpi:KIOX020A*', 1.0) > 1 (':acpi:KIOX0009*', 1.0) > 1 (':acpi:SMO8500:*', 1.0) > 1 (':acpi:MXC6655*', 1.0) > 1 (':acpi:ACCE0001*', 1.0) > 1 (':acpi:KIOX000A*', 1.0) > 1 (':i2c:bmc150_accel', 1.0) > 1 (':acpi:NCPE0388*', 1.0) > 1 (':acpi:SMO8500*', 1.0) > > Interestingly, some matrices for the same sensors are inverting axes: > KIOX000A* sensors axes are inverted 36 times. > > The reason is the expectation that in convertible devices the > accelerometers return the same data after rotation when the lid angle > is 0: > > # A note about setting ACCEL_MOUNT_MATRIX for ACCEL_LOCATION=base sensors, > # [...] This means that the > # base-accelerometer's mount-matrix must be such, that after applying > # the mount-matrices to both sensors, the base-accelerometer's readings must > # be identical to the display-accelerometer's readings (when the lid is > # closed). > > It means that one of 2 accelerometers is expected to not return data > in the 'normal' orientation. > > W3C device orientation specs [4] implies the sensors use the same > device coordinate frame, and therefore should return the same data > when the lid angle is 180 degree. > > The convention of aligning returned data to 180 degree lid angle can > be fixed completely in user space as long as the algorithm for > calculating lid angle and the udev tables are changed at the same > time. It will result that matrices defined for sensors that follow the > W3C specifications will always invert the axes. > > Regards, > Gwendal. > > [1]: > https://git.kernel.org/pub/scm/linux/kernel/git/jic23/iio.git/tree/Documentation/ABI/testing/sysfs-bus-iio#n1838 > > [2]: > https://www.bosch-sensortec.com/media/boschsensortec/downloads/datasheets/bst-bmi160-ds000.pdf > > [3]: > https://en.wikipedia.org/wiki/Determinant#Orientation_of_a_basis) > > [4] > https://w3c.github.io/deviceorientation/#deviceorientation > > python script to pocess the determinent of the matrices: > #!/usr/bin/python3 > > import collections > import numpy as np > import re > import sys > > > sensor_re=re.compile(r'sensor:modalias(.*):dmi.*') > matrix_re=re.compile(r' ACCEL_MOUNT_MATRIX=(.*)') > > sensors = [] > sensor_dict = collections.defaultdict(int) > for l in sys.stdin: > l = l.rstrip() > if l == '': > sensors = [] > sensor_match = sensor_re.match(l) > if sensor_match: > sensors.append(sensor_match.group(1)) > matrix_match = matrix_re.match(l) > if matrix_match: > matrix = np.matrix(matrix_match.group(1)) > for s in sensors: > sensor_dict[(s, np.linalg.det(matrix))] += 1 > > for k in sorted(sensor_dict, key=sensor_dict.get, reverse=True): > print(sensor_dict[k], k) > > Output of the script on 60-sensor.hwdb: > > cat 60-sensor.hwdb.txt | ~/bin/process_rotation_matrix.py > 36 (':acpi:KIOX000A*', -1.0) > 35 (':acpi:BOSC0200*', -1.0) > 29 (':acpi:SMO8500*', -1.0) > 14 (':acpi:INVN6500*', -1.0) > 14 (':acpi:BMA250E*', -1.0) > 9 (':acpi:BOSC0200*', 1.0) > 9 (':acpi:KIOX010A*', -1.0) > 6 (':platform:cros-ec-accel', -1.0) > 6 (':acpi:KIOX020A*', -1.0) > 4 (':i2c:bmc150_accel', -1.0) > 4 (':acpi:BMA250*', -1.0) > 3 (':acpi:KIOX0009*', -1.0) > 3 (':acpi:MXC6655*', -1.0) > 3 (':acpi:INVN6500*', 1.0) > 3 (':acpi:*BOSC0200*', -1.0) > 2 (':acpi:KIOX010A*', 1.0) > 2 (':acpi:KIOX020A*', 1.0) > 1 (':acpi:KIOX0009*', 1.0) > 1 (':acpi:SMO8500:*', 1.0) > 1 (':acpi:KXJ2109*', -1.0) > 1 (':acpi:BMI0160*', -1.0) > 1 (':acpi:MXC6655*', 1.0) > 1 (':acpi:*KIOX000A*', -1.0) > 1 (':acpi:ACCE0001*', 1.0) > 1 (':acpi:KIOX000A*', 1.0) > 1 (':acpi:KXCJ9000*', -1.0) > 1 (':acpi:BMA250E*', 0.0) > 1 (':i2c:bmc150_accel', 1.0) > 1 (':acpi:NCPE0388*', 1.0) > 1 (':acpi:SMO8840*', -1.0) > 1 (':acpi:DUAL250E*', -1.0) > 1 (':acpi:SMO8500*', 1.0) > 1 (':acpi:KIOX0008*', -1.0)