forked from MicroPythonOS/MicroPythonOS
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathtest_calibration_check_bug.py
More file actions
162 lines (128 loc) · 5.47 KB
/
test_calibration_check_bug.py
File metadata and controls
162 lines (128 loc) · 5.47 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
"""Test for calibration check bug after calibrating.
Reproduces issue where check_calibration_quality() returns None after calibration.
"""
import unittest
import sys
# Mock hardware before importing SensorManager
class MockI2C:
def __init__(self, bus_id, sda=None, scl=None):
self.bus_id = bus_id
self.sda = sda
self.scl = scl
self.memory = {}
def readfrom_mem(self, addr, reg, nbytes):
if addr not in self.memory:
raise OSError("I2C device not found")
if reg not in self.memory[addr]:
return bytes([0] * nbytes)
return bytes(self.memory[addr][reg])
def writeto_mem(self, addr, reg, data):
if addr not in self.memory:
self.memory[addr] = {}
self.memory[addr][reg] = list(data)
class MockQMI8658:
def __init__(self, i2c_bus, address=0x6B, accel_scale=0b10, gyro_scale=0b100):
self.i2c = i2c_bus
self.address = address
self.accel_scale = accel_scale
self.gyro_scale = gyro_scale
@property
def temperature(self):
return 25.5
@property
def acceleration(self):
return (0.0, 0.0, 1.0) # At rest, Z-axis = 1G
@property
def gyro(self):
return (0.0, 0.0, 0.0) # Stationary
# Mock constants
_QMI8685_PARTID = 0x05
_REG_PARTID = 0x00
_ACCELSCALE_RANGE_8G = 0b10
_GYROSCALE_RANGE_256DPS = 0b100
# Create mock modules
mock_machine = type('module', (), {
'I2C': MockI2C,
'Pin': type('Pin', (), {})
})()
mock_qmi8658 = type('module', (), {
'QMI8658': MockQMI8658,
'_QMI8685_PARTID': _QMI8685_PARTID,
'_REG_PARTID': _REG_PARTID,
'_ACCELSCALE_RANGE_8G': _ACCELSCALE_RANGE_8G,
'_GYROSCALE_RANGE_256DPS': _GYROSCALE_RANGE_256DPS
})()
def _mock_mcu_temperature(*args, **kwargs):
return 42.0
mock_esp32 = type('module', (), {
'mcu_temperature': _mock_mcu_temperature
})()
# Inject mocks
sys.modules['machine'] = mock_machine
sys.modules['mpos.hardware.drivers.qmi8658'] = mock_qmi8658
sys.modules['esp32'] = mock_esp32
try:
import _thread
except ImportError:
mock_thread = type('module', (), {
'allocate_lock': lambda: type('lock', (), {
'acquire': lambda self: None,
'release': lambda self: None
})()
})()
sys.modules['_thread'] = mock_thread
# Now import the module to test
from mpos import SensorManager
class TestCalibrationCheckBug(unittest.TestCase):
"""Test case for calibration check bug."""
def setUp(self):
"""Set up test fixtures before each test."""
# Reset SensorManager state
SensorManager._initialized = False
SensorManager._imu_driver = None
SensorManager._sensor_list = []
SensorManager._has_mcu_temperature = False
# Create mock I2C bus with QMI8658
self.i2c_bus = MockI2C(0, sda=48, scl=47)
self.i2c_bus.memory[0x6B] = {_REG_PARTID: [_QMI8685_PARTID]}
def test_check_quality_after_calibration(self):
"""Test that check_calibration_quality() works after calibration.
This reproduces the bug where check_calibration_quality() returns
None or shows "--" after performing calibration.
"""
# Initialize
SensorManager.init(self.i2c_bus, address=0x6B)
# Step 1: Check calibration quality BEFORE calibration (should work)
print("\n=== Step 1: Check quality BEFORE calibration ===")
quality_before = SensorManager.check_calibration_quality(samples=10)
self.assertIsNotNone(quality_before, "Quality check BEFORE calibration should return data")
self.assertIn('quality_score', quality_before)
print(f"Quality before: {quality_before['quality_rating']} ({quality_before['quality_score']:.2f})")
# Step 2: Calibrate sensors
print("\n=== Step 2: Calibrate sensors ===")
accel = SensorManager.get_default_sensor(SensorManager.TYPE_ACCELEROMETER)
gyro = SensorManager.get_default_sensor(SensorManager.TYPE_GYROSCOPE)
self.assertIsNotNone(accel, "Accelerometer should be available")
self.assertIsNotNone(gyro, "Gyroscope should be available")
accel_offsets = SensorManager.calibrate_sensor(accel, samples=10)
print(f"Accel offsets: {accel_offsets}")
self.assertIsNotNone(accel_offsets, "Accelerometer calibration should succeed")
gyro_offsets = SensorManager.calibrate_sensor(gyro, samples=10)
print(f"Gyro offsets: {gyro_offsets}")
self.assertIsNotNone(gyro_offsets, "Gyroscope calibration should succeed")
# Step 3: Check calibration quality AFTER calibration (BUG: returns None)
print("\n=== Step 3: Check quality AFTER calibration ===")
quality_after = SensorManager.check_calibration_quality(samples=10)
self.assertIsNotNone(quality_after, "Quality check AFTER calibration should return data (BUG: returns None)")
self.assertIn('quality_score', quality_after)
print(f"Quality after: {quality_after['quality_rating']} ({quality_after['quality_score']:.2f})")
# Verify sensor reads still work
print("\n=== Step 4: Verify sensor reads still work ===")
accel_data = SensorManager.read_sensor(accel)
self.assertIsNotNone(accel_data, "Accelerometer should still be readable")
print(f"Accel data: {accel_data}")
gyro_data = SensorManager.read_sensor(gyro)
self.assertIsNotNone(gyro_data, "Gyroscope should still be readable")
print(f"Gyro data: {gyro_data}")
if __name__ == '__main__':
unittest.main()