Autor Wątek:  Projekt Lua, czyli automatyzacja scenerii  (Przeczytany 8973 razy)

0 użytkowników i 1 Gość przegląda ten wątek.

Offline jakubg1

  • Deweloper
  • Wiadomości: 1147
  • MaSzyna ma szynę, szyna ma MaSzynę - na kołach.
    • Zobacz profil
  • Otrzymane polubienia: 602
Projekt Lua, czyli automatyzacja scenerii
« dnia: 31 Stycznia 2018, 18:39:23 »
Cześć. Jakieś kilka miesięcy temu rozpocząłem z ciekawości (i namowy innych osób) pisanie scenariuszy w języku Lua. Lubię kodować, więc takie rozwiązanie przypadło mi do gustu. I zrobiłem taki mały scenariusz - td_mijanka.scn. Jest to przerobiony w niewielkim stopniu Tor Doświadczalny z małym scenariuszem - mijanką pociągu osobowego z towarowym.
Kod podzielony jest na dwie części, jedną - kernel - która zawiera kod do przetwarzania informacji oraz wysyłania ich w odpowiedniej formie do symulatora - oraz drugą - kod scenariusza - zawierającą dane o stacjach, przebiegach oraz eventach zależnych od trasy.
Funkcje, które do tej pory zrobiłem:
  • Dynamicznie generowane sygnały semaforów
  • Przebiegi
  • Obsługa odcinków izolowanych
  • Losowanie opóźnienia dyżurnego dla każdej stacji oddzielnie, być może będziemy czekali na wjazd, a być może będzie już podany
  • Własna kolejka eventów z możliwością ich odwołania
Do perfekcji brakuje jeszcze dużo, dużo rzeczy i zdaję sobie sprawę z tego, iż ogarnięcie tego nie jest proste. Docelowo też obsługa tego systemu będzie wspierana w moim generatorze scenerii, w którym zrobię nową scenerię testową, żebym mógł przetestować więcej aspektów (jej schemat naskrobałem w załączniku).

Trzy uwagi na koniec:
  • Warunkiem poprawnego działania scenerii jest posiadanie buildu EXE Miłka, buildy tmj nie obsługują kodu Lua.
  • Wszelkie błędy typu crashe, zapalenia semafora za pociągiem, przerżnięcia S1 itd. proszę zgłaszać tutaj, załączając log.txt oraz screenshot, w przeciwnym wypadku nie będę takich zgłoszeń rozpatrywał!
  • W kodzie jest dużo komentarzy, jeśli ktoś lubi może sobie przejrzeć, choć chyba nikt niczego tam nie zrozumie. :P

Linki do nowych wersji (wypakować do głównego katalogu symulatora):
Wersja 5.0: https://eu07.pl/userfiles/22592/lua_5_0_test1.zip

Linki do starych wersji (wypakować do scenery/):
Wersja 4.0: http://eu07.pl/userfiles/22592/priv-td_mijanka_8.7z
Wersja 3.1: http://eu07.pl/userfiles/22592/priv-td_mijanka_7.7z
Wersja 3.0: http://eu07.pl/userfiles/22592/priv-td_mijanka_6.7z
Wersja 2.0: http://eu07.pl/userfiles/22592/priv-td_mijanka_5.7z
Wersja 1.0: http://eu07.pl/userfiles/22592/priv-td_mijanka_3.7z
« Ostatnia zmiana: 20 Stycznia 2020, 22:59:30 wysłana przez jakubg1 »

Offline pozdze

  • Deweloper
  • Wiadomości: 473
    • Zobacz profil
  • Otrzymane polubienia: 198
Odp: Pisanie scenariuszy w Lua
« Odpowiedź #1 dnia: 01 Lutego 2018, 19:13:23 »
  • Warunkiem poprawnego działania scenerii jest posiadanie buildu EXE Miłka, buildy tmj nie obsługują kodu Lua.

Objaśnij o co chodzi. Co to są builidy?
Łukasz Jachimek

Offline uetam

  • Zasłużony dla Symulatora
  • Wiadomości: 2641
    • Zobacz profil
  • Otrzymane polubienia: 6
Odp: Pisanie scenariuszy w Lua
« Odpowiedź #2 dnia: 01 Lutego 2018, 20:30:34 »
Kompilacje exe.
« Ostatnia zmiana: 02 Lutego 2018, 14:01:00 wysłana przez macius5991 »

Offline jakubg1

  • Deweloper
  • Wiadomości: 1147
  • MaSzyna ma szynę, szyna ma MaSzynę - na kołach.
    • Zobacz profil
  • Otrzymane polubienia: 602
