Połącz się z Aidlabem i wykorzystaj dane o ułożeniu ciała do zbudowania prostego detektora. Pokazujemy kod i ograniczenia tej metody.
W tym poradniku zbudujemy prosty detektor snu na podstawie ułożenia ciała. Połączymy się z pasem piersiowym Aidlab, odczytamy dane o orientacji i sprawdzimy, jak długo użytkownik leży. Dostęp do surowych danych ruchowych pojawił się w Aidlab SDK 1.0.3.
- Utwórz pusty katalog, a w nim plik
basic-sleep-detector.py. - Zainstaluj Aidlab Python SDK.
Odbieranie danych
Wyszukaj urządzenia za pomocą AidlabManager i połącz się z wybranym Aidlabem. Klasa implementująca DeviceDelegate odbierze dane o orientacji, gdy rozpoczniesz pomiar:
import asyncio
from time import time
from aidlab import AidlabManager, DataType, DeviceDelegate, DisconnectReason
class MainManager(DeviceDelegate):
def __init__(self):
self.startTimeOfSleepingPosition = 0
self.isInSleepingPosition = False
async def run(self):
devices = await AidlabManager().scan()
if len(devices) > 0:
print("Connecting to:", devices[0].address)
await devices[0].connect(self)
while True:
await asyncio.sleep(1)
def did_connect(self, device):
print("Connected to:", device.address)
asyncio.create_task(device.collect([DataType.ORIENTATION], []))
def did_disconnect(self, device, reason: DisconnectReason):
print("Disconnected from:", device.address, reason)
def did_receive_quaternion(self, device, timestamp, qw, qx, qy, qz):
self.naiveSleepDetector([qw, qx, qy, qz])
if __name__ == '__main__':
asyncio.run(MainManager().run())
Dane o orientacji pochodzą z dziewięcioosiowego czujnika inercyjnego (IMU). W tym przykładzie odbieramy je z częstotliwością 30 Hz.
Określanie ułożenia ciała względem pionu
Najpierw sprawdzimy, czy użytkownik leży. Wykorzystamy do tego orientację klatki piersiowej względem podłogi. Rozróżnimy trzy pozycje:
Up— użytkownik leży na plecach,Down— użytkownik leży na brzuchu lub robi pompki,Front— użytkownik stoi, chodzi, siedzi itp.
Callback przekazuje kwaternion do funkcji naiveSleepDetector. Ta ustala orientację i wywołuje detektor:
def did_receive_quaternion(self, device, timestamp, qw, qx, qy, qz):
self.naiveSleepDetector([qw, qx, qy, qz])
def naiveSleepDetector(self, value):
quaternion = value[0:4]
verticalOrientation = self.determineVerticalOrientation(
quaternion[0], quaternion[1], quaternion[2], quaternion[3])
# Sleep detection heuristic
self.basicSleepDetector(verticalOrientation)
Do określenia ułożenia ciała wykorzystamy następującą operację:
Quaternion x UpVector
Składowa Z obróconego wektora pozwala przypisać jedną z etykiet używanych w kodzie:
Z >= 0.5—OrientationDown,Z <= -0.5—OrientationUp,- pozostałe wartości —
OrientationFront.
Zapiszmy tę logikę w kodzie:
def determineVerticalOrientation(self, qW, qX, qY, qZ):
normalVec = self.normalVectorToUp(qW, qX, qY, qZ)
if normalVec[2] >= 0.5:
return "OrientationDown"
elif normalVec[2] <= -0.5:
return "OrientationUp"
else:
return "OrientationFront"
Obrót wektora za pomocą kwaternionu zapisujemy następująco:
V' = Q * V * conjugate(Q)
Wektor V traktujemy tu jako kwaternion, w którym w=0:
def normalVectorToUp(self, qW, qX, qY, qZ):
quat = self.multQuat(qW, qX, qY, qZ, 0, 0, 0, 1)
quat = self.multQuat(quat[0], quat[1], quat[2], quat[3], qW, -qX, -qY, -qZ)
return [quat[1], quat[2], quat[3]]
def multQuat(self, w, x, y, z, qW, qX, qY, qZ):
newW = w * qW - x * qX - y * qY - z * qZ
newX = w * qX + x * qW + y * qZ - z * qY
newY = w * qY + y * qW + z * qX - x * qZ
newZ = w * qZ + z * qW + x * qY - y * qX
return [newW, newX, newY, newZ]
Prosty detektor snu
Detektor mierzy czas spędzony w pozycji OrientationDown lub OrientationUp. Po dziesięciu minutach wyświetla komunikat o śnie. To uproszczone założenie: samo leżenie nie oznacza, że użytkownik zasnął.
def __init__(self):
super().__init__()
self.startTimeOfSleepingPosition = 0
self.isInSleepingPosition = False
def basicSleepDetector(self, verticalOrientation):
if (verticalOrientation == 'OrientationUp' or verticalOrientation == 'OrientationDown') and self.isInSleepingPosition == False:
self.isInSleepingPosition = True
self.startTimeOfSleepingPosition = time()
elif verticalOrientation == 'OrientationFront' and self.isInSleepingPosition:
self.startTimeOfSleepingPosition = 0
self.isInSleepingPosition = False
# Sleep detection heuristic:
# We are sleeping if we are in sleeping position for longer than 10 minutes
if self.isInSleepingPosition and (time() - self.startTimeOfSleepingPosition > 10 * 60):
print("I am sleeping")
Włącz Aidlaba i uruchom skrypt:
python basic-sleep-detector.py
Przykład nie rozpoznaje leżenia na boku. Aby uwzględnić tę pozycję, możesz rozbudować klasyfikację o kąty RPY (roll, pitch, yaw). Możesz też sprawdzić, czy dodatkowe sygnały — tętno, oddech lub temperatura skóry — pomagają odróżnić sen od spokojnego leżenia. Ten skrypt pokazuje punkt wyjścia do takich eksperymentów.
Ilustracja tytułowa: Vecteezy.








