refactor: change task

This commit is contained in:
diana-tym 2024-03-13 15:14:48 +02:00
parent 0c5954f96c
commit b8db2fe6ee
2 changed files with 14 additions and 167 deletions

View File

@ -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.
Для позначення нерівностей на дорозі також використовувати маркери. Зображення для маркерів можна знайти в папці 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)

View File

@ -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):
"""