Odp: Pisanie scenariuszy w Lua
« Odpowiedź #3 dnia: 02 Lutego 2018, 14:15:23 »
Wydałem kolejną wersję, która już ma podzielony kod na dwie części - kernel i kod scenariusza. (patrz pierwszy post)
Dlaczego podzieliłem? Kernel jest obowiązkową częścią mojego systemu scenariuszy, a w przypadku znalezienia jakiegoś błędu w nim nie trzeba będzie go poprawiać w każdej scenerii oddzielnie. Jeśli chodzi o kod scenariusza, to wystarczy w scenerii includować (załączać poprzez odnośnik) ten kod, bo każdy kod z kolei includuje kernela. Uwaga, PRZED (nie po!) wpisie lua trzeba wpisać linijkę
config joinduplicatedevents yes endconfig
W przeciwnym wypadku nie będzie działać wygaszanie semaforów.

Jak pisać kod scenariusza?
Na początku każdego kodu scenariusza musimy zaincludować kernela linijką
local kernel = require "scenery/$lua_test/kernel"
Spowoduje to dołączanie dalszych poleceń do kernela, który jest nieodłączną częścią systemu. Teraz najtrudniejsza część, będziemy robić drabinkę. Nie, spokojnie, nie będziemy się bawić w kominiarza, drabinką nazywa się często złożoną strukturę danych. Będziemy bowiem robić wszystkie zależności na scenerii. To może potrwać nawet kilka dni przy bardzo dużych sceneriach. Struktura jest w widoczny i czytelny sposób podana w przykładowym pliku LUA (scenery/$lua_test/td_mijanka.lua). Zaczynamy od wpisania linijki
inicjalizuj()
Teraz w ten nawias wpisujemy dane zgodnie ze strukturą podaną w pliku (patrz wyżej). Kilka porad:
1. Żadnego z wyrazów nie podajemy dosłownie, są one wskazówką co mamy wpisać. Typ wpisu jest podany w nawiasie, może to być:
* int - zwykła liczba, np. 3,
* string - tekst, zamknięty w cudzysłowiu, np. "Hello World!",
* bool - wartość typu prawda/fałsz, prawda = true, fałsz = false,
* array - robimy {}, wewnątrz podajemy to, co jest bardziej we wcięciu, np.
nazwy (array)
    parametr1 (string)
    parametr2 (array)
        parametr11 (int)
        parametr12 (string)
dupa (bool)
powinniśmy zapisać jako
{parametr1, {parametr11, parametr12}}, dupa
, oczywiście podstawiając, np. taki zapis jest poprawny:
{"Stacja1", {0, "Hahahaha"}}, false
2. Jeśli mamy podać nazwę semafora, zwrotnicy lub izolacji, pamiętajmy, że jeśli chodzi nam o stację, którą właśnie definiujemy, to wpisujemy
nazwaObiektu
, jeśli zaś chcemy odwołać się do np. szlaku to wpisujemy
skrótStacji_nazwaObiektu
Uwaga, wszystkie obiekty są domyślnie zapisywane w formacie skrótStacji_nazwaObiektu, jednak gdy nie podamy skrótu stacji to zostanie podany skrót stacji, którą właśnie definiujemy. Pamiętajmy o tym podczas nazywania obiektów na scenerii!
3. Dzielmy odcinki izolowane tak, jak jest w rzeczywistości, nie idźmy na łatwiznę izolując całą głowicę jako jeden odcinek - uniemożliwi to prowadzenie płynniejszego ruchu na stacji.
4. Przy pisaniu przebiegów nie podajemy toru na którym stoimy czekając na wjazd/wyjazd - kod rozpozna, że pociąg, który właśnie czeka na podanie tego semafora, blokuje przebieg i semafor nie zostanie podany!
5. Z tego samego powodu pamiętajmy, żeby wpisać również te izolacje, które dotyczą torów z którymi przebieg się tylko krzyżuje:


Dobra, myślę, że jeśli chodzi o podawanie danych to już wszystko. Przejdźmy do łączenia eventów.

