Menu

andipanda.dev

CaRadio: jak dostosowałem sterowanie dotykowe CarPlay

W poprzednim artykule opisałem, jak eksperymentowałem z FastCarPlay i LIVI, a następnie zmodyfikowałem procedurę inicjalizacji Carlinkit, aby uzyskać stabilne połączenie z telefonem.

Jednak pomyślne połączenie z CarPlay to tylko część zadania. Aby korzystać z systemu w samochodzie, potrzebne jest również wygodne sterowanie.

W moim przypadku podstawowym urządzeniem wejściowym był ekran dotykowy. I właśnie jego obsługą musiałem zająć się na kolejnym etapie rozwoju projektu.

Pierwsze eksperymenty ze sterowaniem dotykowym

FastCarPlay miał już obsługę wprowadzania danych za pomocą dotyku. Jednak w swojej pierwotnej postaci projekt był w dużej mierze nastawiony na sterowanie klawiaturą.

Do tworzenia oprogramowania i testowania działania CarPlay jest to całkiem odpowiednie rozwiązanie. Ja jednak chciałem zbudować pełnoprawne radio samochodowe, którym można sterować bezpośrednio przez ekran, bez klawiatury i myszy.

Podczas pierwszych eksperymentów napotkałem niestabilne działanie sterowania dotykowego na moim sprzęcie.

O ile dobrze pamiętam, po kilku dotknięciach lub próbie przesunięcia palcem CarPlay przestawał reagować na dotyk. Sama aplikacja nadal jednak działała.

Dziś nie potrafię już dokładnie powiedzieć, co powodowało takie zachowanie. Być może problem był związany ze specyfiką mojej konfiguracji, sprzętem lub obsługą zdarzeń wejściowych.

Dlatego wyciąganie wniosków na temat przyczyn problemu w oryginalnym projekcie byłoby niewłaściwe.

Poza tym i tak zamierzałem stworzyć własny interfejs radia, więc prędzej czy później musiałbym dostosować obsługę sterowania do CaRadio.

Od klawiatury do ekranu dotykowego

FastCarPlay korzystał z SDL — biblioteki, którą zacząłem poznawać po powrocie do projektu.

Jedną z jej zalet jest możliwość odbierania zdarzeń z różnych urządzeń wejściowych i obsługiwania ich bezpośrednio w aplikacji.

W przypadku mojego radia było to wygodne.

Podczas pracy nad oprogramowaniem na komputerze mogłem korzystać z myszy, a na Raspberry Pi z ekranu dotykowego. Jednocześnie główna logika sterowania mogła pozostać wspólna.

Jednak w przypadku CarPlay nie wystarczy samo wykrycie, że użytkownik dotknął wyświetlacza.

Trzeba wiedzieć, gdzie dokładnie nastąpiło dotknięcie, kiedy palec zetknął się z ekranem, czy się poruszał i w którym momencie został oderwany.

Wszystkie te działania należy przekształcić w polecenia zrozumiałe dla systemu CarPlay.

Dotknięcia, ruchy i gesty przesuwania

Sterowanie dotykowe nie ogranicza się do pojedynczych dotknięć.

Na przykład, aby otworzyć aplikację, wystarczy dotknąć odpowiedniej ikony. Natomiast przewijanie listy lub przesuwanie mapy wymaga już obsługi ruchu palca.

Dlatego w CaRadio przewidziałem obsługę kilku rodzajów zdarzeń: rozpoczęcia dotknięcia, ruchu i oderwania palca od ekranu.

W przypadku zwykłego dotknięcia aplikacja otrzymuje współrzędne punktu, w którym użytkownik dotknął ekranu, i przekazuje odpowiednie zdarzenie dalej.

Podczas przesuwania palca trzeba przekazywać zmiany współrzędnych, aby CarPlay mógł reagować na gest.

Gdy palec zostaje oderwany od wyświetlacza, wysyłane jest zdarzenie zakończenia dotknięcia.

Na pierwszy rzut oka wszystko wydaje się dość proste. Jednak dla prawidłowego działania ważne jest zachowanie właściwej kolejności zdarzeń i oddzielenie ich od sterowania własnym interfejsem radia.

Zachowałem również możliwość korzystania z myszy. Jest to przydatne podczas tworzenia i testowania aplikacji bez podłączonego ekranu dotykowego.

Współrzędne ekranu i CarPlay

Kolejnym zadaniem było prawidłowe przekazywanie współrzędnych dotknięć.

