|
|
(Nie pokazano 122 pośrednich wersji utworzonych przez tego samego użytkownika) |
Linia 1: |
Linia 1: |
| [[category:Pracownie specjalistyczne]] | | [[category:Pracownie specjalistyczne]] |
| <!-- __NOTOC__ --> | | <!-- __NOTOC__ --> |
− | ==Wprowadzenie == | + | |
| + | ===Materiały dydaktyczne=== |
| + | #[[Nowe_technologie_w_fizyce_biomedycznej/Posturografia|Posturografia]] |
| + | #[[Nowe_technologie_w_fizyce_biomedycznej/Kamery 3D|Kamery 3D]] |
| + | #[[Nowe_technologie_w_fizyce_biomedycznej/Raspberry Pi|Raspberry Pi]] |
| + | ===Opis=== |
| Przedmiot "Nowe technologie w fizyce biomedycznej" to 30 godzin zajęć i 3 punkty ECTS. Jego celem jest umożliwienie studentom wykorzystania rewolucyjnych i tanich technologii, nie uwzględnianych dotychczas w programach kształcenia w UW, w działalności naukowej i gospodarczej, oraz rozbudzenie kreatywności. Adresowany jest do studentów studiów II stopnia Fizyki Medycznej i Neuroinformatyki na Wydziale Fizyki. Zajęcia mają formę zajęć warsztatowych/pracowni. Przewiduje się 7 stanowisk dla 14 studentów pracujących w parach. Pojedyncze zajęcia na pracowni trwają 2h. Program podzielony jest na 3 bloki tematyczne: | | Przedmiot "Nowe technologie w fizyce biomedycznej" to 30 godzin zajęć i 3 punkty ECTS. Jego celem jest umożliwienie studentom wykorzystania rewolucyjnych i tanich technologii, nie uwzględnianych dotychczas w programach kształcenia w UW, w działalności naukowej i gospodarczej, oraz rozbudzenie kreatywności. Adresowany jest do studentów studiów II stopnia Fizyki Medycznej i Neuroinformatyki na Wydziale Fizyki. Zajęcia mają formę zajęć warsztatowych/pracowni. Przewiduje się 7 stanowisk dla 14 studentów pracujących w parach. Pojedyncze zajęcia na pracowni trwają 2h. Program podzielony jest na 3 bloki tematyczne: |
− |
| |
| * Posturografia - 8h (4 zajęcia) | | * Posturografia - 8h (4 zajęcia) |
| * Kamery 3D - 8h (4 zajęcia) | | * Kamery 3D - 8h (4 zajęcia) |
| * Raspberry Pi - 14h (7 zajęć) | | * Raspberry Pi - 14h (7 zajęć) |
− | | + | ===Warunki zaliczenia przedmiotu=== |
| Warunkiem uczestnictwa w zajęciach jest uprzednie zaliczenie przedmiotów „Pracownia fizyczna i elektroniczna”, „Analiza sygnałów” oraz podstawowa znajomość języka Python. | | Warunkiem uczestnictwa w zajęciach jest uprzednie zaliczenie przedmiotów „Pracownia fizyczna i elektroniczna”, „Analiza sygnałów” oraz podstawowa znajomość języka Python. |
− |
| |
| Zaliczenie przedmiotu odbywa się na podstawie: | | Zaliczenie przedmiotu odbywa się na podstawie: |
| *obecności (maksymalnie 2 nieusprawiedliwione nieobecności) | | *obecności (maksymalnie 2 nieusprawiedliwione nieobecności) |
− | *przedstawienia prezentacji z wynikami na koniec koniec tematu: Posturografia, Kamery 3D | + | *przedstawienia prezentacji z wynikami na koniec tematu: Posturografia, Kamery 3D |
| *projektu zaliczeniowego na koniec tematu: Raspberry Pi | | *projektu zaliczeniowego na koniec tematu: Raspberry Pi |
− |
| |
− | ==Posturograf ==
| |
− |
| |
− | Opis bloku tematycznego: Zajęcia warsztatowe składające się z wprowadzającego w tematykę zajęć wykładu i indywidualnych ćwiczeń wykonywanych przez studentów. Studenci w czasie zajęć przeprowadzają standardowe pomiary posturograficzne, a następnie analizują zebrane dane.
| |
− |
| |
− | ===Plan zajęć===
| |
− |
| |
− | Zajęcia 1:
| |
− | *Wstęp teoretyczny:
| |
− | **Wii Balance Board (budowa, główne biblioteki obsługujące sensor, zastosowania)
| |
− | **Projesjonalne systemy do rejestracji siły nacisku
| |
− | **Kinect (budowa, biblioteki, zastosowania)
| |
− | **Profesjonalne systemy do rejestracji ruchu
| |
− | **Równowaga a stabilność posturalna
| |
− | **Podstawowe zadania posturograficzne
| |
− | **Opis wybranych wskaźników do zadań posturograficznych
| |
− | *Wprowadzenie do pomiarów przeprowadzanych na zajęciach (zapoznanie się z wybranymi scenariuszami oraz modułami do analizy)
| |
− | *Zapoznanie się z działaniem sensora Kinect i Wii Balance Board
| |
− | *Przeprowadzenie pomiarów
| |
− |
| |
− | [[Media: WiiBoard.pdf]] Informacje wstępne oraz opis zadań
| |
− | <!--
| |
− | [[Media:wprowadzenie.pdf]] Wykład z zajęć wprowadzających
| |
− | [[Media:Pomiary_wii.pdf]] Wstęp do pomiarów posturograficznych
| |
− | -->
| |
− |
| |
− | Zajęcia 2,3,4:
| |
− | *Analiza zebranych danych
| |
− | *Prezentacja wyników
| |
− |
| |
− | ===Pomiary===
| |
− |
| |
− | Pomiary przeprowadzane są w środowisku OpenBCI. Architektura systemu oraz opis wybranych scenariuszy jest dostępny na stronie http://bci.fuw.edu.pl/wiki/Tutorials. Szczegółowe informacje dotyczące konfiguracji OpenBCI na Ubuntu 14.04 LTS można znaleźć pod adresem http://deb.braintech.pl/. Po zainstalowaniu pakietów źródła znajdą sie w katalogu <tt>/usr/share/openbci</tt>.
| |
− |
| |
− | Z OpenBCI można również korzystać na systemie Windows -> instrukcja [[Media: obci_Windows.pdf]]
| |
− |
| |
− | Rejestracja danych odbywa się w środowisku OpenBCI. System ten uruchamiamy wykonując w terminalu polecenie:
| |
− | <source lang="c">$ obci_gui --presets new_tech </source>
| |
− |
| |
− | Podczas zajęć przeprowadzone zostaną następujące pomiary:
| |
− | *stanie swobodne z oczami otwartymi/zamkniętymi,
| |
− | *wychylenia szybkie i "z przytrzymaniem" bez informacji zwrotnej dla badanego (w przód, w tył, w prawo, w lewo),
| |
− | *wychylenia szybkie i "z przytrzymaniem" z informacją zwrotną dla badanego (w przód, w tył, w prawo, w lewo).
| |
− |
| |
− | W wyniku każdego pomiaru otrzymujemy komplet trzech plików (lokalizacja: Katalog Domowy):
| |
− | * Plik z sygnałem (.raw) zapisanym w formacie binarnym. W pliku znajdują się próbki z pięciu kanałów – wartości z czterech czujników WBB oraz momenty w czasie (w sekundach) mierzone względem pojawienia się pierwszej próbki.
| |
− | * Plik z metadanymi (.xml), w którym znajdują się szczegółowe informacje dotyczące rejestracji (nazwy kanałów, częstość próbkowania, całkowita liczba próbek itp.).
| |
− | * Plik ze znacznikami (.tag), w którym zapisywane są momenty kolejnych zdarzeń (np. początek i koniec wykonywania zadania) zsynchronizowane z sygnałem. Każdy znacznik posiada charakterystyczną nazwę, moment wystąpienia w sygnale, długość oraz ewentualnie opis.
| |
− | W przypadku zadań z informacją zwrotną dla badanego generowane są dwa pliki ze znacznikami. Interesujące nas informacje znajdują się w pliku z rozszerzeniem .game.tag. Nie są one zsynchronizowane z sygnałem, ponieważ gra uruchamiana jest w osobnym wątku, który nie ma możliwości komunikacji z multiplekserem. Z tego względu każdy znacznik zapisany w tym pliku posiada czas systemowy, który należy wyrównać względem pierwszej próbki w sygnale. Procedura ta została zaimplementowana w przykładowym skrypcie do analizy.
| |
− |
| |
− | ===Analiza danych===
| |
− |
| |
− | ====Przygotowanie danych do analizy====
| |
− | Pierwszym etapem analizy jest wstępne przetworzenie danych. W tym celu należy wyestymować rzeczywistą częstość próbkowania Fs (w idealnym przypadku wynosi ona 65 Hz) oraz przepróbkować sygnał do częstości fs ok. 30 Hz (wychylenia swobodne widoczne są głównie w niższych częstościach).
| |
− |
| |
− | <source lang="Python">
| |
− | #!/usr/bin/env python
| |
− | # -*- coding: utf-8 -*-
| |
− | from obci.analysis.balance.wii_read_manager import WBBReadManager
| |
− | from obci.exps.ventures.analysis import analysis_baseline
| |
− | from obci.analysis.balance.wii_preprocessing import *
| |
− | from obci.analysis.balance.wii_analysis import *
| |
− |
| |
− | def read_file(file_path, file_name, tag_format = 'obci'):
| |
− | file_name = file_path+file_name
| |
− | wbb_mgr = WBBReadManager(file_name+'.obci.xml', file_name+'.obci.raw', file_name + '.' + tag_format + '.tag')
| |
− | return wbb_mgr
| |
− |
| |
− | FILE_PATH = '/home/newtech/'
| |
− | FILE_NAME = 'wii_baseline_2015-03-04_15-02-01' #przykładowa nazwa pliku
| |
− |
| |
− | #wczytanie danych
| |
− | wbr_baseline = read_file(FILE_PATH, FILE_NAME)
| |
− | #estymacja częstości próbkowania Fs
| |
− | Fs = analysis_baseline.estimate_fs(wbr_baseline.mgr.get_channel_samples('TSS'))
| |
− | #wpisanie częstości Fs do obiektu
| |
− | wbr_baseline.mgr.set_param('sampling_frequency', Fs)
| |
− | #przepróbkowanie z czynnikiem 2
| |
− | wbr_baseline = wii_downsample_signal(wbr_baseline, factor=2, pre_filter=True, use_filtfilt=True)
| |
− | #odczytanie nowej częstości próbkowania fs
| |
− | fs = wbr_baseline.mgr.get_param('sampling_frequency')
| |
− |
| |
− | </source>
| |
− |
| |
− | Po takich operacjach dane przechowywane w obiekcie 'wbr_baseline' klasy WBBReadManager są gotowe do użycia. Klasa ta posiada metodę 'get_raw_signal', która zwraca 4-kanałową macierz z danymi z 4 czujników (są to kanały odpowiadające kolejno czujnikom: górny lewy-TL, górny prawy-TR, dolny prawy-BR, dolny lewy-BL). Można wyznaczyć wartości wychyleń w kierunkach x i y na podstawie informacji z czterech czujników (<xr id="fig:wbb">rys. %i</xr>).:
| |
− |
| |
− | <div style="text-align: center;">
| |
− | <math>x=\frac{(TR+BR)-(TL+BL)}{TR+TL+BL+BR}</math>
| |
− |
| |
− | <math>y=\frac{(TR+TL)-(BR+BL)}{TR+TL+BL+BR}</math>
| |
− | </div>
| |
− |
| |
− | Należy pamiętać, że dane z czujników pochodzą z układu odniesienia deski Wii Board - zatem uzyskane wartości x i y mieszczą się w zakresie od -1 do 1. Aby uzyskać dane w cm trzeba przemnożyć współrzędne x i y przez odpowiednie czynniki:
| |
− | [[Plik:wbb_axes.png|600px|thumb|center|<figure id="fig:wbb"></figure>Wii Balance Board z oznaczonymi płaszczyznami ML i AP. TR, TL, BR, BL ozanczają pozycje czterech czujników.]]
| |
− |
| |
− | Jednak w przypadku niektórych zadań należy jeszcze, przed wyznaczaniem x i y, odpowiednio wyciąć interesujące nas dane względem znaczników. Czynność tę wykonuje funkcja 'wii_cut_fragments', która zwraca listę obiektów 'smart_tags'. Liczba tych obiektów odpowiada liczbie zdarzeń z danym znacznikiem (dla stania swobodnego lista będzie miała tylko jeden element, natomiast dla wielokrotnych wychyleń będzie ich kilka). Każdy element na tej liście, posiada metodę 'get_samples' zwracającą dane w macierzy 7 kanałowej. W pierwszych 4 kanałach znajdują się dane z czujników TL,TR,BR,BL.
| |
− |
| |
− | <source lang="Python">
| |
− | smart_tags = wii_cut_fragments(wbr_baseline, start_tag_name='ss_start', end_tags_names=['ss_stop'])
| |
− | TL = smart_tags[0].get_samples()[0,:]
| |
− | TR = smart_tags[0].get_samples()[1,:]
| |
− | BR = smart_tags[0].get_samples()[2,:]
| |
− | BL = smart_tags[0].get_samples()[3,:]
| |
− | </source>
| |
− |
| |
− | Znaczniki 'start_tag_name' oraz 'end_tags_names' dla poszczególnych pomiarów:
| |
− |
| |
− | * stanie swobodne oczy otwarte: 'ss_start', 'ss_stop'
| |
− | * stanie swobodne oczy zamknięte: 'ss_oczy_start', 'ss_oczy_stop'
| |
− |
| |
− | * wychylenia szybkie bez informacji zwrotnej: 'szybkie_start', 'szybkie_stop'
| |
− | * wychylenia "z przytrzymaniem" bez informacji zwrotnej: 'start', 'stop'
| |
− |
| |
− | * stanie swobodne jako kalibracja do zadań z informacją zwrotną: 'ss_start', 'ss_stop'
| |
− | * wychylenia szybkie z informacją zwrotną: nie ma znaczników - ciągły zapis danych
| |
− | * wychylenia "z przytrzymaniem" z informacją zwrotną: 'start_1', 'finish'
| |
− |
| |
− | Podczas wczytywania danych z wychyleń "z przytrzymaniem" z informacją zwrotną należy ustawić parametr 'tag_format' w wywołaniu funkcji read_file na 'game' (zamiast domyślnie ustawionego 'obci'). Dalsze kroki przygotowania danych do analizy wykonujemy tak samo. Obiekty w liście zwróconej przez funkcję 'wii_cut_fragments' odpowiadają kolejnym realizacjom zadania. Mają one jednak nieco inną strukturę. Oprócz metody 'get_samples()', za pomocą której tak jak poprzednio wczytamy dane z 4 czujników, posiadają również metody:
| |
− | *'get_end_tag()' - zwraca strukturę, która w polu ['desc']['type'] przechowuje informację o tym czy zadanie zostało wykonane poprawnie (0-niepoprawnie, 1-poprawnie)
| |
− | *'get_start_tag()' - zwraca strukturę, która w polu ['desc']['type'] przechowuje informację o kierunku wychylenia (pole 'direction', wartości: 'up','down','left','right') oraz o poziomie trudności zadania (pole 'level'). Aby wydobyć informację o kierunku wychylenia (analogicznie dla poziomiu trudności) można skorzystać z funkcji: eval(smart_tags[index].get_start_tag()['desc']['type'])['direction']
| |
− | <!--Dokumentacja funkcji klasy WBBReadManager (przy pomcy której wczytujemy dane. Korzysta ona z obiektu klasy ReadManager, która została zaprojektowana do wczytywania i segmentacji danych rejestrowanych przy pomocy systemu OpenBCI. Moduł <tt>obci.analysis.balance.wii_preprocessing</tt> umożliwia dodatkowo przepróbkowanie oraz filtrację danych):
| |
− |
| |
− | *Przepróbkowanie danych
| |
− |
| |
− | <source lang="Python">
| |
− | # Parametry wejściowe:
| |
− | # wbb_mgr - obiekt klasy WBBReadManager
| |
− | # factor - nowa_fs = fs / factor (int)
| |
− | # pre_filter - True/False w zależności czy ma być użyty filtr dolnoprzepustowy z częstością
| |
− | # odcięcia: częstość próbkowania / 2
| |
− | # use_filtfilt - True/False w zależności czy ma być użyta procedura
| |
− | # filtrowania filtfilt/lfilter (bool)
| |
− |
| |
− | # Funkcja zwraca obiekt klasy WBBReadManager z przepróbkowanym sygnałem.
| |
− |
| |
− | factor = 2
| |
− | pre_filter = False
| |
− | use_filtfilt = True
| |
− |
| |
− | wbb_mgr = wii_downsample_signal(wbb_mgr,
| |
− | factor,
| |
− | pre_factor,
| |
− | use_filtfilt)
| |
− | </source>
| |
− |
| |
− | *Segmentacja danych
| |
− |
| |
− | <source lang="Python">
| |
− | # Parametry wejściowe:
| |
− | # wbb_mgr - obiekt klasy WBBReadManager,
| |
− | # start_tag_name - nazwa znacznika określającego początek fragmentu,
| |
− | # end_tags_names - lista z nazwami znaczników określających koniec fragmentu.
| |
− |
| |
− | # Funkcja zwraca obiekt klasy SmartTagsManager.
| |
− |
| |
− | smart_tags = wii_cut_fragments(wbb_mgr,
| |
− | start_tag_name='start',
| |
− | end_tags_names=['stop'])
| |
− | </source>
| |
− |
| |
− | *Filtracja danych
| |
− |
| |
− | <source lang="Python">
| |
− | # Parametry wejściowe:
| |
− | # wbb_mgr - obiekt klasy WBBReadManager
| |
− | # cutoff_upper - częstość odcięcia (float)
| |
− | # order - rząd filtru (int)
| |
− | # use_filtfilt - True/False w zależności, czy ma być użyta procedura
| |
− | # filtrowania filtfilt/lfilter (bool)
| |
− |
| |
− | # Funkcja zwraca obiekt klasy WBBReadManager z przefiltrowanym sygnałem.
| |
− |
| |
− | cutoff_upper = 20
| |
− | order = 2
| |
− | use_filtfilt = False
| |
− | wbb_mgr = wii_filter_signal(wbb_mgr,
| |
− | cutoff_upper,
| |
− | order,
| |
− | use_filtfilt)
| |
− | </source> -->
| |
− |
| |
− | ====Analiza danych: stanie swobodne====
| |
− |
| |
− | W przypadku stania swobodnego z oczami zamkniętymi oraz otwartymi, studenci mają za zadanie wyznaczyć następujące wskaźniki posturograficzne:
| |
− | <!-- (korzystając z funkcji zaimplentowanych w bibliotece <tt>obci.analysis.balance.wii_analysis</tt>): -->
| |
− | *położenie środka równowagi COP (''center of posture'')
| |
− | *maksymalne przemieszczenie względem położenia środka równowagi (w AP,ML oraz przestrzeni AP/ML),
| |
− | *długość drogi względem położenia środka równowagi (w AP,ML oraz przestrzeni AP/ML),
| |
− | *średnia prędkość przemieszczenia (w AP,ML oraz przestrzeni AP/ML),
| |
− | *wskaźnik Romberga - stosunek różnicy długości drogi przy oczach zamkniętych i otwartych, do sumy długości drogi przy oczach zamkniętych i otwartych
| |
− | <!--*95% powierzchnia ufności elipsy - powierzchnia elipsy, w której powinno zawierać się około 95% punktów drogi COP,
| |
− | *RMS (''root mean square'') (w AP i ML).--->
| |
− | Dokładny opis matematyczny wyżej wymienionych wskaźników znajduje się w pracy (Prieto, 1996).
| |
− |
| |
− | Należy również przedstawić na wykresie przebieg ruchu COP oddzielnie w płaszczyźnie AP, ML oraz w przestrzeni AP/ML.
| |
− |
| |
− | Dodatkowo studenci mają za zadanie przeprowadzić analizę rozkładu przestrzennego punktów statokinezjogramu. Statokinezjogramem lub posturogramem nazywamy wędrówkę COP w dwuwymiarowej płaszczyźnie podparcia. Kierunki na tej płaszczyźnie określa się jako AP (y) lub ML (x), przy czym ML oznacza wychylenia w płaszczyźnie czołowej (''medio-lateral''), a AP w płaszczyźnie strzałkowej (''anterio-posterior''). W celu przeprowadzenie takiej analizy, cały zakres zostaje podzielony na jednakowe komórki. Następnie obliczony zostaje histogram przestrzenny czasu przebywania w każdej z nich. Taki histogram pozwala ocenić, czy kontrola położenia referencyjnego COG (''center of gravity''), a tym samym pionowa orientacja ciała, jest prawidłowa. Wyznacznikiem prawidłowej kontroli jest histogram o skupionym rozkładzie i z wyraźnym maksimum. Upośledzenie kontroli objawia się tym, że histogram przestrzenny staje się rozmyty lub wyraźnie niesymetryczny (Błaszczyk, 2004).
| |
− |
| |
− | ====Analiza danych: wychylenia dynamiczne====
| |
− |
| |
− | Oprócz wskaźników statycznych stabilności do oceny kontroli posturalnej wykorzystuje się również miary dynamiczne. Z punktu widzenia miar bezpośrednich, istotna jest ocena kontroli środka ciężkości ciała w czasie jego świadomego przemieszczania w wyznaczonym kierunku. W ramach pomiarów, studenci mieli za zadanie wykonać dwa rodzaje wychyleń (szybkie i "z przytrzymaniem") w dwóch warunkach: bez informacji zwrotnej dla badanego oraz z informacją zwrotną dla badanego. Dla każdego z przypadków należy wyznaczyć następujące parametry:
| |
− |
| |
− | *wartość maksymalnego wychylenia (w określonym kierunku),
| |
− | *wykresy składowych wychwiań w płaszczyźnie AP, ML w zależności od czasu oraz wypadkowa trajektoria przemieszczeń COP (w dwuwymiarowej przestrzeni AP, ML).
| |
− |
| |
− | i zbadać czy informacja zwrotna wpływa na rezultaty badanego.
| |
− |
| |
− | Literatura:
| |
− | *Błaszczyk J., Biomechanika kliniczna, PZWL, 2004
| |
− | *Prieto T.E. et al., Measures of postural steadiness: differences between healthy young and elderly adults, IEEE Trans Biomed Eng, 1996, 43(9):956-66
| |
− | <!--
| |
− | Przykładowe skrypty do analizy:
| |
− |
| |
− | *zadanie "stanie swobodne"
| |
− | <source lang="Python">
| |
− | #!/usr/bin/env python
| |
− | # -*- coding: utf-8 -*-
| |
− |
| |
− | from obci.analysis.balance.wii_read_manager import WBBReadManager
| |
− | from obci.analysis.balance.wii_preprocessing import *
| |
− | from obci.analysis.balance.wii_analysis import *
| |
− |
| |
− | import matplotlib.pyplot as py
| |
− |
| |
− | from obci.exps.ventures.analysis import analysis_baseline
| |
− | from obci.exps.ventures.analysis import analysis_helper
| |
− |
| |
− | from obci.acquisition import acquisition_helper
| |
− |
| |
− | FILE_PATH = '~/' #full path
| |
− | FILE_NAME = 'wii_baseline_2015-03-03_20-51-48' #file name without extension
| |
− |
| |
− | def read_file(file_path, file_name, tag_format = 'obci'):
| |
− | file_name = acquisition_helper.get_file_path(file_path, file_name)
| |
− | wbb_mgr = WBBReadManager(file_name+'.obci.xml', file_name+'.obci.raw', file_name + '.' + tag_format + '.tag')
| |
− | return wbb_mgr
| |
− |
| |
− | if __name__ == '__main__':
| |
− | #load data
| |
− | wbb_mgr = read_file(FILE_PATH, FILE_NAME)
| |
− |
| |
− | #add two additional (x, y) channels (computed from sensor values)
| |
− | wbb_mgr.get_x()
| |
− | wbb_mgr.get_y()
| |
− |
| |
− | #estimate true sampling frequency value
| |
− | fs = analysis_baseline.estimate_fs(wbb_mgr.mgr.get_channel_samples('TSS'))
| |
− | wbb_mgr.mgr.set_param('sampling_frequency', analysis_baseline.estimate_fs(wbb_mgr.mgr.get_channel_samples('TSS')))
| |
− |
| |
− | #preprocessing
| |
− | wbb_mgr = wii_downsample_signal(wbb_mgr, factor=2, pre_filter=True, use_filtfilt=True)
| |
− |
| |
− | #extract fragments from standing task with eyes open
| |
− | smart_tags = wii_cut_fragments(wbb_mgr, start_tag_name='ss_start', end_tags_names=['ss_stop'])
| |
− | sm_x = smart_tags[0].get_channel_samples('x')
| |
− | sm_y = smart_tags[0].get_channel_samples('y')
| |
− | py.figure()
| |
− | print(wii_COP_path(wbb_mgr, sm_x, sm_y, plot=True))
| |
− | py.show()
| |
− | </source>
| |
− |
| |
− | *zadanie "wychylenia bez informacji zwrotnej"
| |
− |
| |
− | <source lang="Python">
| |
− | #!/usr/bin/env python
| |
− | # -*- coding: utf-8 -*-
| |
− |
| |
− | from obci.analysis.balance.wii_read_manager import WBBReadManager
| |
− | from obci.analysis.balance.wii_preprocessing import *
| |
− |
| |
− | from obci.exps.ventures.analysis import analysis_baseline
| |
− | from obci.exps.ventures.analysis import analysis_helper
| |
− |
| |
− | from obci.acquisition import acquisition_helper
| |
− |
| |
− | FILE_PATH_LEFT = '' #full path
| |
− | FILE_NAME_LEFT = '' #file name without extension
| |
− |
| |
− | FILE_PATH_RIGHT = '' #full path
| |
− | FILE_NAME_RIGHT = '' #file name without extension
| |
− |
| |
− | FILE_PATH_DOWN = '' #full path
| |
− | FILE_NAME_DOWN = '' #file name without extension
| |
− |
| |
− | FILE_PATH_UP = '' #full path
| |
− | FILE_NAME_UP = '' #file name without extension
| |
− |
| |
− | def read_file(file_path, file_name, tag_format = 'obci'):
| |
− | file_name = acquisition_helper.get_file_path(file_path, file_name)
| |
− | wbb_mgr = WBBReadManager(file_name+'.obci.xml', file_name+'.obci.raw', file_name + '.' + tag_format + '.tag')
| |
− | return wbb_mgr
| |
− |
| |
− | if __name__ == '__main__':
| |
− | #load data from right sway task
| |
− | wbb_mgr_right = read_file(FILE_PATH_RIGHT, FILE_NAME_RIGHT)
| |
− |
| |
− | #here should be preprocessing...
| |
− |
| |
− | #extract fragments from sway task (right)
| |
− | smart_tags_quick = wii_cut_fragments(wbb_mgr_right, start_tag_name='szybkie_start', end_tags_names=['szybkie_stop'])
| |
− | x_fragments_quick = [i.get_channel_samples('x') for i in smart_tags_quick]
| |
− | y_fragments_quick = [i.get_channel_samples('y') for i in smart_tags_quick]
| |
− |
| |
− | #extract fragments from sway&stay task (right)
| |
− | smart_tags_long = wii_cut_fragments(wbb_mgr_right, start_tag_name='start', end_tags_names=['stop'])
| |
− | x_fragments_long = [i.get_channel_samples('x') for i in smart_tags_long]
| |
− | y_fragments_long = [i.get_channel_samples('y') for i in smart_tags_long]
| |
− | </source>
| |
− |
| |
− | *zadanie "wychylenia z informacją zwrotną"
| |
− |
| |
− | <source lang="Python">
| |
− | #!/usr/bin/env python
| |
− | # -*- coding: utf-8 -*-
| |
− |
| |
− | from obci.analysis.balance.wii_read_manager import WBBReadManager
| |
− | from obci.analysis.balance.wii_preprocessing import *
| |
− |
| |
− | from obci.exps.ventures.analysis import analysis_baseline
| |
− | from obci.exps.ventures.analysis import analysis_helper
| |
− |
| |
− | from obci.acquisition import acquisition_helper
| |
− |
| |
− | BASELINE_FILE_PATH = '' #full path
| |
− | BASELINE_FILE_NAME = '' #file name without extension
| |
− |
| |
− | FILE_PATH = '' #full path
| |
− | FILE_NAME = '' #file name without extension
| |
− |
| |
− | def get_baseline_points(file_path, file_name):
| |
− | """ baseline area is a rectangle with parameters:
| |
− | center point: xc, yc,
| |
− | width: 2*xa,
| |
− | height: 2*yb.
| |
− | """
| |
− | xa, ya, xb, yb, xc, yc = analysis_baseline.calculate(file_path, file_name, show=False)
| |
− | return xa, ya, xb, yb, xc, yc
| |
− |
| |
− | def read_file(file_path, file_name, tag_format = 'game'):
| |
− | file_name = acquisition_helper.get_file_path(file_path, file_name)
| |
− | wbb_mgr = WBBReadManager(file_name+'.obci.xml', file_name+'.obci.raw', file_name + '.' + tag_format + '.tag')
| |
− | return wbb_mgr
| |
− |
| |
− | if __name__ == '__main__':
| |
− | xa, ya, xb, yb, xc, yc = get_baseline_points(BASELINE_FILE_PATH, BASELINE_FILE_NAME)
| |
− | wbb_mgr = read_file(FILE_PATH, FILE_NAME)
| |
− | wbb_mgr.mgr = analysis_helper.set_first_timestamp(wbb_mgr.mgr) #adjusting tags to signal
| |
− | </source>
| |
− |
| |
− | Moduł <tt>obci.analysis.balance.wii_analysis</tt> umożliwia wyznaczenie podstawowych wskaźników posturograficznych z zadania eksperymentalnego "stanie swobodne".
| |
− |
| |
− | *Maksymalna wartość wychwiań w AP i ML
| |
− |
| |
− | <source lang="Python">
| |
− | # Parametry wejściowe:
| |
− | # x - macierz reprezentująca kanał x,
| |
− | # y - macierz reprezentująca kanał y.
| |
− |
| |
− | # Funkcja zwraca:
| |
− | # max_sway - maksymalne wychwianie (float),
| |
− | # max_AP - maksymalne wychwianie w kierunku AP (float),
| |
− | # max_ML - maksymalne wychwianie w kierunku ML (float).
| |
− |
| |
− | max_sway, max_AP, max_ML = wii_max_sway_AP_MP(x, y)
| |
− | </source>
| |
− |
| |
− | *Średnia wartość wychwiań COP od punktu (0,0)
| |
− |
| |
− | <source lang="Python">
| |
− | # Parametry wejściowe:
| |
− | # x - macierz reprezentująca kanał x,
| |
− | # y - macierz reprezentująca kanał y.
| |
− |
| |
− | # Funkcja zwraca:
| |
− | # cop - średnią wartość wychwiań do punktu (0, 0) (float),
| |
− | # mean_y_COP - średnią wartość wychwiań do punktu (0, 0) w AP (float),
| |
− | # mean_x_COP - średnią wartość wychwiań do punktu (0, 0) w ML (float).
| |
− |
| |
− | mean_COP, mean_y_COP, mean_x_COP = wii_mean_COP_sway_AP_ML(x, y)
| |
− | </source>
| |
− |
| |
− | *Długość drogi
| |
− |
| |
− | <source lang="Python">
| |
− | # Parametry wejściowe:
| |
− | # wbb_mgr - obiekt klasy WBBReadManager,
| |
− | # x - macierz reprezentująca kanał x,
| |
− | # y - macierz reprezentująca kanał y,
| |
− | # plot - True/False (opcjonalnie).
| |
− |
| |
− | # Funkcja zwraca:
| |
− | # path_length - długość drogi COP (float),
| |
− | # path_length_x - długość drogi COP w ML (float),
| |
− | # path_length_y - długość drogi COP w AP (float).
| |
− |
| |
− | path_length, path_length_x, path_length_y = wii_COP_path(wbb_mgr, x, y, plot=False)
| |
− | </source>
| |
− |
| |
− | *RMS
| |
− |
| |
− | <source lang="Python">
| |
− | # Parametry wejściowe:
| |
− | # x - macierz reprezentująca kanał x,
| |
− | # y - macierz reprezentująca kanał y.
| |
− |
| |
− | # Funkcja zwraca:
| |
− | # RMS - (float),
| |
− | # RMS_AP - (float),
| |
− | # RMS_ML - (float).
| |
− |
| |
− | RMS, RMS_AP, RMS_ML = wii_RMS_AP_ML(x, y)
| |
− | </source>
| |
− |
| |
− | *95% powierzchnia ufności elipsy
| |
− |
| |
− | <source lang="Python">
| |
− | # Parametry wejściowe:
| |
− | # x - macierz reprezentująca kanał x,
| |
− | # y - macierz reprezentująca kanał y.
| |
− |
| |
− | # Funkcja zwraca:
| |
− | # e - 95% powierzchnia ufności elipsy (float).
| |
− |
| |
− | e = wii_confidence_ellipse_area(x, y)
| |
− | </source>
| |
− |
| |
− | *Średnia prędkość przemieszczenia
| |
− |
| |
− | <source lang="Python">
| |
− | # Parametry wejściowe:
| |
− | # wbb_mgr - obiekt klasy WBBReadManager
| |
− | # x - macierz reprezentująca kanał x,
| |
− | # y - macierz reprezentująca kanał y,
| |
− | # plot - True/False (opcjonalnie).
| |
− |
| |
− | # Funkcja zwraca:
| |
− | # mean_velocity - średnia prędkość przemieszczenia,
| |
− | # velocity_AP - średnia prędkość przemieszczenia w AP,
| |
− | # velocity_ML - średnia prędkość przemieszczenia w ML.
| |
− |
| |
− | mean_velocity, velocity_AP, velocity_ML = wii_mean_velocity(wbb_mgr, x, y)
| |
− | </source>
| |
− |
| |
− | *Procentowa wartość przebywania w czterech ćwiartkach układu współrzędnych
| |
− |
| |
− | <source lang="Python">
| |
− | # Parametry wejściowe:
| |
− | # wbb_mgr - obiekt klasy WBBReadManager,
| |
− | # x - macierz reprezentująca kanał x,
| |
− | # y - macierz reprezentująca kanał y,
| |
− | # plot - True/False (opcjonalnie).
| |
− |
| |
− | # Funkcja zwraca:
| |
− | # top_right - procentowa wartość przebywania w prawej górnej ćwiartce układu współrzędnych (float),
| |
− | # top_left - procentowa wartość przebywania w lewej górnej ćwiartce układu współrzędnych (float),
| |
− | # bottom_right - procentowa wartość przebywania w prawej dolnej ćwiartce układu współrzędnych (float),
| |
− | # bottom_left - procentowa wartość przebywania w lewej dolnej ćwiartce układu współrzędnych (float).
| |
− |
| |
− | top_right, top_left, bottom_right, bottom_left = wii_get_percentages_values(wbb_mgr, x, y, plot=False)
| |
− | </source> -->
| |
− |
| |
− | ==Kamery 3D ==
| |
− | ===Plan zajęć===
| |
− | Zajęcia 1:
| |
− | *Wstęp teoretyczny:
| |
− | **Budowa i zasada działania sensora Kinect.
| |
− | **Zastosowania w biomechanice oraz rehabilitacji.
| |
− | **Opis podstawowych bibliotek wykorzystywanych do komunikacji z urządzeniem.
| |
− | *Pomiary:
| |
− | **W ramach pomiarów studenci wykonają standardowy test wykorzystywany w medycynie sportowej do oceny prawdopodobieństwa urazów więzadła krzyżowego przedniego (ACL).
| |
− |
| |
− | [[Media:3D_Kinect.pdf]] Informacje wstępne oraz opis zadań
| |
− |
| |
− | Zajęcia 2,3,4:
| |
− | *Analiza zebranych danych
| |
− | *Zaprezentowanie uzyskanych wyników
| |
− |
| |
− | ===Sensor Kinect===
| |
− |
| |
− | Śledzenie ruchów postaci ludzkiej w ogólności znajduje zastosowanie m.in. w analizie chodu, diagnostyce chorób związanych z układem ruchu człowieka, analizie ruchu sportowców, czy nawet w procesie animacji postaci na potrzeby produkcji filmów i gier. W tym celu wykorzystuje się głównie profesjonalne markerowe systemy śledzenia ruchu (marker-based motion capture systems) określane w skrócie jako systemy mocap. Systemy te wymagają zastosowania specjalistycznego sprzętu, a na ciele śledzonej postaci muszą zostać umieszczone odpowiednie markery, przez co rejestracja musi odbywać się w warunkach laboratoryjnych. Systemy te nie nadają się do śledzenia ruchu w czasie rzeczywistym, a przesłonięcie lub przemieszczenie markerów w trakcie ruchu może być przyczyną błędów. Z tych względów coraz większe zainteresowanie zyskują bezmarkerowe systemy śledzenia ruchu, które wykorzystują zaawansowane algorytmy analizy obrazu.
| |
− |
| |
− | Sensor Kinect firmy Microsoft do śledzenia ruchu postaci wykorzystuje informacje z kamery głębokości. Znajduje on zastosowanie w różnego rodzaju systemach umożliwiających interakcję człowiek-komputer, ale zaczyna również budzić coraz większe zainteresowanie w dziedzinach związanych z biomechaniką i rehabilitacją. W tym celu konieczne jest jednak określenie dokładności pozycji estymowanych przy pomocy bibliotek obsługujących sensor. Problem ten został poruszony w pracy (Webster, 2014).
| |
− |
| |
− |
| |
− | [[Plik:kinect.png|600px|thumb|center|<figure id="fig:kinect"></figure>Sensor Kinect Xbox 360.]]
| |
− |
| |
− |
| |
− | Budowa sensora Kinect Xbox 360 (<xr id="fig:kinect">rys. %i</xr>):
| |
− | *kamera wizyjna RGB (typu CMOS, o rozdzielczości 640x480) - przesyła serię obrazów z prędkością 30 klatek na sekundę,
| |
− | *kamera głębokości (typu CMOS, o rozdzielczości ~300x200) - zwraca informację o głębokości poprzez analizę zniekształconej przez obiekt wiązki promieni podczerwonych,
| |
− | *emiter podczerwieni - emituje wiązkę promieni podczerwonych,
| |
− | *4 mikrofony kierunkowe - wykorzystywane przez funkcje rozpoznawania mowy,
| |
− | *napęd umożliwiający ruch głowicą z akcelerometrem.
| |
− |
| |
− | ===Pomiary===
| |
− |
| |
− | Rejestracja danych odbywa się w środowisku OpenBCI. System ten uruchamiamy wykonując w terminalu polecenie:
| |
− |
| |
− | <source lang="c">$ obci_gui </source>
| |
− |
| |
− | Obsługa sensora wraz z algorytmami estymacji poszczególnych pozycji anatomicznych śledzonej postaci, możliwa jest dzięki bibliotekom OpenNI i NiTE.
| |
− | Scenariusz do rejestracji danych przy pomocy sensora Kinect pokazany został poniżej (<xr id="fig:obci_kinect">rys. %i</xr>). Umożliwia on rejestrację w trybie ''online'', i wówczas zarówno obraz RGB, jak mapa głębokości mogą zostać zapisane w domyślnym formacie .oni. Dodatkowo tworzony jest plik binarny .algs z metadanymi rejestracji, gdzie zapisywane są między innymi współrzędne wyestymowanych pozycji anatomicznych. Tryb ''offline'' umożliwa odtwarzanie plików .oni oraz .algs. W przypadku rejestracji w trybie ''online'' w scenariuszu zmieniamy następujące parametry:
| |
− |
| |
− | capture_raw = 1 – zapis obrazu do pliku .oni (0 lub 1)
| |
− | out_raw_file_path = test.oni – nazwa pliku .oni
| |
− | capture_hands = 1 – zapis pozycji rąk (0 lub 1)
| |
− | capture_skeleton = 1 – zapis pozycji anatomicznych (0 lub 1)
| |
− | out_algs_file_path = test.algs – nazwa pliku .algs z metadanymi rejestracji
| |
− |
| |
− | Wybierając tryb ''offline'' należy podać odpowiednią ścieżkę do plików .oni oraz .algs:
| |
− |
| |
− | in_raw_file_path = test.oni
| |
− | in_algs_file_path = test.algs
| |
− |
| |
− | Wszystkie pliki zapisywane są w lokalizacji: /home/.obci/sandbox
| |
− |
| |
− | [[Plik:obci_gui.png|600px|thumb|center|<figure id="fig:obci_kinect"></figure>Scenariusz w OpenBCI do rejestracji danych przy pomocy Kinecta.]]
| |
− |
| |
− | Zeskok z następującym wyskokiem pionowym (''drop vertical jump'', DVJ) należy do badań przesiewowych, pozwalających oszacować ryzyko występienia urazu (w szczególności więzadła krzyżowego przedniego u kobiet) lub określić efekty rehabilitacji. Przed rozpoczęciem skoku osoba badana stoi na platformie o wysokości ok. 30 cm. Ma ona za zadanie wykonać zeskok z platformy na ziemię, a następnie maksymalny skok pionowy w górę. W dalszej analizie interesujące będą momenty: kontaktu pięt z podłożem (''initial contact'', IC) zaraz po wykonaniu zeskoku oraz moment maksymalnego zgięcia kolan (''peak flexion'', PF) zaraz po IC, ale przed oderwaniem pięt od podłoża w celu wykonania skoku pionowego.
| |
− |
| |
− | ===Analiza danych===
| |
− |
| |
− | Studenci zapoznają się z modułami (napisanymi w języku programowania Python) do wczytywania oraz wstępnego przetwarzania danych. Następnie samodzielnie wyznaczą następujące wskaźniki biomechaniczne (opisane w pracy (Stone et al., 2013)):
| |
− | *knee valgus motion (KVM),
| |
− | *frontal plane knee angle (FPKA) w dwóch momentach (w trakcie kontaktu pięt z podłożem zaraz po wykonaniu zeskoku oraz w trakcie maksymalnego zgięcia kolan),
| |
− | *knee-to-ankle separation ration (KASR) w momencie PF,
| |
− | *zmiana w czasie średniej pozycji bioder.
| |
− | Wyniki opracowane powinny zostać w formie tabeli, gdzie zestawione zostaną wartości KVM, FPKA, KASR otrzymane dla każdej osoby z grupy. Trajektoria średniej pozycji bioder podczas wykonywania zadania powinna zostać przedstawiona na wykresie.
| |
− |
| |
− | ====Analiza danych====
| |
− |
| |
− | Przykładowy skrypt do wczytywania wyników algorytmów śledzenia pozycji anatomicznych (wraz z metadanymi rejestracji):
| |
− |
| |
− | <source lang="Python">
| |
− | #!/usr/bin/env python
| |
− | # -*- coding: utf-8 -*-
| |
− |
| |
− | from __future__ import print_function
| |
− |
| |
− | import sys
| |
− | sys.path.append('/usr/share/openbci/drivers/kinect/')
| |
− |
| |
− | from KinectUtils import Serialization
| |
− |
| |
− | class KinectDataReader(object):
| |
− | def __init__(self, file_name):
| |
− | super(KinectDataReader, self).__init__()
| |
− | self.file_name = file_name
| |
− | self.in_algs_file = open(self.file_name + '.algs', 'rb')
| |
− | self._s = Serialization()
| |
− |
| |
− | def readNextFrame(self):
| |
− | return self._s.unserialize_frame(self.in_algs_file)
| |
− |
| |
− | if __name__ == '__main__':
| |
− | try:
| |
− | file_name = sys.argv[1]
| |
− | except Exception:
| |
− | file_name = 'test'
| |
− | kinect = KinectDataReader(file_name)
| |
− | while True:
| |
− | frame = kinect.readNextFrame()
| |
− | if frame is None:
| |
− | print('END OF FILE')
| |
− | break
| |
− |
| |
− | frame_index = frame[0]
| |
− | hands_included = frame[1]
| |
− | skeleton_included = frame[2]
| |
− | frame_time = frame[3]
| |
− |
| |
− | if skeleton_included:
| |
− | skel = frame[8]
| |
− | else:
| |
− | skel = None
| |
− |
| |
− | if hands_included:
| |
− | hands = frame[9]
| |
− | else:
| |
− | hands = None
| |
− |
| |
− | print('Idx:', frame_index, 'Time:', frame_time)
| |
− | if skel is not None:
| |
− | print('Skeleton: ', skel.user_x, skel.user_y, skel.user_z)
| |
− |
| |
− | if hands is not None:
| |
− | print('Hands: ', hands.hands[0].x, hands.hands[0].y, hands.hands[0].z)
| |
− | </source>
| |
− |
| |
− | Plik z metadanymi rejestracji zawiera: nagłówek, wyniki algorytmów śledzenia 15 pozycji anatomicznych, wyniki algorytmów śledzenia pozycji rąk (oddzielna opcja w scenariuszu). Pozycje anatomiczne sylwetki zapisane są w następującej kolejności:
| |
− |
| |
− | joints = [JOINT_HEAD,
| |
− | JOINT_NECK,
| |
− | JOINT_RIGHT_SHOULDER,
| |
− | JOINT_LEFT_SHOULDER,
| |
− | JOINT_RIGHT_ELBOW,
| |
− | JOINT_LEFT_ELBOW,
| |
− | JOINT_RIGHT_HAND,
| |
− | JOINT_LEFT_HAND,
| |
− | JOINT_TORSO,
| |
− | JOINT_RIGHT_HIP,
| |
− | JOINT_LEFT_HIP,
| |
− | JOINT_RIGHT_KNEE,
| |
− | JOINT_LEFT_KNEE,
| |
− | JOINT_RIGHT_FOOT,
| |
− | JOINT_LEFT_FOOT]
| |
− |
| |
− | Ich położenie (x,y,z) wyrażone jest w jednostkach [mm].
| |
− | [[Plik:Uklad_jointow.png|600px|thumb|center|<figure id="fig:kinect_joints"></figure>Układ pozycji anatomicznych.]]
| |
− |
| |
− | ====Literatura====
| |
− | *Stone E.E., Butler M., McRuer A., Gray A., Marks J., Skubic M., Evaluation of the Microsoft Kinect for Screening ACL Injury, Conference proceedings: ... Annual International Conference of the IEEE Engineering in Medicine and Biology Society, 2013:4152-5, 2013.
| |
− | *Webster D., Celik O., Systematic review of Kinect applications in elderly care and stroke rehabilitation, Journal of NeuroEngineering and Rehabilitation, 11:108, 2014.
| |
− |
| |
− | ==Raspberry Pi ==
| |
− |
| |
− | ===Raspberry Pi===
| |
− | Raspberry Pi to mała (wymiary: 85.60 mm × 53.98 mm, przy wadze 45 gramów) platforma komputerowa stworzona przez brytyjską organizację charytatywną "Fundację Raspberry Pi" w celach edukacyjnych. Miała za zadanie ułatwić uczniom naukę programowania oraz sterowania zewnętrznymi urządzeniami.
| |
− |
| |
− | Raspberry Pi zasilany jest napięciem 5V poprzez gniazdo microUSB. Niski pobór mocy jest jedną z przyczyn częstego wykorzystania Raspberry w robotyce. Komputer ten to w głównej mierze układ Broadcom:
| |
− | *512 MB RAMu
| |
− | *procesor graficzny
| |
− | *procesor taktowany zegarem 700MHz
| |
− | Raspberry Pi nie posiada wbudowanego dysku twardego - korzysta z karty SD, którą wykorzystuje do załadowania systemu operacyjnego (Raspbian - specjalnie dedykowana wersja Debiana) i przechowywania danych. Do tego komputera można podłączyć urządzenia zewnętrzne poprzez łącza:
| |
− | *HDMI - monitor
| |
− | *ethernet - internet
| |
− | *USB - klawiatura, myszka, itp.
| |
− | Główną cechą Raspberry Pi jest zestaw połączeń GPIO (General Purpose Input Output), które pozwalają na wysyłanie i odbieranie sygnałów cyfrowych (z i do urządzeń zewnętrznych takich jak motorki, czujniki, diody, przełączniki itd.).
| |
− |
| |
− | [[Plik:Raspberry.jpg|400px|thumb|center|<figure id="fig:wbb"></figure>Raspberry Pi. Źródło: https://en.wikipedia.org/wiki/Raspberry_Pi]]
| |
− |
| |
− | ===Gertboard===
| |
− |
| |
− | Gertboard jest to moduł rozszerzający możliwości komputera Raspberry Pi. Płytka ta posiada m.in.:
| |
− | *sterownik silnika prądu stałego
| |
− | *12 buforowanych portów wyjścia/ wejścia
| |
− | *3 przyciski typu tact-switch
| |
− | *6 wejść typu otwarty kolektor
| |
− | *dwukanałowy 10 bitowy przetwornik analogowo-cyfrowy
| |
− | *dwukanałowy 8, 10 lub 12 bitowy przetwornik cyfrowo-analogowy
| |
− | Płytka ta podłączana jest bezpośrednio do pinów GPIO w Raspberry, skąd też pobiera zasilanie.
| |
− |
| |
− | [[Plik:Gertboard.png|400px|thumb|center|<figure id="fig:wbb"></figure>Raspberry Pi z podłączoną płytką Gertboard. Źródło: Gertboard User Maual]]
| |
− |
| |
− | <!--
| |
− | Opis bloku tematycznego:
| |
− | Zajęcia warsztatowe składające się z wprowadzającego w tematykę zajęć wykładu i ćwiczeń indywidualnych wykonywanych przez studentów. Studenci w czasie zajęć przygotowują prototypowe układy elektroniczne mierzące wybrane wielkości fizyczne, oprogramowują je w języku Python i testują. Przygotowane uprzednio eksperymenty w ramach zajęć terenowych umieszczane są w wybranych miejscach na terenie Wydziału Fizyki w celu przeprowadzenia ciągłych i automatycznych pomiarów. Zebrane dane są następnie analizowane przez studentów w ramach ćwiczeń.
| |
− | ===Wyposażenie pracowni===
| |
− |
| |
− | <figure id="fig:spiny">
| |
− | <caption>Moduły i elementy elektroniczne dostępne na pracowni Nowych Technologii</caption>
| |
− | {| class="wikitable" style="width: 90%"
| |
− | ! L.p.
| |
− | ! Nazwa
| |
− | ! Opis
| |
− | !Dostępnych sztuk
| |
− | |-
| |
− | | 1
| |
− | | Rezystor 22 Om
| |
− | | Rezystor węglowy, THT, 22 Om, 1/4 W, 5%
| |
− | | 100
| |
− | |-
| |
− | | 2
| |
− | | Rezystor 1 kOm
| |
− | | Rezystor węglowy, THT, 1 kOm, 1/4 W, 5%
| |
− | | 100
| |
− | |-
| |
− | | 3
| |
− | | Rezystor 4.7 MOm
| |
− | | Rezystor węglowy, THT, 4.7 MOm, 1/4 W, 5%
| |
− | | 100
| |
− | |-
| |
− | | 4
| |
− | | Rezystor 10 Om
| |
− | | Rezystor węglowy, THT, 10 Om, 1/4 W, 5%
| |
− | | 100
| |
− | |-
| |
− | | 5
| |
− | | Rezystor 620 Om
| |
− | | Rezystor węglowy, THT, 620 Om, 1/4 W, 5%
| |
− | | 100
| |
− | |-
| |
− | | 6
| |
− | | Rezystor 100 kOm
| |
− | | Rezystor węglowy, THT, 100 kOm, 1/4 W, 5%
| |
− | | 100
| |
− | |-
| |
− | | 7
| |
− | | Rezystor 2.2 kOm
| |
− | | Rezystor węglowy, THT, 2.2 kOm, 1/4 W, 5%
| |
− | | 100
| |
− | |-
| |
− | | 8
| |
− | | Rezystor 11 Om
| |
− | | Rezystor węglowy, THT, 11 Om, 1/4 W, 5%
| |
− | | 100
| |
− | |-
| |
− | | 9
| |
− | | Rezystor 10 kOm
| |
− | | Rezystor węglowy, THT, 10 kOm, 1/4 W, 5%
| |
− | | 100
| |
− | |-
| |
− | | 10
| |
− | | Rezystor 47 Om
| |
− | | Rezystor węglowy, THT, 47 Om, 1/4 W, 5%
| |
− | | 100
| |
− | |-
| |
− | | 11
| |
− | | Rezystor 22 kOm
| |
− | | Rezystor węglowy, THT, 22 kOm, 1/4 W, 5%
| |
− | | 100
| |
− | |-
| |
− | | 12
| |
− | | Kondensator 100 nF
| |
− | | Kondensator ceramiczny, THT, 100 nF, 50V, 10%
| |
− | | 25
| |
− | |-
| |
− | | 13
| |
− | | Kondensator elektrolityczny 470 uF
| |
− | | Kondensator elektrolityczny, THT, 470 uF, 16V, 20%
| |
− | | 25
| |
− | |-
| |
− | | 14
| |
− | | Stabilizator napięcia 7805
| |
− | | Scalony stabilizator napięcia L7805ABV, nieregulowany, 5V, 1.5A, obudowa TO220, THT
| |
− | | 10
| |
− | |-
| |
− | | 15
| |
− | | Wzmacniacz operacyjny CA3140EZ
| |
− | | Wzmacniacz operacyjny CA3140EZ, 4.5 MHz, 4-36 VDC, 1 kanał, ubudowa DIP8
| |
− | | 10
| |
− | |-
| |
− | | 16
| |
− | | Fotodioda VTP1220FBH
| |
− | | Fotodioda na światło widzialne VTP1220FBH, 550 nm, 400-700 nm, montaż: THT
| |
− | | 10
| |
− | |-
| |
− | | 17
| |
− | | Dioda LED zielona
| |
− | | Dioda LED zielona, 3 mm, 15 mcd, 40 st., montaż: THT
| |
− | | 10
| |
− | |-
| |
− | | 18
| |
− | | Dioda LED czerwona
| |
− | | Dioda LED zielona, 3 mm, 8-50 mcd, 60 st., montaż: THT
| |
− | | 10
| |
− | |-
| |
− | | 19
| |
− | | Dioda LED żółta
| |
− | | Dioda LED żółta, 3 mm, 20-30 mcd, 40 st., montaż: THT
| |
− | | 10
| |
− | |-
| |
− | | 20
| |
− | | Przetwornik MCP3004
| |
− | | Przetwornik analogowo-cyfrowy (ADC), 4 kanały, 10 bit, 200 kcps, 2.7-5.5 V, obudowa DIP14
| |
− | | 10
| |
− | |-
| |
− | | 21
| |
− | | Ładowarka Imax B6AC Dual Power
| |
− | | Mikroprocesorowa ładowarka/balancer akumulatorów LiIon/LiPo/LiFe 1-6 cel, NiCd/NiMH 1-15 cel, Pb 2-20V, Maksymalny prąd ładowania 6A
| |
− | | 1
| |
− | |-
| |
− | | 22
| |
− | | Moduł GPS
| |
− | | Moduł GPS Adafriut Ultimate D GPS Breakout fw5632 v3 + CR1220
| |
− | | 7
| |
− | |-
| |
− | | 23
| |
− | | Czujnik gazów
| |
− | | Gassensor Figaro TGS2600-B00
| |
− | | 10
| |
− | |-
| |
− | | 24
| |
− | | Czujnik gazów
| |
− | | Gassensor Figaro TGS2442-B00
| |
− | | 10
| |
− | |-
| |
− | | 25
| |
− | | Czujnik wilgotności i temperatury
| |
− | | DHT22
| |
− | | 7
| |
− | |-
| |
− | |}
| |
− | </figure>
| |
− | 1. Moduły "mod10DOF"
| |
− | Moduł 10DOF zawiera czujniki pozwalające mierzyć zmiany dziewięciu stopni swobody plus ciśnienie (L3G4200D, ADXL345, HMC5883L, BMP085):
| |
− |
| |
− | *trzyosiowy żyroskop L3G4200D
| |
− | *trzyosiowy akcelerometr ADXL345
| |
− | *trzyosiowy czujnik pola magnetycznego Honeywell HMC5883L (+/-8gauss)
| |
− | *czujnik ciśnienia BMP085 (300 - 1100hPa)
| |
− |
| |
− | Wszystkie elementy pomiarowe komunikują się magistralą I2C (napięcia logiki i zasilania w zakresie 3-5 V)
| |
− |
| |
− | 2. Moduł "mod10DOF_1"
| |
− | Moduł jest analogiczny do powyższego z tym, że wykorzystano w nim inne czujniki: żyroskop ITG3205 (±2000°/sec) i akcelerometr BMA180 (+-1g ... +-16g).
| |
− |
| |
− | ===Zajęcia 1===
| |
− | Plan zajęć:
| |
− | *Komputer jednoukładowy SoC, przykłady
| |
− | *Dlaczego Raspberry Pi?
| |
− | *Architektura ARM, harvardzka vs Von Neumanna
| |
− | *Podstawowe elementy komputera RP, schemat elektryczny, zasilanie, bezpieczeństwo użytkowania, BHP pracy, omówienie zestawu dostępnych elementów
| |
− | *Pierwsze uruchomienie RP, logowanie, zapoznanie z systemem
| |
− | *Porty GPIO, sterowania programowe, elektroniczny „Hello world!” – mrugająca dioda, sterowanie elementami wykonawczymi
| |
− |
| |
− | ====Opis wyprowadzeń ogólnego portu wejścia/wyjścia (GPIO)====
| |
− |
| |
− | [[File:Raspberry-Pi-GPIO-pinouts.png|600px|thumb|center|<figure id="fig:Raspberry-Pi-GPIO-pinouts"></figure>Opis wyprowadzeń ogólnego portu wejścia/wyjścia (GPIO, ang. General Port Input/Output) we wszystkich modelach Raspberry Pi.]]
| |
− |
| |
− |
| |
− | ====Mrugająca dioda, czyli elektroniczne Hello World!====
| |
− |
| |
− |
| |
− | Mrugająca dioda w języku Python:
| |
− | <source lang = 'python'>
| |
− | import time
| |
− | import RPi.GPIO as GPIO
| |
− |
| |
− | GPIO.setmode(GPIO.BCM)
| |
− |
| |
− | StepPins = [24,25,8,7]
| |
− |
| |
− | for pin in StepPins:
| |
− | print "Setup pins"
| |
− | GPIO.setup(pin,GPIO.OUT)
| |
− | GPIO.output(pin, False)
| |
− | </source>
| |
− |
| |
− | Mrugająca dioda w języku C:
| |
− | <source lang = 'c'>
| |
− | #include <wiringPi.h>
| |
− | int main (void)
| |
− | {
| |
− | wiringPiSetup () ;
| |
− | pinMode (0, OUTPUT) ;
| |
− | for (;;)
| |
− | {
| |
− | digitalWrite (0, HIGH) ; delay (500) ;
| |
− | digitalWrite (0, LOW) ; delay (500) ;
| |
− | }
| |
− | return 0 ;
| |
− | }
| |
− | </source>
| |
− |
| |
− | Zanim uruchomimy program w C musimy go najpierw skompilować linkując również bibliotekę wiringPi:
| |
− |
| |
− | <source lang = 'bash'>
| |
− | gcc -Wall -o blink blink.c -lwiringPi
| |
− | sudo ./blink
| |
− | </source>
| |
− |
| |
− | [[File:Opis_płyty_RP_small.png|600px|thumb|center|<figure id="fig:spi_sck"></figure>Opis płyty głównej komputera Raspberry Pi Rev. 2 ver. B. Złącze Display Serial Interface (DSI) służy do podłączenia zewnętrznego wyświetlacza, złącze Camera Serial Interface (CSI) przeznaczona jest do podłączenia zewnętrznej kamery. Złącze JTAG jest złączem programowania/debugowania chipu Broadcom, wykorzystywane podczas produkcji.]]
| |
− |
| |
− | ===Zajęcia 2===
| |
− | Plan zajęć:
| |
− | *Generator przebiegu prostokątnego
| |
− | *Modulacja PWM (dla chętnych)
| |
− | *Komunikacja ze światem zewnętrznym – magistrala I2C
| |
− | *Uruchomienie czujnika ciśnienia BMP085
| |
− |
| |
− | ====Uruchamianie obsługi magistrali I2C====
| |
− | UWAGA! Na niektórych komputerach magistrala I2C została już wcześniej uruchomiona. Zanim zacznie się poniższą procedurę warto najpierw przejść do kroku 6 i sprawdzić czy system nie jest już przypadkiem skonfigurowany i gotowy.
| |
− |
| |
− | Obsługa magistrali I2C jest domyślnie wyłączona w systemie Raspbian. Żeby ją uruchomić należy wykonać następujące kroki:
| |
− |
| |
− | 1. Otworzyć do edycji czarną listę modułów jądra (plik konfiguracyjny narzędzia modprobe) i wykomentować wiersz dotyczący magistrali I2C
| |
− |
| |
− | <source lang = 'bash'>
| |
− | sudo nano /etc/modprobe.d/raspi-blacklist.conf
| |
− | </source>
| |
− |
| |
− | Jeżeli mamy do czynienia z domyślnym plikiem znajdziemy w nim następujące linie:
| |
− |
| |
− | <source lang = 'bash'>
| |
− | # blacklist spi and i2c by default (many users don't need them)
| |
− |
| |
− | blacklist spi-bcm2708
| |
− | blacklist i2c-bcm2708
| |
− | </source>
| |
− |
| |
− | z których powinniśmy wykomentować linię blacklist i2c-bcm2708:
| |
− |
| |
− | <source lang = 'bash'>
| |
− | # blacklist spi and i2c by default (many users don't need them)
| |
− |
| |
− | blacklist spi-bcm2708
| |
− | #blacklist i2c-bcm2708
| |
− | </source>
| |
− |
| |
− | 2. Gdy alias modułu I2C został usunięty z czarnej listy możemy dodać go do listy modułów jądra ładowanych przy starcie systemu. Otwieramy do edycji plik modules:
| |
− |
| |
− | <source lang = 'bash'>
| |
− | sudo nano /etc/modules
| |
− | </source>
| |
− |
| |
− | i dodajemy nową linię "i2c-dev":
| |
− |
| |
− | <source lang = 'bash'>
| |
− | # /etc/modules: kernel modules to load at boot time.
| |
− | #
| |
− | # This file contains the names of kernel modules that should be loaded
| |
− | # at boot time, one per line. Lines beginning with "#" are ignored.
| |
− | # Parameters can be specified after the module name.
| |
− |
| |
− | snd-bcm2835
| |
− | i2c-dev
| |
− | </source>
| |
− |
| |
− | 3. Zanim zrestartujemy system, żeby załadować nowy moduł, warto przedtem doinstalować narzędzia diagnostyczne:
| |
− |
| |
− | <source lang = 'bash'>
| |
− | sudo apt-get install i2c-tools
| |
− | </source>
| |
− |
| |
− | i bibliotekę dla języka Python umożliwiającą wykorzystanie magistrali I2C:
| |
− |
| |
− | <source lang = 'bash'>
| |
− | sudo apt-get install python-smbus
| |
− | </source>
| |
− |
| |
− | 4. Po zainstalowaniu powyższych pakietów konieczne jest jeszcze dodanie użytkownika (domyślnie użytkownika pi) do grupy mającej dostęp do magistrali:
| |
− |
| |
− | <source lang = 'bash'>
| |
− | sudo adduser pi i2c
| |
− | </source>
| |
− |
| |
− | 5. Teraz możemy zrestartować komputer:
| |
− |
| |
− | <source lang = 'bash'>
| |
− | sudo reboot
| |
− | </source>
| |
− |
| |
− | 6. Po restarcie moduł i2c-dev powinien już działać. Żeby przetestować hardware próbujemy uzyskać dostęp do magistrali I2C i odczytać adresy podłączony urządzeń:
| |
− |
| |
− | <source lang = 'bash'>
| |
− | i2cdetect -y 0
| |
− | </source>
| |
− |
| |
− | Jeżeli nie podłączyliśmy żadnych urządzeń dostaniemy prawdopodobnie następujący wynik:
| |
− | [[File:I2cdetect-empty.png|600px|thumb|center|<figure id="fig:I2cdetect-empty"></figure>]]
| |
− | Urządzenie pojawiające się pod adresem 0x1b to adres przetwornika audio, oznaczenie UU oznacza, że ten adres już jest używany przez sterownik pracujący w trybie jądra.
| |
− |
| |
− | Jeżeli prawidłowo podłączyliśmy np. moduł DOF zobaczymy dostępne adresy urządzeń podłączonych do I2C:
| |
− |
| |
− | [[File:I2cdetect.png|600px|thumb|center|<figure id="fig:I2cdetect"></figure>]]
| |
− |
| |
− |
| |
− | Jeżeli nie udało nam się uzyskać listy adresów:
| |
− |
| |
− | [[File:I2cdetect-wrong.png|600px|thumb|center|<figure id="fig:I2cdetect-wrong"></figure>]]
| |
− |
| |
− | wówczas warto sprawdzić czy magistrala I2C nie jest dostępna pod innym numerem porządkowym (np. próbując z parametrem -y 1).
| |
− |
| |
− |
| |
− |
| |
− | Rezystor podciągający (pull up):
| |
− | <source lang = 'python'>
| |
− | GPIO.setup(17, GPIO.IN,pull_up_down=GPIO.PUD_UP)
| |
− | </source>
| |
− |
| |
− | ===Zajęcia 3===
| |
− | Plan zajęć:
| |
− | *Komunikacja ze światem zewnętrznym – magistrala SPI
| |
− | *Uruchomienie przetwornika analogowe
| |
− | *Pomiar dowolnej wybranej wielkości analogowej (oświetlania, napięcia, wskazań czujników stężeń)
| |
− |
| |
− | [[File:spi.jpg|300px|thumb|right|<figure id="fig:spi"></figure>Komunikacja z wykorzystaniem magistrali SPI odbywa się przez wymianę danych zawartych w rejestrach przesuwnych układów Master i Slave.]]
| |
− |
| |
− |
| |
− |
| |
− | [[File:spi_sck.png|300px|thumb|right|<figure id="fig:spi_sck"></figure>Synchronizację transmisji zapewnia generowany przez układ Master sygnał zegarowy SCK.]]
| |
− |
| |
− |
| |
− |
| |
− | [[File:spi-multislave.png|300px|thumb|right|<figure id="fig:spi_sck"></figure>Do magistrali SPI może być dołączone wiele układów Slave. W celu wybrania konkretnego układu, z którym ma odbywa się w danym momencie komunikacja, służy linia Chip Select (CS), osobna dla każdego układu Slave.]]
| |
− |
| |
− | ===Zajęcia 4===
| |
− |
| |
− | Plan zajęć:
| |
− |
| |
− | *Komunikacja ze światem zewnętrznym – magistrala 1-Wire
| |
− | *Pomiar temperatury z wykorzystaniem czujnika DS18B20
| |
− | *Synchronizacja wyników ze zdalną bazą danych (Google Docs)
| |
− | *Pomiar temperatury i wilgotności czujnikiem DHT22 – wzorowana na 1-Wire
| |
− |
| |
− | ===Zajęcia 5===
| |
− | Plan zajęć:
| |
− | *Transmisja szeregowa
| |
− | *Komunikacja z modułem GPS
| |
− | *Parsowanie danych w standardzie NMEA
| |
− |
| |
− | ====Protokół NMEA 0183====
| |
− | Protokół komunikacji NMEA 0183 został opracowany przez amerykańską organizację handlową The National Marine Electronics Association (NMEA), zajmującą się rozwijaniem specyfikacji definiujących interfejsy między różnymi elementami morskiej elektroniki nawigacyjnej. Standard NMEA 0183 opisuje format przesyłu danych i standardy elektroniczne pozwalające na komunikację z komputerami i między sobą takich urządzeń jak sonary, żyrokompasy, autopiloty, anemometry i odbiorniki GPS. Z tego powodu większość, o ile nie wszystkie, odbiorniki GPS mają zaimplementowane przekazywanie danych w powyższym formacie.
| |
− |
| |
− |
| |
− | Od strony sprzętowej NMEA 0183 bazuje na popularnym komputerowym standardzie komunikacji szeregowej RS232, ale precyzyjnie mówiąc nie jest z nimi tożsamy. Szybkość przesyłu danych może być zmieniana, ale każde podłączone urządzenie powinno być w stanie pracować z prędkością 4800 bitów/s. Dane przesyłane są w postaci znaków ASCII, bez znaku parzystości, z jednymi bitem stopu.
| |
− |
| |
− | ====Dekodowanie wiadomości NMEA 0183====
| |
− | Dane są zawsze przesyłane w postaci pojedynczych wiadomości składającej się łącznie z maksymalnie 82 znaków (wliczając znaki końca linii i powrotu karetki). Każda wiadomość zaczyna się znakiem dolara '$' i kończy znakami końca linii i powrotu karetki <CR><LF> (ang. Carriage Return, Line Feed; <CR> o kodzie ASCII 13, <LF> o kodzie ASCII 10). Kolejne dane są rozdzielone od siebie przecinkami, dwuznakowa suma kontrolna pojawia się po gwiazdce "*".
| |
− |
| |
− | Budowa typowej wiadomość NMEA wygląda następująco:
| |
− |
| |
− | $GPGGA,193734.000,5214.0928,N,02105.8908,E,2,07,0.98,84.1,M,38.9,M,0000,0000*53<CR><LF>
| |
− |
| |
− | $ - znak początku wiadomości
| |
− | GP - dwuliterowy skrót oznaczający typ urządzenia nadającego dana, GP oznacza dane z odbiornika GPS
| |
− | GGA - trzyliterowe oznaczeni rodzaju wiadomości, GGA to kluczowe informacje na temat położenia w trzech wymiarach i dokładności przekazywanych danych
| |
− | 193734.000 - godzina czasu Greenwich (UTC), w tym przypadku 19:37 i 34 sekundy
| |
− | 5214.0928 - szerokość geograficzna, pierwsze dwa znaki to liczba stopni, pozostałe liczba minut, czyli: 52'14.0928"
| |
− | N - wskaźnik półkuli dla szerokości geogr. półkula północna
| |
− | 02105.8908 - wysokość geograficzna, pierwsze trzy znaki to liczba stopni, pozostałe liczba minut, czyli: 21'5.8908"
| |
− | E - wskaźnik półkuli dla wysokości geogr. półkula wschodnia
| |
− | 2 - jakość "fixu": 0 = invalid
| |
− | 1 = GPS fix (SPS)
| |
− | 2 = DGPS fix
| |
− | 3 = PPS fix
| |
− | 4 = Real Time Kinematic
| |
− | 5 = Float RTK
| |
− | 6 = estimated (dead reckoning) (2.3 feature)
| |
− | 7 = Manual input mode
| |
− | 8 = Simulation mode
| |
− | 07 - liczba śledzonych satelitów
| |
− | 0.98 - horyzontalne rozmycie położenia
| |
− | 84.1,M - wysokość w metrach nad średnim poziomem morza
| |
− | 38.9,M - wysokość geoidy w metrach (średniego poziomu morza) ponad elipsoidę WGS84 (zbiór parametrów określających wielkość i kształt Ziemi oraz właściwości jej potencjału grawitacyjnego. System ten definiuje elipsoidę, która jest generalizacją kształtu geoidy, wykorzystywaną do tworzenia map)
| |
− | 0000 - czas w sekundach od ostatniej aktualizacji DGPS
| |
− | 0000 - numer identyfikacyjny stacji DGPS
| |
− |
| |
− |
| |
− | Dostępne na pracowni moduły GPS są w stanie generować następujące komunikaty: GSA (Overall Satellite data), GSV (Detailed Satellite dat), RMC (recommended minimum data for gps), VTG (Vector track an Speed over the Ground), GGA (Fix information),
| |
− |
| |
− |
| |
− | Poniżej znajduje się fragment sekwencji wiadomości wysyłanych przez odbiornik GPS:
| |
− |
| |
− | <source lang = 'bash'>
| |
− | $GPRMC,193749.000,A,5214.1444,N,02105.8814,E,24.61,15.81,050215,,,D*61
| |
− | $GPVTG,15.81,T,,M,24.61,N,45.60,K,D*03
| |
− | $GPGGA,193750.000,5214.1511,N,02105.8847,E,2,07,0.99,81.6,M,38.9,M,0000,0000*5F
| |
− | $GPGSA,A,3,12,17,14,24,06,15,25,,,,,,1.79,0.99,1.49*02
| |
− | $GPRMC,193750.000,A,5214.1511,N,02105.8847,E,25.39,17.50,050215,,,D*6C
| |
− | $GPVTG,17.50,T,,M,25.39,N,47.04,K,D*01
| |
− | $GPGGA,193751.000,5214.1579,N,02105.8884,E,2,07,0.98,81.4,M,38.9,M,0000,0000*5C
| |
− | $GPGSA,A,3,12,17,14,24,06,15,25,,,,,,1.78,0.98,1.49*02
| |
− | $GPRMC,193751.000,A,5214.1579,N,02105.8884,E,26.33,18.90,050215,,,D*66
| |
− | $GPVTG,18.90,T,,M,26.33,N,48.79,K,D*0E
| |
− | $GPGGA,193752.000,5214.1649,N,02105.8925,E,2,07,0.98,81.2,M,38.9,M,0000,0000*53
| |
− | $GPGSA,A,3,12,17,14,24,06,15,25,,,,,,1.78,0.98,1.49*02
| |
− | $GPRMC,193752.000,A,5214.1649,N,02105.8925,E,26.79,20.03,050215,,,D*60
| |
− | $GPVTG,20.03,T,,M,26.79,N,49.63,K,D*0B
| |
− | $GPGGA,193753.000,5214.1720,N,02105.8966,E,2,07,0.99,81.2,M,38.9,M,0000,0000*5A
| |
− | $GPGSA,A,3,12,17,14,24,06,15,25,,,,,,1.78,0.99,1.49*03
| |
− | $GPRMC,193753.000,A,5214.1720,N,02105.8966,E,27.30,19.66,050215,,,D*6D
| |
− | $GPVTG,19.66,T,,M,27.30,N,50.58,K,D*0E
| |
− | $GPGGA,193754.000,5214.1791,N,02105.9011,E,2,07,0.98,81.1,M,38.9,M,0000,0000*5D
| |
− | $GPGSA,A,3,12,17,14,24,06,15,25,,,,,,1.78,0.98,1.49*02
| |
− | $GPGSV,2,1,08,24,81,195,46,12,61,265,46,17,30,050,40,14,23,317,32*71
| |
− | $GPGSV,2,2,08,06,22,103,39,25,21,261,26,33,21,223,26,15,17,197,21*70
| |
− | $GPRMC,193754.000,A,5214.1791,N,02105.9011,E,27.27,23.10,050215,,,D*66
| |
− | $GPVTG,23.10,T,,M,27.27,N,50.54,K,D*0C
| |
− | </source>
| |
− | W przypadku braku danych wysyłane są puste pola rozdzielone przecinkami - brak "fixu" GPS nie zatrzymuje transmisji!
| |
− |
| |
− | ====Konfiguracja układu UART w Raspbian====
| |
− | Port szeregowy w Raspberry Pi domyślnie jest skonfigurowany do celu debugowania a także na jego wyjście przekierowane wszystkim komunikaty startowe. Ponadto, na port szeregowy jest przekierowany jeden ze standardowych terminali umożliwiający podanie nazwy użytkownika, hasła i zalogowanie się do komputera. Domyślnie port szeregowy w Raspbian jest dostępny jak /dev/ttyAMA0. Żeby przejąć nad nim pełną kontrolę nad należy domyślną konfigurację zmodyfikować, tak aby mógł być wykorzystany wyłącznie do naszych celów i żeby jego praca nie była zakłócana niepotrzebnymi komunikatami.
| |
− |
| |
− | 1. Po pierwsze otwieramy do edycji plik /boot/cmdline.txt:
| |
− |
| |
− | <source lang = 'bash'>
| |
− | sudo nano /boot/cmdline.txt
| |
− | </source>
| |
− |
| |
− | Powinny się w nim znajdować mniej więcej następujące ustawienia:
| |
− |
| |
− | <source lang = 'bash'>
| |
− | dwc_otg.lpm_enable=0 console=ttyAMA0,115200 kgdboc=ttyAMA0,115200 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait
| |
− | </source>
| |
− |
| |
− | Słowo kluczowe console ustawia standardowy strumień wyjścia na port szeregowy (ttyAMA0) i trafią tam wszystkie komunikaty pojawiające się w trakcie bootowania systemu, natomiast słowo kluczowe kgdboc włącza tryb debugowania jądra. Żeby uwolnić port szeregowy od tych zastosowań musimy usunąć wszystkie odniesienia do ttyAMA0, modyfikując powyższy wiersz np. do następującej postaci:
| |
− |
| |
− | <source lang = 'bash'>
| |
− | dwc_otg.lpm_enable=0 console=tty1 root=/dev/mmcblk0p2 rootfstype=ext4 elevator=deadline rootwait
| |
− | </source>
| |
− |
| |
− | 2. Teraz pozostaje zmodyfikować ustawienia terminali:
| |
− |
| |
− | Otwieramy do edycji plik /etc/inittab:
| |
− |
| |
− | <source lang = 'bash'>
| |
− | sudo nano /etc/inittab
| |
− | </source>
| |
− |
| |
− | gdzie znajdujemy następujący fragment:
| |
− |
| |
− | <source lang = 'bash'>
| |
− | #Spawn a getty on Raspberry Pi serial line
| |
− | T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
| |
− | </source>
| |
− |
| |
− | i go wykomentowujemy:
| |
− |
| |
− | <source lang = 'bash'>
| |
− | #Spawn a getty on Raspberry Pi serial line
| |
− | #T0:23:respawn:/sbin/getty -L ttyAMA0 115200 vt100
| |
− | </source>
| |
− |
| |
− | 3. Żeby zmiany weszły w życie musimy jeszcze zrestartować system:
| |
− |
| |
− | <source lang = 'bash'>
| |
− | sudo reboot
| |
− | </source>
| |
− |
| |
− | 4. Po restarcie powinniśmy dysponować w zasadzie standardowym linuksowym portem szeregowym, niezakłócanym przez żadne procesy systemowe. Poprawność powyższej procedury możemy sprawdzić upewniając się jaka jest aktualna konsola ustawiona dla jądra:
| |
− |
| |
− | <source lang = 'bash'>
| |
− | cat /proc/cmdline
| |
− | </source>
| |
− |
| |
− | i czy żaden proces nie używa portu szeregowego (w szczególności getty):
| |
− |
| |
− | <source lang = 'bash'>
| |
− | ps aux | grep ttyAMA0
| |
− | </source>
| |
− |
| |
− | ====Narzędzia do testowania modułu GPS====
| |
− |
| |
− | Żeby przetestować czy nasz moduł GPS funkcjonuje prawidłowo instalujemy następujące narzędzia:
| |
− | <source lang = 'bash'>
| |
− | sudo apt-get install gpsd gpsd-clients python-gps
| |
− | sudo apt-get install minicom
| |
− | </source>
| |
− |
| |
− | Po pierwsze możemy podejrzeć czy nasz moduł GPS wysyła cokolwiek przez port szeregowy. Używamy do tego narzędzia minicom:
| |
− |
| |
− | <source lang = 'bash'>
| |
− | minicom -b 9600 -o -D /dev/ttyAMA0
| |
− | </source>
| |
− |
| |
− | Żeby z niego wyjść należy wcisnąć 'Ctr+A' a następnie 'X' i potwierdzić wybór.
| |
− |
| |
− | Powinniśmy zobaczyć komunikaty NMEA, nawet jeżeli odbiornik jest uruchomiony w budynku :
| |
− |
| |
− | [[File:Minicom.png|600px|thumb|center|<figure id="fig:minicom"></figure>]]
| |
− |
| |
− | W zależności czy moduł już "zafixował" położenie, czy jeszcze nie, zobaczymy więcej lub mniej aktualnych danych. Należy pamiętać, że nawet przy dobrej widoczności satelitów potrzeba minimum około 45 sekund na uzyskanie "fixu". Jeżeli otrzymujemy dane, możemy spróbować użyć gotowego programu do ich parsowania. W tym celu uruchamiamy demon parsujący dane z portu szeregowego:
| |
− |
| |
− | <source lang = 'bash'>
| |
− | sudo gpsd /dev/ttyAMA0 -F /var/run/gpsd.sock
| |
− | </source>
| |
− |
| |
− | Następnie uruchamiam program do wyświetlania danych:
| |
− | <source lang = 'bash'>
| |
− | cgps -s
| |
− | </source>
| |
− |
| |
− | Powinniśmy zobaczyć taki widok:
| |
− |
| |
− | [[File:Gpsd.png|600px|thumb|center|<figure id="fig:Gpsd"></figure>]]
| |
− |
| |
− | Jeżeli pracujemy w środowisku Xów możemy uruchomić graficzna wersję programu:
| |
− |
| |
− | <source lang = 'bash'>
| |
− | xgps
| |
− | </source>
| |
− |
| |
− | i obejrzeć rozmieszczenie satelitów na niebie:
| |
− |
| |
− | [[File:Xgps.png|600px|thumb|center|<figure id="fig:xps"></figure>]]
| |
− |
| |
− | Należy pamiętać, że jeżeli chcielibyśmy ponownie uzyskać "ręczny" dostęp do portu szeregowego należy wcześniej zakończyć pracę demona gpsd, który blokuje możliwość używania portu przez inne programy:
| |
− |
| |
− | <source lang = 'bash'>
| |
− | sudo killall gpsd
| |
− | </source>
| |
− |
| |
− | ====Ćwiczenia====
| |
− | 1. Napisz w języku Python parser danych otrzymywanych z GPS. W przypadku niemożliwości uzyskania fixingu użyj poniższych danych testowych:
| |
− |
| |
− | 2. W pliku track.txt znajduje się zarejestrowana trasa zapisana w formacie NEMA. Przeprowadź parsowanie danych, nanieś uzyskane współrzędne i ustal: adres początkowy/końcowy trasy, czas pokonania trasy, średnią i maksymalną prędkość.
| |
− |
| |
− | 3. [Dla zaawansowanych] Przygotuj GPS logger zasilany ogniwem litowym i z jego wykorzystaniem spróbuj zdigitalizować kształt wybranej powierzchni terenu (wybierz miejsce z charakterystyczną rzeźbą np. Pola Mokotowskie, Górkę Szczęśliwicką czy też Skarpę Wiślaną). Z uzyskanych punktów odtwórz trójwymiarowy model rzeźby terenu.
| |
− |
| |
− | ====Wskazówki====
| |
− |
| |
− | 1. Do narysowania danych odczytanych z GPS w postaci trasy na mapie można użyć narzędzia internetowego GPS Visualizer, pozwalającego wczytać dane w formacie NMEA: http://www.gpsvisualizer.com/
| |
− |
| |
− | ====Ciekawostki====
| |
− | GPS loggery wykorzystano w badaniu zachowania psów pasterskich i ich sposobów na zaganianie i kontrolowanie stada owiec. Zebrane dane pozwoliły stworzyć model komputerowy odwzorowujący zachowanie psa:
| |
− |
| |
− | <iframe width="420" height="315" src="https://www.youtube.com/embed/kGynBYD3sbE" frameborder="0" allowfullscreen></iframe>
| |
− |
| |
− | Daniel Strömbom, Richard P. Mann, Alan M. Wilson, Stephen Hailes, A. Jennifer Morton, David J. T. Sumpter, Andrew J. King, Solving the shepherding problem: heuristics for herding autonomous, interacting agents, The Royal Society, 2014
| |
− | http://rsif.royalsocietypublishing.org/content/11/100/20140719
| |
− |
| |
− | ===Zajęcia 6===
| |
− | Plan zajęć:
| |
− | *Zdalne logowanie na RP, automatyczny start oprogramowania, automatyzacja pomiarów
| |
− | *Realizacja projektu zaliczeniowego
| |
− |
| |
− | ====Automatyczny start====
| |
− | Czasami zachodzi potrzeba przygotowania komputera Raspberry Pi do automatycznego startu przygotowanych skryptów/programów bez zewnętrznej ingerencji użytkownika. Wówczas możemy uruchomić pożądane pomiary np. w warunkach terenowych bez dysponowania monitorem/klawiaturą/myszką. Do uruchamiania skryptów według harmonogramu lub w przypadku nastąpienia pewnym zdarzeń (np. uruchomienia) możemy użyć programu crone.
| |
− |
| |
− | W pierwszej kolejności przygotowujemy skrypt uruchamiający o nazwie loggerLauncher.sh i przykładowej zawartości jak niżej:
| |
− | <source lang = 'bash'>
| |
− | #/bin/sh
| |
− |
| |
− | cd /home/pi/
| |
− | sudo python /home/pi/dataLogger.py
| |
− | </source>
| |
− |
| |
− | Zmieniamy ustawienia pliku na plik wykonywalny:
| |
− | <source lang = 'bash'>
| |
− | chmod 755 /home/pi/loggerLauncher.sh
| |
− | </source>
| |
− | Upewniamy się, że skrypt uruchamia się prawidłowo:
| |
− | <source lang = 'bash'>
| |
− | sh launcher.sh
| |
− | </source>
| |
− | Teraz możemy przygotowany skrypt dodać do zadań crone, otwieramy do edycji listę zadań:
| |
− | <source lang = 'bash'>
| |
− | sudo crontab -e
| |
− | </source>
| |
− | i dodajemy następującą linię:
| |
− | <source lang = 'bash'>
| |
− | @reboot sh /home/pi/loggerLauncher.sh >/home/pi/cronlog 2>&1
| |
− | </source>
| |
− | która spowoduje uruchomienia naszego skryptu przy starcie systemu. Możemy również ustawić cykliczne uruchamianie:
| |
− | <source lang = 'bash'>
| |
− | # Start co 2 minuty
| |
− | */2 * * * * /home/pi/loggerLauncher.sh >/home/pi/cronlog 2>&1
| |
− | </source>
| |
− |
| |
− | ===Zajęcia 6===
| |
− | Plan zajęć:
| |
− | *Realizacja projektu zaliczeniowego i zaliczenie bloku tematycznego RP.
| |
− |
| |
− | ===Linki===
| |
− | http://pi.gadgetoid.com/pinout
| |
− |
| |
− | https://code.google.com/p/webiopi/
| |
− |
| |
− | https://www.primianotucci.com/blog/android-on-udoo-quad
| |
− |
| |
− | http://docs.scipy.org/doc/scipy-0.14.0/reference/generated/scipy.spatial.Delaunay.html
| |
− |
| |
− | http://www.gpsinformation.org/dale/nmea.htm
| |
− |
| |
− | ===Dokumentacja===
| |
− | [[Media:Raspberry-Pi-Rev-1.0-Model-AB-Schematics.pdf|Raspberry Pi Revision 1.0 Model AB]] - schemat elektryczny
| |
− |
| |
− | [[Media:Raspberry-Pi-Rev-2.0-Model-AB-Schematics.pdf|Raspberry Pi Revision 2.0 Model AB]] - schemat elektryczny
| |
− |
| |
− | [[Media:Raspberry-Pi-Rev-2.1-Model-AB-Schematics.pdf|Raspberry Pi Revision 2.1 Model AB]] - schemat elektryczny
| |
− |
| |
− | ===Przydatne polecenia Raspbian===
| |
− | Uruchomienie Xów: startx
| |
− | Login: pi
| |
− | Hasło: raspberry
| |
− |
| |
− | Sprawdzenie ile jest wolnego miejsca na dysku?:
| |
− | df -Bm
| |
− | Dodaj -h (od ang. "Human readable"), żeby uzyskać informację przeliczoną na megabajty, gigabajty itd.
| |
− |
| |
− | Jak zamontować pendrive?
| |
− |
| |
− | * Podłącz urządzenie
| |
− | * Sprawdź jaką nazwę nadał mu system:
| |
− | ls /dev/sd*
| |
− | * Zamontuj:
| |
− | sudo mount -t vfat /dev/sda /mnt/usb
| |
− |
| |
− | Upewnij się wcześniej, że folder /mnt/usb istnieje, w razie potrzeby utwórz.
| |
− |
| |
− | Jak wyłączyć Raspberry Pi?
| |
− |
| |
− | Użyj polecnia: sudo shutdown -h now albo w przypadku żywania LXDE GUI naciśnij czerwony przycisk wyłączenia w menu w prawym górnym rogu ekranu.
| |
− |
| |
− | ====Udostępnianie folderu w sieci Windows====
| |
− |
| |
− | Instalujemy Sambę:
| |
− | <source lang = 'bash'>
| |
− | sudo apt-get install samba samba-common-bin
| |
− | </source>
| |
− |
| |
− | Tworzymy udostępniany folder:
| |
− | <source lang = 'bash'>
| |
− | mkdir ~/share
| |
− | </source>
| |
− |
| |
− | Otwieramy do edycji plik konfiguracyjny Samby:
| |
− | <source lang = 'bash'>
| |
− | sudo nano /etc/samba/smb.conf
| |
− | </source>
| |
− |
| |
− | Upewniamy się, że obsługa udostępniania folderów dla Windows jest włączony, a nazwa grupy roboczej taka do jakiej chcemy dołączyć:
| |
− | <source lang = 'bash'>
| |
− | workgroup = WORKGROUP
| |
− | wins support = yes
| |
− | </source>
| |
− |
| |
− | Grupa robocza "WORKGROUP" jest domyślną grupą dla Windows.
| |
− |
| |
− | Na końcu plik konfiguracyjnego dodajemy opis udostępnianego zasobu:
| |
− | <source lang = 'bash'>
| |
− | [PiShare]
| |
− | comment=Raspberry Pi Share
| |
− | path=/home/pi/share
| |
− | browseable=Yes
| |
− | writeable=Yes
| |
− | only guest=no
| |
− | create mask=0777
| |
− | directory mask=0777
| |
− | public=no
| |
− | </source>
| |
− |
| |
− | Parametr "public=no" oznacza, że każdy próbujący uzyskać dostęp do tego zasobu będzie musiał się zalogować. Należy ustawić jeszcze nazwę użytkownika i hasło do logowania do folderu:
| |
− | <source lang = 'bash'>
| |
− | sudo smbpasswd -a pi
| |
− | </source>
| |
− |
| |
− | Gotowe.
| |
− |
| |
− | ====Jak wykonać zrzut ekranu w Raspbian?====
| |
− |
| |
− | Najpierw musimy zainstalować narzędzie scrot przeznaczone do tego celu:
| |
− |
| |
− | <source lang = 'bash'>
| |
− | sudo apt-get install scrot
| |
− | </source>
| |
− |
| |
− | A potem wystarczy je wywołać z linii poleceń w terminalu:
| |
− |
| |
− | <source lang = 'bash'>
| |
− | scrot
| |
− | </source>
| |
− | Zrzut ekranu zostanie zapisany w folderze, w którym aktualnie się znajdujemy. Jeżeli nie chcemy mieć na zrzucie ekranu widocznego okna terminalu możemy zrobić zrzut z zadanym opóźnieniem i zminimalizować w tym czasie terminal:
| |
− |
| |
− | <source lang = 'bash'>
| |
− | scrot -d 10
| |
− | </source>
| |
− | -->
| |
− |
| |
− | <!--
| |
− | ==Okulograf ==
| |
− |
| |
− | ===1. Analiza obrazu===
| |
− | * Wstęp o analizie obrazu - analizie kilkuwymiarowego sygnału
| |
− | ** przykłady wykorzystania analizy obrazu: qr codes, kody kreskowe, OCR, okulografia, AR, Microsoft HoloLens
| |
− | ** przedstawienie obrazu jako macierzy
| |
− | ** rgb, rgbA, hsv
| |
− | ** obraz z kamery
| |
− | ** OpenCV
| |
− | * Zadania:
| |
− | ** podłączyć suwaki OpenCV pod każdy z kanałów B, G, R
| |
− | <source lang="Python">
| |
− | import cv2
| |
− |
| |
− | def nothing(x):
| |
− | pass
| |
− |
| |
− | cam = cv2.VideoCapture(0)
| |
− |
| |
− | cv2.namedWindow("window")
| |
− |
| |
− | cv2.createTrackbar("name", "window", 0, 255, nothing)
| |
− |
| |
− | while True:
| |
− | frame = cam.read()[1]
| |
− |
| |
− | track_pos = cv2.getTrackbarPos("name", "window")
| |
− |
| |
− | cv2.imshow("window", frame)
| |
− | key = cv2.waitKey(10) & 0xFF
| |
− | if key == 27 or key == ord('q'):
| |
− | break
| |
− |
| |
− | cam.release()
| |
− | cv2.destroyAllWindows()
| |
− |
| |
− |
| |
− | </source>
| |
− | ** przekonwetować obraz BGR do skali szarości
| |
− | ** narysować histogram
| |
− | *** najłatwiej skorzystać z Matplotlib
| |
− | *** dla obrazu z kamery należy skorzystać z opci "ion" w matplotlib, aby móc rysować na bieżąco
| |
− | *** należy skorzystać z funkcji cv2.calcHist - [http://docs.opencv.org/modules/imgproc/doc/histograms.html?highlight=cv2.calchist#cv2.calcHist]
| |
− | *** wyrównać histogram - [http://pl.wikipedia.org/wiki/Wyr%C3%B3wnanie_histogramu]
| |
− | ** zaimplementować własny filtr
| |
− | ** wykrywanie danego obiektu po kolorze - konwersja na hsv - [http://opencv-python-tutroals.readthedocs.org/en/latest/py_tutorials/py_imgproc/py_colorspaces/py_colorspaces.html#object-tracking]
| |
− | ** dorysowanie obiektu na obrazie poruszającego się razem z wykrytym obiektem
| |
− | *** np. kółko - [http://docs.opencv.org/modules/core/doc/drawing_functions.html#circle]
| |
− |
| |
− | ===2. Okulografia===
| |
− | * Wstęp teoretyczny
| |
− | ** Co to są okulografy, jak działają i komu mogą pomóc.
| |
− | ** Dlaczego potrzebna jest korekcja ruchu głowy.
| |
− | ** Dlaczego obsługa interfejsu okulografem jest trudna - rozwiązania od Tobii i wykrywania ruchu głowy jako alternatywa.
| |
− | ** Eviacam - duzy projekt wykorzystujący bibliotekę OpenCV do wykrywania głowy i obsługi myszki
| |
− | * Ergonomia oraz badanie
| |
− | ** Obsługa okulografu na kiju i Tobii
| |
− | ** Obsługa aplikacji do pisania i aplikacji do rysowania z projektu PISAK za pomocą okulografów oraz Eviacam-a(ruchy głową)
| |
− | ** Ankieta ergonomiczności - używanie Tobii, używanie eyetracker-a na kiju, używanie Eviacam-a
| |
− |
| |
− | ===Zadanie dodatkowe dla chętnych===
| |
− | Zaprojektowanie interfejsu do obsługi okulografem w oparciu o engine PISAKa
| |
− |
| |
− | * Projektowanie interfejsu w PISAKu:
| |
− | ** widgets - moduły funkcjonalne PISAKa
| |
− | ** handlers - funkcje podłączane do przycisku
| |
− | ** jsony - składanie różnych modułów funkcjonalnych w jeden interfejs
| |
− | ** css-y - edycja wyglądu interfejsu
| |
− | * stworzenie własnego/zmodyfikowanie istniejącego interfejsu z myślą o obsłudze okulografem
| |
− | * praca nad własnym interfejsem
| |
− | * porównanie interfejsów
| |
− | -->
| |