Łączenie eventów z torami
Aby w scenariuszu wjazdy były podawane dopiero wtedy, gdy zbliżamy się do semafora, albo żeby rogatki opuszczały się i podnosiły w odpowiednich momentach, konieczne jest połączenie eventów z "MaSzynowego kodu scenariuszowego" do kodu Lua. Pierwszym krokiem będzie przypisanie eventów do toru. Można to zrobić w dwojaki sposób, można przypisać event0, event1, event2 itd. do toru, bądź też wstawić odcinek izolowany (przypisanie isolated do toru). Aby to zrobić, należy w pliku z torami znaleźć tor np. 2 km przed semaforem wjazdowym i przypisać do niego event: https://wiki.eu07.pl/index.php/Obiekt_node::track#Parametry_opcjonalne
No i dwie uwagi:
- "Po primo" nazywamy eventy sensownie, tzn. nie piszemy np. "jskdkbvufidbsa", albo "489367", tylko np. "ps_wjazd_a" (zasady nazywania izolacji wyżej),
- "Po drugo" warto tworzyć eventy dla każdej sytuacji, nawet jeśli nie będzie ona w danym scenariuszu wykorzystywana. Jednym z założeń kodu Lua jest to, aby każdy scenariusz zawierał jedynie plik *.lua i *.scn, przy czym w *.scn będą jedynie include'y do wszystkiego oraz połączenie do kodu Lua scenariusza, a w *.lua kod do obsługi scenariusza samej w sobie.

Terz druga część roboty, czyli kodowanie w Lua. Otwieramy nasz plik z kodem scenariusza (nie kernelem) i wpisujemy tam bezpośrednio polecenie
polaczEvent(nazwa, polecenia)
gdzie eventy to lista poleceń Lua, która ma zostać wykonana. I tak na przykład, jeśli wpiszemy
polaczEvent("wjazd1", {{"podajPrzebieg", {"stacja1_a", "1", genOpoznienie("stacja1")}}, {"podajPrzebieg", {"stacja1_k", "b", genOpoznienie("stacja1")}}})
to po wywołaniu eventu "wjazd1" zostaną wykonane polecenia tak, jakby wywołać
podajPrzebieg("stacja1_a", "1", genOpoznienie("stacja1"))
podajPrzebieg("stacja1_k", "b", genOpoznienie("stacja1"))
Jeżeli chcemy sprawdzić izolację, jako pierwszy parametr do polaczEvent wpisujemy nazwa_izolacji:busy/free, czyli odpowiednio gdy dana izolacja zostanie zajęta lub zwolniona, np. tor1:busy oznacza, że funkcje z listy zostaną wykonane, gdy izolacja tor1 zostanie zajęta.
Co oznaczają konkretne polecenia i co można wpisać - o tym w następnej części.
Ciąg dalszy nigdy nie nastąpi...

« Ostatnia zmiana: 15 Lutego 2018, 19:28:55 wysłana przez jakubg1 »

Offline Mariusz1970

  • Zasłużony dla Symulatora
  • Wiadomości: 3899
    • Zobacz profil
  • Otrzymane polubienia: 231
Odp: Pisanie scenariuszy w Lua
« Odpowiedź #4 dnia: 02 Lutego 2018, 16:31:18 »
Szkoda, ze raczej nie ogarniasz zwyklych eventow, gdyz chcialbym zobaczyc porownanie w scenerii miedzy eventami a lua, robiace dokladnie to samo. Z lua tez to sa poczatki znajomosci z tematem.

Offline jakubg1

  • Deweloper
  • Wiadomości: 1147
  • MaSzyna ma szynę, szyna ma MaSzynę - na kołach.
    • Zobacz profil
  • Otrzymane polubienia: 602
Odp: Pisanie scenariuszy w Lua
« Odpowiedź #5 dnia: 15 Lutego 2018, 19:31:01 »
Wzbogaciłem poradnik wyżej o połączenia eventów.

Edit 23.03.18: Wysłałem nową wersję skryptu - 3.0. Kodu z poprzedniej wersji niewiele zostało, oto najważniejsze zmiany:
  • Rozbicie kodu na kilka części. W samym kernelu pozostały tylko includy.
  • Druga mijanka do toru doświadczalnego, autor @stapox. Wszelkie uwagi w tej sprawie kierować do niego.
    • Jedna głowica ma semafory kształtowe, druga - świetlne, na tej drugiej "panuje" ograniczenie do 100 km/h (test pasów świetlnych).
  • Zrobienie od nowa systemu danych. Teraz zamiast odwoływania się do zmiennych jest jedna wielka tabela ze wszystkimi urządzeniami. Dodano przy okazji obsługę semaforów kształtowych.
  • Trochę innych rzeczy.
W razie błędów proszę pisać.