Wyświetlacz radia ma własną rozdzielczość, natomiast obraz CarPlay jest obsługiwany w osobnym układzie współrzędnych.

Jeśli współrzędne ekranu dotykowego zostaną przekazane bez przeliczenia, dotknięcie może trafić w inne miejsce, niż oczekuje użytkownik.

Dlatego w CaRadio współrzędne są przeliczane z uwzględnieniem rozmiaru okna aplikacji i skali obrazu CarPlay.

Pozwala to oddzielić fizyczną rozdzielczość wyświetlacza od współrzędnych wykorzystywanych do sterowania.

Takie podejście jest szczególnie przydatne podczas tworzenia oprogramowania, gdy aplikacja może działać w oknie o innych wymiarach niż ekran radia samochodowego.

Jak wrócić z CarPlay do CaRadio

Kiedy CarPlay zajmuje cały ekran, pojawia się kolejne pytanie: jak wrócić do własnego interfejsu radia?

Można byłoby wykorzystać osobny fizyczny przycisk. Chciałem jednak, aby podstawowe funkcje były dostępne bezpośrednio z ekranu dotykowego.

Dlatego przewidziałem specjalny obszar w lewym górnym rogu wyświetlacza.

Gdy użytkownik dotknie tego obszaru, zdarzenie jest obsługiwane przez samo CaRadio i nie jest przekazywane do CarPlay jako zwykłe dotknięcie.

Następnie można otworzyć ekran główny radia i uzyskać dostęp do pozostałych funkcji aplikacji.

Jednocześnie pozostała część ekranu nadal służy do sterowania CarPlay.

W ten sposób jedno urządzenie wejściowe realizuje dwa różne zadania: sterowanie telefonem przez CarPlay oraz sterowanie samym radiem.

Dlaczego postanowiłem zrobić to samodzielnie

Moim celem nie było całkowite przepisanie sterowania FastCarPlay ani udowodnienie, że pierwotna implementacja była nieprawidłowa.

Potrzebowałem rozwiązania dostosowanego do konkretnej konstrukcji CaRadio.

Chciałem samodzielnie kontrolować obsługę zdarzeń, wiedzieć, dokąd trafia każde dotknięcie, i mieć możliwość dodawania własnych elementów sterujących.

Ponadto takie podejście dobrze odpowiada mojej ogólnej zasadzie tworzenia oprogramowania: w miarę możliwości stosować proste i zrozumiałe rozwiązania bez zbędnych warstw programowych.

Oczywiście samodzielna implementacja również wymaga czasu na debugowanie.

W rezultacie uzyskałem jednak sterowanie, które mogę rozwijać razem z pozostałymi funkcjami radia, bez ograniczania się do możliwości pierwotnego interfejsu.

Kilka słów o FastCarPlay

W tym miejscu chciałbym osobno podziękować autorowi FastCarPlay.

To właśnie dzięki jego pracy udało mi się wrócić do pomysłu zbudowania własnego radia z CarPlay i doprowadzić go do etapu, na którym korzystam z niego w samochodzie.

Gdyby nie ten projekt, całkiem możliwe, że nadal szukałbym odpowiedniego rozwiązania albo całkowicie zrezygnował ze swojego pomysłu.

Dlatego opisane zmiany nie są próbą uczynienia FastCarPlay „bardziej poprawnym” czy „lepszym”. Po prostu dostosowałem istniejącą implementację do własnego sprzętu i potrzeb.

Projekty open source są cenne właśnie dlatego, że pozwalają nie zaczynać za każdym razem od zera, lecz poznawać gotowe rozwiązania i rozwijać je we własnym kierunku.

Podsumowanie

W rezultacie sterowanie dotykowe stało się integralną częścią CaRadio, a nie tylko dodatkową możliwością interakcji z CarPlay.

Teraz aplikacja może obsługiwać dotknięcia i ruchy palca, przeliczać współrzędne na potrzeby obrazu CarPlay oraz oddzielać sterowanie telefonem od sterowania samym radiem.

Dla mnie był to kolejny krok od eksperymentalnego uruchomienia CarPlay na Raspberry Pi do systemu, z którego naprawdę wygodnie korzysta się w samochodzie.

Jednak obraz i sterowanie to tylko część systemu multimedialnego.

Osobnym zadaniem okazała się obsługa dźwięku: jego odbieranie, odtwarzanie i integracja z pozostałymi funkcjami radia.

O tym opowiem w następnym artykule.