From b8db2fe6ee86cc5ae9463d6b64ece1e570a3f06d Mon Sep 17 00:00:00 2001 From: diana-tym Date: Wed, 13 Mar 2024 15:14:48 +0200 Subject: [PATCH] refactor: change task --- MapView/README.md | 175 ++++------------------------------------------ MapView/main.py | 6 +- 2 files changed, 14 insertions(+), 167 deletions(-) diff --git a/MapView/README.md b/MapView/README.md index 9541b99..327c046 100644 --- a/MapView/README.md +++ b/MapView/README.md @@ -9,12 +9,7 @@ ### Підготовка робочого середовище, встановлення проекту -Клонування репозиторію -``` -git clone git@git.comsys.kpi.ua:Diana_Tymoshenko/MapView.git -cd MapView -``` -Створення віртуального середовища. Пакет virtualenv повинен бути встановлений в системі! +Створення віртуального середовища `python -m venv ./venv` @@ -28,49 +23,28 @@ cd MapView Встановлення необхідних бібліотек -`pip install kivy mapview` +`pip install -r requirements.txt` ### Завдання -Для початку необхідно отримати дані з датчиків: дані акселерометра знаходяться в файлі data.csv, -GPS дані можна згенерувати за допомогою цього [ресурсу](https://www.nmeagen.org/) та записати їх у csv файл. - Для відображення мапи використовується віджет [Mapview](https://mapview.readthedocs.io/en/1.0.4/) для Kivy. -Для візуалізації руху машини можна використовувати MapMarker та рухати його відповідно GPS даних. - -Для визначення стану дорожнього покриття потрібно накопичити певну кількість показників акселерометра (наприклад, 100) та -проаналізувати їх певним чином на нерівності дороги (наприклад, великі та маленькі ями, бордюр). -Для їх позначення на дорозі також використовувати маркери. Зображення для маркерів можна знайти в папці images. +Для візуалізації руху машини можна використовувати MapMarker та рухати його відповідно GPS даних. +Для позначення нерівностей на дорозі також використовувати маркери. Зображення для маркерів можна знайти в папці images. Для створення та редагування маршруту машини на мапі використовуйте клас LineMapLayer та функцію -`add_point()` з файлу lineMapLayer.py. Для додавання лінії на мапу – `mapview.add_layer()` з `mode="scatter"`. +`add_point()` з файлу lineMapLayer.py. Додавання лінії на мапу: -Щоб створити затримку у відображення руху машини можна використовувати -функцію `kivy.clock.Clock.schedule_once()`. +```python +map_layer = LineMapLayer() +mapview.add_layer(map_layer, mode="scatter") +``` -### Аналіз даних акселерометра +Щоб створити затримку при відображенні руху машини можна використовувати +функцію `kivy.clock.Clock.schedule_once()` або `kivy.clock.Clock.schedule_interval()`. -Будемо використовувати дані тільки по осі z. В стані спокою значення по осі z становить -приблизно 16667 одиниць (або 1 g = 9.8 м/с²) (1 од = 0.00006 g). - -Для аналізу нерівностей дороги можна використати функцію `scipy.signal.find_peaks()`, що -знаходить локальні максимуми (піки) вхідних даних. Локальні максимуми вказують на наявність -бордюрів або лежачих поліцейських, локальні мінімуми - на ями. - -Для налаштування алгоритму знаходження максимумів використовуються такі параметри: -- `height`: мінімальна висота піків. -- `distance`: мінімальна відстань між піками. -- `prominence`: мінімальна висота піку відносно його сусідів (помітність піку). -- `width`: мінімальна ширина піку. - -Важливо підібрати оптимальні параметри, щоб відсіяти шум та залишити тільки ті піки, що дійсно відображають -якість дорожнього покриття. Для більшої наочності при підбиранні параметрів можна показники акселерометра та -результати аналізу відобразити на графіку. - -Для знаходження мінімуму треба відзеркалити дані (помножити на -1) та вказати негативне значення висоти. - -За бажанням можна використовувати будь-який інший спосіб аналізу показників акселерометра. +Дані для відображення на мапі (координати та стан дороги) зчитуються з бази даних через вебсокет. +Для їх отримання використовуйте функцію `get_new_points()` з datasource.py. **Шаблон основного файлу проєкту** @@ -96,12 +70,6 @@ class MapViewApp(App): Викликається регулярно для оновлення мапи """ - def check_road_quality(self): - """ - Аналізує дані акселерометра для подальшого визначення - та відображення ям та лежачих поліцейських - """ - def update_car_marker(self, point): """ Оновлює відображення маркера машини на мапі @@ -132,120 +100,3 @@ class MapViewApp(App): if __name__ == '__main__': MapViewApp().run() ``` - -### Ідеї для підвищення оцінки - -Замість читання GPS координат з файлу можна використати утиліту Linux `gpsfake`. - -`gpsd` — це програма, яка збирає дані з приймача GPS і надає дані через мережу -потенційно декільком клієнтським програмам. Gpsd можна запускати як фонове завдання. -gpsd надає сервіс шляхом прив'язки до порту 2947 за замовчуванням. - -Але оскільки в нас немає приймача GPS, його роботу імітує `gpsfake`. -Він відкриває PTY (псевдо-TTY), запускає екземпляр gpsd, який вважає, -що підлегла сторона PTY є його пристроєм GPS, і передає вміст -одного або кількох тестових файлів з координатами до приймача GPS. - -**Встановлення пакетів**: - -`sudo apt install gpsd-clients` - -Щоб додати ці пакети у віртуальне середовище, відкрийте файл конфігурації -`venv/pyvenv.cfg` та змініть рядок - -`include-system-site-packages = true` - -В програмі треба додати рядок - -`import gps` - -**Використання gpsfake** - -Команда `gpsfake` запускається в терміналі, але при бажанні можна викликати її із програми -за допомогою модулю `subprocess`. - -`gpsfake [OPTIONS] logfile` - -Опції, які можуть знадобитись: -- `-P port`: встановлює порт прослуховування. -- `-c sec`: встановлює затримку між реченнями в секундах. За замовчуванням дорівнює нулю (без затримки). -- `-1`: logfile інтерпретується лише один раз, а не зациклюється. - -`logfile` - це файл, що містить коодринати в будь-якому підтримуваному форматі, включаючи, -зокрема, NMEA, SiRF, TSIP або Zodiac. Зокрема за допомогою цього [ресурсу](https://www.nmeagen.org/) -можна також згенерувати NMEA файл. - -**Використання gpsd** - -gpsd використовує JSON для зв’язку зі своїми клієнтами. Відповіді містять класи, а їх імена відповідають -типу повідомлення NMEA. Важливо зазначити, що ці об’єкти JSON можуть бути неповними, -якщо значення не визначено. Це може статися, коли GPS-приймач ще не отримав координати. -У такому випадку поле просто опускається. Ви можете знайти повний список команд і більш -детальний опис [тут](https://gpsd.gitlab.io/gpsd/gpsd_json.html). - -Більше про gpsd, його методи та приклади використання можна дізнатися [тут](https://gpsd.io/client-howto.html). - -Треба зазначити, що запускати gpsd треба в окремому потоці, бо він не може працювати в одному -циклі подій Kivy. - -Нижче наведений приклад коду для використання gpsd. - -```python -import gps -import threading - -class GpsPoller(threading.Thread): - def __init__(self): - threading.Thread.__init__(self) - self.gpsd_client = gps.gps(port=port, mode=gps.WATCH_ENABLE) # вказати потрібний порт - self.current_gps = None # поточні координати - self.running = True - - def get_gps_data(self): - return self.current_gps - - def run(self): - while self.running: - response = self.gpsd_client.next() - print('response:', response) - if response['class'] == 'DEVICE': - is_activated = getattr(response, 'activated') - if is_activated == 0: # коли logfile з координатами був повністю прочитаний - self.running = False - return - - if response['class'] == 'TPV' and hasattr(response, 'lat'): - print("Your position: lat = " + str(response.lat) + ", lon = " + str(response.lon)) - self.current_gps = [response.lat, response.lon] -``` - -Для роботи з цим класом треба створити його екземпляр в основному класі програми та розпочати діяльність потоку -за допомогою методу `start()`, який викликає метод `run()`. Для отримання координат використовувати метод `get_gps_data()`. - -Зверніть увагу, що перші координати надходять не одразу, тож слідкуйте за тим, яку затримку -треба поставити, щоб перша відповідь містила поля lat та lon. Також якщо при виклику команди `gpsfake` -ви використовуєте затримку між реченнями в 1 секунду, то між кожним зчитуванням координат від gpsd -треба поставити затримку в 3 секунди, бо для однієї пари координат використовується 3 речення -з logfile. - -Якщо при запуску програми виникає така помилка: -``` -gpsd:ERROR: SER: device open of /dev/pts/4 failed: Permission denied - retrying read-only -gpsd:ERROR: SER: read-only device open of /dev/pts/4 failed: Permission denied -gpsd:ERROR: /dev/pts/4: device activation failed, freeing device. -``` -Треба змінити режим профілю безпеки AppArmor для gpsd з режиму enforced на режим complain: -``` -sudo apt install apparmor-utils -sudo aa-complain /usr/sbin/gpsd -sudo apparmor-status # для перевірки режиму -``` - -### Корисні посилання: - -- [Kivy](https://kivy.org/doc/stable/) -- [Mapview](https://mapview.readthedocs.io/en/1.0.4/) -- [scipy.signal.find_peaks](https://docs.scipy.org/doc/scipy/reference/generated/scipy.signal.find_peaks.html) -- [gpsfake](https://gpsd.gitlab.io/gpsd/gpsfake.html) -- [gpsd](https://gpsd.io/gpsd.html) -- [threading](https://docs.python.org/uk/3/library/threading.html) \ No newline at end of file diff --git a/MapView/main.py b/MapView/main.py index c238059..1445092 100644 --- a/MapView/main.py +++ b/MapView/main.py @@ -3,6 +3,7 @@ from kivy.app import App from kivy_garden.mapview import MapMarker, MapView from kivy.clock import Clock from lineMapLayer import LineMapLayer +from datasource import Datasource class MapViewApp(App): @@ -20,11 +21,6 @@ class MapViewApp(App): Викликається регулярно для оновлення мапи """ - def check_road_quality(self): - """ - Аналізує дані акселерометра для подальшого визначення - та відображення ям та лежачих поліцейських - """ def update_car_marker(self, point): """