Edit 25.03.18: Postanowiłem samemu przebadać scenariusz pod kątem błędów i znalazłem 2 błędy:
  • Zmienne nie resetowały się przy wygaszaniu się semafora kształtowego (było wykrywanie komendy pod względem "_s1", dorobiłem wykrywanie również pod względem "_sr1" i przy okazji "_tm1"). Tak więc ten bug już jest naprawiony;
  • Nieco poważniejszy bug w konkretnych przypadkach mogący doprowadzić do kolejnych Szczekocin - system działa tak, że w momencie wyzwolenia eventu wyjazdowego (przy wjeździe pociągu na stację) sprawdzana jest zajętość toru szlakowego. Jeżeli jest wolny - semafor jest podawany. Jeżeli jest zajęty - wówczas po losowym czasie wykonywana jest następna próba - i tak aż do skutku. Jeżeli mamy taką sytuację, że na dwóch mijankach stoją pociągi "chcące" wjechać na przeciwne mijanki, a szlak pomiędzy nimi jest wolny, wówczas może się zdarzyć taka sytuacja, że pociąg 1 wyjedzie ze stacji, ale "nie zdąży" zająć szlaku - w trakcie wyjazdu pociągu 1 może zostać podjęta próba podania wyjazdu dla pociągu 2, która przechodzi pozytywnie - system patrzy, że szlak jest wolny, mimo, że na ten szlak właśnie wjeżdża inny pociąg. Pociągowi 2 jest podawany wyjazd, wjeżdża na szlak, a dalszy ciąg wydarzeń można sobie już dokończyć za pomocą odrobiny wyobraźni.
    Rozwiązanie wprawdzie jest, tylko nie zostało zaimplementowane - w momencie podania wyjazdu odcinki zostaną "zarezerwowane" (jest już "zaklepana" zmienna w składni danych toru), a przy sprawdzaniu "wolności" szlaku będzie brana pod uwagę również rezerwacja.
Błędy planuję poprawić w następnej wersji. Poradnika wyżej nie będę kontynuował, ponieważ wpadłem na pomysł zrobienia dokumentacji bezpośrednio w paczce.

Edit 31.05.18:
To na początek kilka słów celem usprawiedliwienia nieobecności.
Jakiś miesiąc temu przeniosłem się na Linuxa. Tam Maszyna nie działała. Teraz komputer całkowicie i nieodwracalnie się zepsuł, więc korzystam z pożyczonego. Dane są ocalone, ale sam dysk został w punkcie naprawy (to nie taki zwykły dysk, który można podłączyć do USB, toteż trzeba przekopiować dane). Niestety sam symulator na tymczasowym komputerze działać nie będzie, a uzasadnienie tego znajdziecie w załączniku. Obrałem za to już plany na wersję 4.0, i będzie to kolejna wersja, w której głównie posprzątam. Najważniejsza będzie restrukturyzacja tablic z kolejką eventów i z tablicą urządzeń, od nowej wersji dostęp do nich będzie na zasadzie "słownika", co wyeliminuje funkcje pośrednie i znacznie zwiększy wydajność. Taki najprostszy przykład:
listaUrzadzen = {{}, {}, {}}
zostanie zamienione na:
listaUrzadzen = {tory = {}, zwrotnice = {}, semafory = {}}
Oprócz tego kod będzie bardziej czytelny. Następną zmianą będzie zamiana pętli "for" pętlami "while", co zlikwiduje potrzebę używania tymczasowej zmiennej "ok". @matek__9292 też zauważył parę rzeczy do poprawy, bardzo za to dziękuję.
Prace rozpocznę zaraz po tym, jak uda mi się przywrócić symulator do normalnego działania.
Edit 16.07.18: Zaplanowano także prace mające na celu "zangielszczenie" kodu na prośbę użytkowników.

Edit 20.08.18:
Rozpoczynam prace nad wersją Cztery Zero. Główne aspekty tej wersji będą optymalizacyjne. Zangielszczanie kodu, zrobienie użycia ze słowników zamiast zwykłych list, tworzenie dokumentacji.
Zapraszam do pobrania wersji 3.1, w której zostały naprawione błędy oraz dostosowanie do najnowszej wersji MaSzyny. Pięć kółek przejechanych bez problemu.

