Zapewne wielu z Was słyszało bądź choć raz w życiu korzystało z oprogramowania do automatycznego generowania kodu. Dobrym przykładem jest branża automotive, w której na porządku dziennym używa się takich narzędzi jak DaVinci czy też EB Tresos.
Innym przykładem oprogramowania automatycznie generującego kod jest CubeMX firmy STMicroelectronics. Jest to darmowe narzędzie do zastosowań komercyjnych, które pozwala na wygenerowaniu kodu odpowiedzialnego za obsługę komponentów hardwarowych.
W tym artykule skupimy się na narzędziach, które pozwalają generować kod na podstawie modelu.
Na początek – czym są Matlab i Simulink?
Matlab to nie tylko program komputerowy – to zaawansowana platforma do wykonywania obliczeń naukowych i inżynierskich, umożliwiająca tworzenie symulacji komputerowych. Ciężko wymienić wszystkie możliwe zastosowania Matlaba, ale możemy go użyć m.in. do:
- analizy danych,
- wizualizacji i eksploracji danych,
- programowania,
- symulacji sprzętowych,
- obliczeń równoległych (wspiera wykonywanie obliczeń i symulacji z wykorzystaniem GPU).
Jednym z głównych elementów Matlaba jest narzędzie Simulink, będące platformą do wielodomenowej symulacji i projektowania systemów dynamicznych z wykorzystaniem modeli. Stanowi interaktywne środowisko graficzne oraz zbiór bibliotek konfigurowalnych bloków.
Po co generować kod z modelu?
Do głównych zalet automatycznego generowania kodu możemy zaliczyć:
- uproszczenie procesu projektowania oprogramowania,
- współpraca interdyscyplinarna w projekcie celem szybszego rozwoju oprogramowania,
- łatwiejsza certyfikacja kodu generowanego w oparciu o sprawdzony i ceniony generator,
- możliwość pracy w oparciu o model, kiedy hardware nie jest jeszcze gotowy.
Uproszczenie procesu projektowania oprogramowania
Procesy tworzenia oprogramowania są odpowiedzialne za stworzenie jednego lub wielu poziomów wymagań systemowych (dobrym przykładem jest V-model stosowany w branży Automotive). Wymagania wysokiego poziomu produkowane są bezpośrednio na podstawie analizy wymagań systemowych i architektury systemu. Są one rozwijane w procesie projektowania oprogramowania, tworząc w ten sposób powiązane ze sobą wymagania niższego poziomu.
Jednakże, gdy kod źródłowy generowany jest bezpośrednio na podstawie wymagań wysokopoziomowych, wówczas wymagania te odpowiadają również wymaganiom niskopoziomowym i mają do nich zastosowanie zalecenia dotyczące wymagań niskiego poziomu.
Współpraca interdyscyplinarna w projekcie celem szybszego rozwoju oprogramowania
Inżynierowie posiadający umiejętności tworzenia modeli sterujących nie muszą mieć dużej wiedzy programistycznej, żeby móc wygenerować i przetestować model na rzeczywistym obiekcie sterującym.
Łatwiejsza certyfikacja kodu generowanego w oparciu o sprawdzony i ceniony generator
Rozwój systemów o wysokiej integralności w przemyśle motoryzacyjnym charakteryzuje się wykazaniem zgodności z ISO® 26262, międzynarodowym standardem bezpieczeństwa funkcjonalnego pojazdów drogowych. ISO 26262 klasyfikuje funkcje na poziomach nienaruszalności bezpieczeństwa motoryzacyjnego (ASIL) od A do D – czyli od najmniej do najbardziej rygorystycznego.
Producenci OEM i dostawcy Tier-1 dostosowują swoje procesy rozwoju ECU do projektowania opartego na modelach zgodnie z normą ISO 26262. MATLAB, Simulink, Stateflow, Embedded Coder, narzędzia do weryfikacji MATLAB i Simulink oraz narzędzia do weryfikacji kodu Polyspace® są certyfikowane przez TÜV SÜD jako narzędzia kwalifikowane zgodnie z ISO 26262 dla ASIL A-D.
Kwalifikacje opierają się na zautomatyzowanym, specyficznym dla aplikacji procesie weryfikacji. Obsługują testowanie modelu i kodu w trybie back-to-back, zgodnie z zaleceniami normy ISO 26262-6 dla ASIL C i D, przy użyciu trybu symulacji procesora w pętli (PIL) w Simulink. W ten sposób inżynierowie mogą wykorzystać optymalizacje kodera i kompilatora, w tym kod specyficzny dla procesora generowany przez Embedded Coder, do tworzenia szybkiego i wydajnego pamięciowo oprogramowania potrzebnego do masowej produkcji ECU.
Możliwość pracy w oparciu o model, kiedy hardware nie jest jeszcze gotowy
- Symulacja oprogramowania w pętli (ang. Software-In-the-Loop) kompiluje wygenerowany kod źródłowy i wykonuje go jako oddzielny proces na komputerze hosta. Porównując wyniki symulacji normalnej i SIL, można przetestować numeryczną równoważność modelu i wygenerowanego kodu. Podczas symulacji SIL da się zbierać metryki pokrycia kodu i czasu wykonania dla wygenerowanego kodu.
- Symulacja procesora w pętli (ang. Processor-In-the-Loop) kompiluje wygenerowany kod źródłowy, a następnie pobiera i uruchamia kod obiektowy na docelowym sprzęcie. Porównując wyniki symulacji normalnej i PIL, można przetestować równoważność numeryczną modelu i wygenerowanego kodu. Podczas symulacji PIL da się zbierać metryki pokrycia kodu i czasu wykonania dla wygenerowanego kodu.
Wady automatycznej generacji kodu
Automatyczna generacja kodu nie jest też pozbawiona wad. Należą do nich:
- Jakość kodu generowanego na podstawie modelu zależy od interpretacji wymagań wysokiego poziomu. Ponadto, w normalnym procesie pewne nieścisłości mogą być wykryte na etapie tworzenia wymagań niskiego poziomu. W przypadku użycia modelu weryfikacja może być trudniejsza.
- Integracja generowanego kodu może być utrudniona ze względu na jego nieprzejrzystość i stopień skomplikowania. Używając kodu generowanego, należy pamiętać o zarezerwowaniu czasu potrzebnego na jego ewentualne dostosowanie do bardziej przyjaznej dla programisty formy.
- Generowany kod wymaga przejścia procesu przeglądu kodu (ang. Review proces) pod względem wydajności i zajętości zasobów. Może to być utrudnione i wymagać dodatkowego czasu, aby zrozumieć wygenerowany automatycznie kod.
Nic tak nie zaciemnia sytuacji jak prosty przykład
W celu prezentacji możliwości generowania kodu w Matlab Simulink zdecydowałem się stworzyć przykładowy model, a następnie krok po kroku przedstawić jak wygenerować kod.
Na co dzień pracuję w branży Automotive, ale ze względu na odbyte studia temat lotnictwa jest mi szczególnie drogi. Jednym z istotnych systemów, które znajdą się na pokładzie współczesnego samolotu, jest autopilot kursu umożliwiający lot w zadanym kierunku. Dlatego postanowiłem zbudować w Simulinku uproszczony model autopilota kursu dla UAV (bezzałogowy statek powietrzny) umożliwiający zarówno zadanie kursu jak i kąta przechylenia.
Wykonanie pełnego modelu autopilota zajęłoby dużo czasu, dlatego wybrałem tylko część logiki, żeby zaprezentować działanie oprogramowania do generacji kodu. Założenia przy tworzeniu modelu:
- Mamy do czynienia z modelem samolotu wykonującym zakręt poprzez przechylenie modelu na jedno ze skrzydeł.
- Sterujemy tylko wychyleniem lotek – oznaczanym dalej dA – ze względu na uproszczony model, interesuje nas samo wygenerowanie kodu, a nie poprawne sterowanie.
Żeby zacząć tworzyć model, należy uruchomić program Matlab a następnie wybrać New => Simulink Model – jak pokazano na Ryc. 1:
Otwiera się nam wówczas puste okno nowego modelu. Najprościej je uzupełnić, wstawiając gotowe elementy z wykorzystaniem opcji Library browser – jak widać na Ryc. 2.
Dostępna w Simunlinku biblioteka jest dość rozbudowana i jej ładowanie może zająć do kilku minut. Elementy biblioteczne są posegregowane w tematyczne grupy – jak widać na Ryc. 3.
Elementy biblioteki można umieści w modelu, przeciągając je z okna biblioteki do okna modelu. Mają one na swoim obrysie zaznaczone czarnymi strzałkami wejścia i wyjścia. Połączenie następuje przez przeciągnięcie kursorem myszy od wyjścia jednego elementu do wejścia drugiego z wciśniętym lewym przyciskiem myszy. Jeśli jednak dwa elementy znajdują na modelu na jednej linii, program sam zaproponuje połączenie słabo widoczną niebieską strzałką – jak widać na Ryc. 4. Żeby użyć proponowanego połączenia, wystarczy ją (strzałkę) kliknąć lewym przyciskiem myszy.
Podwójne kliknięcie lewym przyciskiem myszy pozwala dokonać dalszych ustawień elementu – jak widać na Ryc. 5.
Na Ryc. 6 znajduje się skończony model uproszczonego autopilota kursu:
Jak widać na Ryc. 6, autopilot ma dostępnych 5 sygnałów wejściowych:
- Mode – tryb pracy,
- Psi_set – zadany kurs,
- Psi_measured – aktualnie zmierzony kurs,
- Phi_set – zadany kąt przechylenia,
- Phi_measured – aktualnie zmierzony kąt przechylenia.
Autopilot ma dostępny 1 sygnał wyjściowy:
- dA – wychylenie lotek.
Kiedy mamy skończony model, możemy przejść do generacji kodu. Żeby to zrobić, należy najpierw ustawić żądane opcje. Ryc. 7 prezentuje widok okna Simulink przy wybieraniu zakładki opcji generacji kodu.
W zakładce opcji generacji kodu należy wybrać Coder i język – jak widać na Ryc. 7. Pozostałe opcje nie są na ten moment potrzebne.
Następnie, rozpoczynamy proces generacji. Poniżej na Ryc. 9 widoczne jest okno Simulink podczas uruchamiania generatora:
Narzędzie przeprowadza użytkownika krok po kroku, aż do osiągnięcia sukcesu bądź raportu błędów. Pierwszą na drodze do generacji jest zakładka powitalna Ryc. 10.
W zakładce „System” generatora widocznej na Ryc. 11 możemy wybrać jako źródło dla procesu cały model bądź subsytem w przypadku większego, bardziej złożonego modelu:
W zakładce Output widocznej na Ryc. 11 jeszcze raz jesteśmy pytani o język generowanego kodu:
Następne dwie grafiki Ryc. 13 i Ryc. 14 przedstawiają analizę, którą przeprowadza program przed generacją:
Kolejna zakładka zaprezentowana na Ryc. 15 dotyczy rozmiaru użytych zmiennych. Możemy w niej również wybrać architekturę docelowego procesora, na którym miałby działać wygenerowany kod, w moim przypadku ARM Cortex:
W zakładce Optimization możemy wybrać, pod jakim kątem ma być optymalizowany generowany kod.
W ostatniej dostępnej zakładce przedstawionej na Ryc. 17 znajdziemy podsumowanie wybranych ustawień:
Po zakończonej generacji kodu przechodzimy do widoku końcowego, skąd możliwe jest wyświetlenie raportu końcowego, co zostało zaprezentowane na Ryc. 18
W raporcie znajdziemy informacje o zadanych ustawieniach, wygenerowanych plikach czy opis zmiennych, co widać na zrzutach z programu – Ryc. 19 i Ryc. 20.
Sam kod będzie zawierał nazwy użyte w modelu dla łatwiejszej integracji, co przedstawia Ryc. 20.
Pliki powstałe w wyniku generacji kodu zostaną utworzone w folderze, w którym stworzyliśmy model. Warto pamiętać o tym, że Coder użyje nazw użytych w modelu. Jeśli jasno i szczegółowo opiszemy model, nie tylko wejścia i wyjścia, ale użyte elementy biblioteczne i sygnały, ułatwi to odnalezienie się w plikach wyjściowych.
Wygenerowany kod:
- może być porównany w symulacji z utworzonym modelem,
- może być edytowany „ręcznie”,
- wymaga review pod względem wydajności,
- może wymagać refaktoryzacji dla ułatwienia integracji i zrozumienia.
Po osiągnięciu celu, kiedy uzyskamy pliki źródłowe, możemy przystąpić do integracji kodu bądź/i symulacji SIL/PIL.
Podsumowanie
Celem artykułu było wprowadzenie czytelnika w tematykę oprogramowanie do automatycznego generowania kodu i zachęcenie do samodzielnego pogłębiania wiedzy. Simulink jest bardzo rozbudowanym narzędziem, które dostarcza sporo gotowych bibliotek, począwszy od transformacji sygnałów, przez filtrację, aż po biblioteki atmosfery, zjawisk pogodowych, dynamiki obiektów i narzędzi dla systemów czasu rzeczywistego. Ponadto, z każdą kolejną wersją dokładane są nowe funkcjonalności i biblioteki.
Parafrazując Bilbo Baginnsa – połowy z nich nie poznałem, a mniej niż połowę chciałbym znać, choć w połowie tak dobrze, jak na to zasługują. Matlab jest płatnym narzędziem komercyjnym, ale dostępne są 30-dniowe wersje darmowe lub licencje studenckie. Firma MathWorks oferuje też niższe ceny na produkty do użytku domowego w stosunku do cen dla firm oraz pełną dowolność przy dostosowywaniu pakietu.
Bibliografia
***
Jeśli artykuł Cię zainteresował, zajrzyj również koniecznie do innych tekstów przygotowanych przez naszych ekspertów Embedded.
Zostaw komentarz