====== 10. Strojové učení ====== ===== Cíle cvičení ===== * Seznámení výstupem z 9DOF IMU MPU9250 * Rozpoznání náklonu akcelerometru * Interpretace IMU dat ===== Další zdroje ===== * https://github.com/tuupola/micropython-mpu9250 * https://randomnerdtutorials.com/raspberry-pi-pico-i2c-scanner-micropython/ * [[https://pythonnumericalmethods.berkeley.edu/notebooks/chapter16.00-Least-Squares-Regression.html|Least Squares Regression]] * http://www.bzarg.com/p/how-a-kalman-filter-works-in-pictures/ * {{ :courses:b0b37nsi:tutorials:1704.06053.pdf |Using Inertial Sensors for Position and Orientation Estimation}} ===== Rozpoznání náklonu z akcelerometru ===== Cílem této úlohy je natrénovat SVM klasifikátor tak, aby rozpoznal přibližné naklonění akcelerometru. Abychom toho mohli dosáhnout, je třeba projít těmito kroky: - Získání trénovacích dat - Označení trénovacích dat (štítky) - Natrénování modelu - Predikce v reálném čase ==== Získání trénovacích dat ==== Modul 10 DOF IMU je připojen k RPi pomocí sběrnice I2C. Vyberte vhodné piny (např. ''SDA'' na pin ''0'' a ''SCL'' na pin ''1'') a modul připojte, pro napájení zvolte pin ''VSYS''. Z [[https://github.com/tuupola/micropython-mpu9250|githubu]] stáhněte moduly [[https://github.com/tuupola/micropython-mpu9250/blob/master/mpu9250.py|mpu9250.py]], [[https://github.com/tuupola/micropython-mpu9250/blob/master/mpu6500.py|mpu6500.py]] a [[https://github.com/tuupola/micropython-mpu9250/blob/master/ak8963.py|ak8963.py]]. Stažené moduly uložte do paměti RPi. Nádledující kód přečte data ze všech dostupných senzorů. import utime from machine import I2C, Pin from mpu9250 import MPU9250 i2c = I2C(0, scl=Pin(1), sda=Pin(0)) sensor = MPU9250(i2c) print("MPU9250 id: " + hex(sensor.whoami)) while True: print(sensor.acceleration) print(sensor.gyro) print(sensor.magnetic) print(sensor.temperature) utime.sleep_ms(1000) Jedná se o data typu float, takže je nutné promyslet, jak data efektivně přenést a případně uložit. S ohledem na rychlost přenosu a potřebnou přesnost může být výhodné přenášet data binárně. V Pythonu pak lze pro přenost a dekódování dat ve strukturách podobným jako v C využít knihovny [[https://docs.python.org/3/library/ctypes.html|ctypes]] nebo [[https://docs.python.org/3/library/struct.html|struct]]. === PC - příjem a uložení === Pro offline analýzu uložte data do souboru ve formátu CSV. To lze udělat např. pomocí modulu [[https://docs.python.org/3/library/csv.html|csv]]. Následující kód předpokládá, že jsou data získána (ze sériového portu, z databáze, z API rozhraní služby) ve formě seznamu. import csv header = ['acc_x', 'acc_y', 'acc_z', 'gyr_x', 'gyr_y', 'gyr_z'] data = [0.0, 0.0, 0.0, 0.0, 0.0, 0.0] with open('data.csv', 'w', encoding='UTF8', newline='') as f: writer = csv.writer(f) # write the header writer.writerow(header) # write the data writer.writerow(data) ==== Přiřazení štíků ==== Rozpoznání náklonu akcelerometru je velmi jednoduchá klasifikační úloha. Hledané třídě (náklonu) odpovídá kombinace diskrétní hodnot, získaných z IMU. Nasbíraná data rozdělíme do tříd tak, že do jednotlivých řádků doplníme jednoznačný štítek, např. takto * 0 - vodorovně * 1 - náklon dopředu * 2 - náklon dozadu Štítky nemusí být číselné, může to být i textový řetězec. Příklad výsledného souboru: acc_x,acc_y,acc_z,gyr_x,gyr_y,gyr_z,class 0.076416015625,-0.04150390625,1.00341796875,0.030517578125,6.591796875,0.9307861328125,0 0.1044921875,-0.04052734375,0.851318359375,-2.95257568359375,9.6435546875,-0.38909912109375,0 ... 0.173583984375,0.426513671875,0.89892578125,2.99072265625,10.36834716796875,1.8768310546875,1 0.146728515625,0.327392578125,0.689697265625,3.692626953125,4.31060791015625,4.6844482421875,1 ... -0.076904296875,-0.660888671875,0.782958984375,5.767822265625,2.02178955078125,2.4566650390625,2 -0.1162109375,-0.67138671875,0.619384765625,6.44683837890625,-15.106201171875,-0.61798095703125,2 ==== Trénování klasifikátoru ==== Uložená data použijeme jako trénovací (70% dat) a testovací (30% dat) množinu pro získání klasifikátoru. import pandas as pd import numpy as np from sklearn.model_selection import train_test_split from sklearn import svm import pickle dataset = pd.read_csv('data.csv') X = dataset.iloc[:, [0, 1, 2, 3, 4, 5]].values y = dataset.iloc[:, [6]].values X_train, X_test, y_train, y_test = train_test_split(X, y, test_size = 0.30, random_state = 0) clf = svm.SVC(kernel='linear') clf.fit(X_train, np.ravel(y_train)) Klasifikátor je možné uložit pro pozdější použití např. pomocí modulu [[https://docs.python.org/3/library/pickle.html|pickle]]. filename = 'model.sav' pickle.dump(clf, open(filename, 'wb')) ==== Predikce ==== Pokud máme k dispozici model, je možné použít předikci z dat, které v reálném čase získáváme z IMU: clf = pickle.load(open('model.sav', 'rb')) # ziskani dat D = [[data.acc_x, data.acc_y, data.acc_z, data.gyr_x, data.gyr_y, data.gyr_z]] # predikce print(clf.predict(D)) ===== IMU interpretace ===== {{:courses:b0b37nsi:tutorials:7e35672ed3e05191cb6aea0d69cf6ebb98bcb88a.png?400|}} pitch = 180 * atan2(acc_x, sqrt(acc_y*acc_y + acc_z*acc_z))/PI; roll = 180 * atan2(acc_y, sqrt(acc_x*acc_x + acc_z*acc_z))/PI; Vyzkoušejte vypočítat hodnoty a zamyslet se nad tím, jaké výsledky získáváte. Další linky: https://silo.tips/download/application-note-imu-visualization-software https://github.com/jarzebski/Arduino-ADXL345 http://davidegironi.blogspot.com/2013/02/avr-atmega-mpu6050-gyroscope-and.html#.YnpJnZYzXrc https://www.instructables.com/Arduino-MPU6050-GY521-6-Axis-Accelerometer-Gyro-3D/ https://www.slideshare.net/dibaowang/imu-general-introduction ===== Kód pro vizualizaci dat z gyroskopu ===== Předpokládejme, že ve třech prvních sloupcích CSV souboru jsou data přečtená z gyroskopu. Jejich vizualizaci můžeme provést např. takto: from mpl_toolkits import mplot3d import pandas as pd import matplotlib.pyplot as plt data = pd.read_csv('data1.csv') ax = plt.axes(projection='3d') x = data.iloc[:,0] y = data.iloc[:,1] z = data.iloc[:,2] ax.scatter3D(x, y, z, color='green') plt.show()