Edit 26.08.18:
Wakacje się kończą, więc nadszedł czas na premierę wersji 4.0. Oprócz przetłumaczenia kodu na język angielski (nie licząc komentarzy, te zostają) oraz zmiany organizacji struktury danych zostało dodanych kilka ciekawych rzeczy.
- Log systemu Lua został przeniesiony do osobnego pliku - folder lua_log w głównym katalogu symulatora.
- Dodano debugger - po uruchomieniu symulatora, wciśnięciu klawisza F12 i naciśnięciu kombinacji Shift + 0 można podejrzeć stan każdej zwrotnicy, semafora i odcinka izolowanego. Dzięki temu można łatwiej złapać błędy związane z organizacją przebiegów. Debugger można wyłączyć wciskając te same klawisze (Shift + 0, F12). Kolejność wciskania nie ma znaczenia.
Docelowo debugger zostanie przeniesiony do zupełnie innej aplikacji (jeszcze nie zaczęła ona powstawać), gdzie po wybraniu pliku będzie można na bieżąco podglądać stan scenerii oraz przeglądać jej przebieg po zakończeniu symulacji, co może być dużą pomocą w przypadku napotkania błędów. Program będzie oczywiście dostępny dla wszystkich, kod źródłowy będzie otwarty.
- Zepsucia semaforów i zwrotnic mogą już być naprawione - po instalacji i wejściu w scenery/lua/dlugosczepsucia (OpenDocument) można zobaczyć krzywą prezentującą obecnie dobrane ustawienia. Około 4% usterek będzie się przeciągać przez ponad 2 godziny, 0.5% przez ponad 3 godziny. Dajcie znać czy tak może zostać.
« Ostatnia zmiana: 26 Sierpnia 2018, 18:45:25 wysłana przez jakubg1 »

Offline jakubg1

  • Deweloper
  • Wiadomości: 1147
  • MaSzyna ma szynę, szyna ma MaSzynę - na kołach.
    • Zobacz profil
  • Otrzymane polubienia: 602
Odp: Projekt Lua, czyli automatyzacja scenerii
« Odpowiedź #6 dnia: 20 Stycznia 2020, 21:18:43 »
No to zaczynamy z drugim podejściem.

Od początku tego roku rozpocząłem prace nad kompletnie nową wersją. Ze starej praktycznie nic nie zostało - cały skrypt został przepisany od nowa. Organizacja kodu również została bardziej przemyślana. System od teraz jest napisany w sposób obiektowy, zamiast strukturalnego jak wcześniej. Ułatwia to pracę nad kodem.

Testowanie kodu jest prostsze - napisałem specjalny program, pozwalający na testowanie systemu bez konieczności uruchamiania symulatora. Jest oparty na silniku LOVE2D - kodu nie będę na razie udostępniał z powodu konieczności posiadania zainstalowanego silnika w celu działania aplikacji. Jak ktoś bardzo chce - zapraszam na PW lub na czat. Program do testowania wraz z samym systemem zostaną upublicznione na GitHubie, gdy zostanie ukończony drugi etap tworzenia systemu.

Plan pracy jest taki:
Etap 1 - definiowanie stacji, szlaków, torów, semaforów i zwrotnic oraz komunikacja ich z symulatorem. Pole testowe - zmodyfikowana sceneria TD.
Etap 2 - proste AI stacji bazujące na rozkładach jazdy. Dynamiczne generowanie rozkładów jazdy na podstawie scenerii. Pole testowe - zmodyfikowana sceneria Krzyżowa.
Dalsze etapy nie są jeszcze zaplanowane, ale będą to głównie dodatkowe funkcje i tzw. "smaczki".

Udostępniam paczkę do testu, żebyście sprawdzili, czy wszystko działa dobrze.
Prosiłbym o testowanie wygaszania semafora, blokady podawania przebiegów sprzecznych oraz na tory zajęte oraz poprawnego uzależniania obrazów na semaforach od sygnału na następnym semaforze.
Prosiłbym o nie testowanie AI oraz braków w osygnalizowaniu itp.

Lista przebiegów:
Shift+1, Shift+2 - wjazd od strony pociągu na starcie (tak jak w oryginalnym torze doświadczalnym)
Shift+3, Shift+4 - wjazd od drugiej strony (lustrzane odbicie Shift+1, 2)
Shift+5, Shift+6 - wyjazd ze stacji, odpowiedniki Shift+3, 4 w oryginalnym torze doświadczalnym.
Shift+7, Shift+8 - lustrzane odbicia powyższego.
Shift+9 - zezwolenie na jazdę na semaforze po drugiej stronie scenerii. Występuje uzależnienie z semaforem wjazdowym na stacji!
Shift+0 - reset wszystkiego.

Download: https://eu07.pl/userfiles/22592/lua_5_0_test1.zip
Wypakować do głównego katalogu symulatora. Żadne pliki nie są nadpisywane.

Jak poprzednio, konieczne posiadanie exe Milka do działania systemu!