Autor Wątek:  [INNE] Ekran komputera pokładowego w pythonie  (Przeczytany 51256 razy)

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

Offline Stele

  • Zasłużony dla Symulatora
  • Wiadomości: 10133
    • Zobacz profil
  • Otrzymane polubienia: 2609
[INNE] Ekran komputera pokładowego w pythonie
« dnia: 20 Grudnia 2016, 21:13:09 »
Wstęp teoretyczny:
Symulator ma w siebie wbudowany moduł pythona interpretujący kod programu rysujący ekran. Jest on niekompilowany, możemy go dowolnie modyfikować notatnikiem przed inicjalizacją symulacji.
Moduł podmienia teksturę jednego obiektu w kabinie pojazdu generowaną dynamicznie.
Kod: ("SP42.mmd") [Zaznacz]
pyscreen: komp ekranikOznacza, że ekranem będzie obiekt (submodel w kabinie) "komp" a jego tekstura będzie generowana skryptem/funkcją "ekranik". Jeśli w danej kabinie nie zostanie znaleziony taki obiekt, zostanie on zignorowany.
Jak widać mamy tylko jeden obiekt, który w t3d może mieć tylko jedną teksturę. Przy kilku ekranach w pojeździe musimy je wszystkie scalić w jeden obiekt i mapować z różnych części jednej dużej tekstury. Zniesione. Pojazd może obsłużyć dowolną ilość skryptów.
Liczenie tekstury odbywa się w osobnym wątku, którego priorytet względem symulacji można ustawić w eu07.ini wpisem:
pyscreenrendererpriority normal // (normal, lower, lowest, idle) priorytet wątku pythonowego renderera. Odciąża procesor zmniejszając odświeżanie ekranów w lokomotywach.Ciężki skrypt na wolnym komputerze może znacznie spowolnić symulację. Niższy priorytet za to powodować, że klatka ekranu będzie liczona nawet raz na kilka tysięcy klatek symulacji, przez co ciężko będzie nawet dostrzec animację tekstury.

W pętli symulatora część wartości fizycznych naszego pojazdu/składu jest udostępniana do słownika pythona. Lista kluczy dostępna jest tutaj: https://wiki.eu07.pl/index.php/Python
Klucze rozpoczynające się frazą "eimp" oznaczają "electric induction motor parameter" i nie działają dla innych typów pojazdów. Niekiedy dokumentacja może też trochę wyprzedzać publiczne wersje exe.
Wartości fizyczne ze słownika mogą być wykorzystane w naszym programie. Dodatkowo możemy używać wartości uzyskanych z bibliotek wbudowanych w środowisko pythona. W ten sposób uzyskiwana jest choćby data systemowa, jako że symulacja nie ustawia konkretnej fikcyjnej daty.
Cały program jest jak zapewne się domyślacie napisany w języku python, więc wymagana jest podstawowa znajomość składni. Zazwyczaj nie trzeba wymyślać koła od nowa. Ekrany zawierają podobne dane. Wystarczy zmienić ich reprezentację graficzną i ustawić w dobrym miejscu, modyfikując gotowy kod.
Warto jednak przejrzeć podstawy https://docs.python.org/3/ lub znaleźć sobie dowolny, polskojęzyczny poradnik by poznać zasady inicjalizacji zmiennych, budowy funkcji, pętli, warunków.

Używamy głównie zmodyfikowanej biblioteki PIL-PILLOW. https://pillow.readthedocs.io/en/3.4.x/ W szczególności modułu ImageDraw.
Pozwala on na wczytanie grafiki tła, nakładanie na nią innych grafik, generowanie prostej grafiki wektorowej, napisów i eksport w postaci nowej bitmapy.
Taki proces właśnie jest przeprowadzany w naszym programie. Bierzemy teksturę ekranu, na podstawie zaczerpniętych i odpowiednio przeliczonych wartości fizycznych pojazdu rysujemy na niej napisy, słupki, diagramy, nakładamy ikonki i eksportujemy do bufora. Ten obrazek jest wysyłany do menadżera tekstur w głównym wątku symulatora i nakładany na obiekt zdefiniowany w mmd pojazdu.

Przykład:
Dostałem od @EP08_015 prośbę:

Cytuj
Data aktualna, predkosc cyfrowa pod predkoscia pasek rozszerzajacy sie domyslam sie ze to procent max szybkosci oraz oststni prad trakcyjny cyfrowy z paskiem sily trakcyjnej.

Ekranik musi się świecić w nocy. Świecenie jest atrybutem materiału obiektu a nie tekstury, więc pythonem na nie nie wpłyniemy. Ekranik ma się więc świecić cały czas/być podłączony pod universala. Częścią świecącą będzie sam czarny prostokącik (świecenie na czarno=brak świecenia).
Na teksturze którą otrzymałem ma on rozdzielczość 158x124 px. Nie wiem jaką ma w rzeczywistości, ale że ma być teksturą wyświetlaną przez symulator, musi mieć wymiary 2^n i jak wszystkie tekstury dynamiczne, mieć głębię 24 bitów.
Zeskalowałem podkładkę do 256^2 px. U dołu został biały pasek. Niestety musi zostać. Część tekstury się zmarnuje. Tak to wygląda obecnie:


Potrzebujemy więc:
1. Szare tło 256x256 px.
2. Pikselową czcionkę do cyferek.
3. Godzinę w symulacji.
4. Prędkość pojazdu.
5. Prąd trakcyjny silnika spal-ele.
6. Siłę trakcyjną.

Punktów 5-6 nie zrobimy, bo nie są zaimplementowane w exe471.

Otwieramy notatnik i zaczynamy pisać program.

Potrzebujemy tła. Zazwyczaj bierzemy jakiś rysunek na tło, ale tu jest jednorodne, wiec nie ma to sensu. Generujemy nowy plik. https://pillow.readthedocs.io/en/3.4.x/reference/Image.html#constructing-images

Z biblioteki PIL wczytujemy moduł Image. W nagłówku piszemy:
from PIL import ImageMamy teraz dostęp do wszystkich funkcji klasy Image

Tworzymy podstawową strukturę programu.
class ekranik(abstractscreenrenderer):
def __init__(self,lookup_path,name,cab):
#tu będą inicjowane stałe
def _render(self, state):
#tu będą zmienne odświeżane w każdej klatce

W metodzie render tworzymy nasze tło. Musi się odświeżać w każdej klatce by zakrywać stare napisy.
obrazek=Image.new(mode, size, color=0)mode=RGB (3x8-bit pixels, true color)
size=(256,256)
color=(57,57,57) (ciemnoszary, takie rgb odczytało mi z podkładki)
obrazek=Image.new(RGB, (256,256), color=(57,57,57))
I na końcu metody zwracamy finalny obrazek do bufora:
return obrazek
By móc coś rysować po naszym obrazku używamy funkcji Draw z modułu ImageDraw z biblioteki PIL.
Dodajemy ją do nagłówka. Razem z poprzednią będziemy mieć:
from PIL import Image, ImageDraw
W metodzie render po wygenerowaniu tła, ładujemy je do edycji, przypisując funkcję pod zmienną draw by nie pisać tego przy każdej funkcji korzystającej z niej później:
draw=ImageDraw.Draw(obrazek)
Zegarek:
Kopiujemy gotowy kod z traxxa:
#czas
if state['seconds'] != self.last_time_update:
dt = state['seconds'] - self.last_time_update
if dt < 0:
dt+=60
self.kilometry += dt*speed * 0.0002778
self.last_time_update = state['seconds']
if state['hours']<10: #dodaje zero przed liczbą gdy ma tylko jedną cyfrę
godz = "0" + str(state['hours'])
else:
godz = str(state['hours']) #zapisuje do zmiennej "godz" liczbę godzin jako string
if state['minutes']<10:
min = "0" + str(state['minutes'])
else:
min = str(state['minutes'])
if state['seconds']<10:
sec = "0" +str(state['seconds'])
else:
sec = str(state['seconds'])
Licznika kilometrów nam nie potrzeba, więc go usuwamy.
Mamy trzy zmienne z godzinami, minutami i sekundami. Wyświetlamy je na ekranie:
draw.text((x,y), godz +":"+ min +":"+ sec, fill, font)Musimy podać pozycję, kolor i czcionkę napisu. Użyjemy obecnej już w symulatorze czcionki Alterebro Pixel Font Regular. Otwieram w gimpie podkładkę i piszę nią napis by pokrył się ze zdjęciem. Odczytuję:
Lewy górny róg ramki tekstu (zero w grafice rastrowej): (7, 20)
Rozmiar: 68
Kolor jest strasznie zszarzały. Wezmę intensywniejszy (193,164,50)

W metodzie init definiuję czcionkę:
self.pixel = ImageFont.truetype(lookup_path + "Alterebro Pixel Font Regular.ttf", 68)Używam modułu ImageFont, więc dodaję go do nagłówka. Mamy tam już:
from PIL import ImageDraw, ImageFont, ImageDodajemy również nasz kolor. Można go za każdym razem podawać jako RGB, ale w ten sposób w jednym miejscu możemy go zmieniać jakby efekt był niezadowalający.
self.zolty = (193,164,50)
Pod stworzonym tłem rysujemy właściwy napis:
draw.text((7, 20), godz +":"+ min +":"+ sec, fill=selfzolty, font=self.pixel)Używamy domyślnej funkcji draw.text justującej do lewej. Składamy godziny, minuty i sekundy, oddzielając je dwukropkami. Zazwyczaj dwukropki migają z pulsacją 1s, ale nie wiem jak osiągnąć taktowanie 0,5s na wł/wył.
Do dyspozycji mamy trzy funkcje wypisujące tekst o niestety różnej kolejności argumentów. Oprócz tej jest justująca do prawej (czy raczej justująca pole na stałą ilość znaków do lewej a tekst w nim do prawej) i centrująca napis. Wszystkie funkcje naszego autorstwa są do wglądu w pliku: python\local\abstractscreenrenderer.py. Jeśli napiszecie coś mającego uniwersalny potencjał, warto rozważyć dodanie funkcji tam, by nie dublować w każdym skrypcie tego samego.
def print_fixed_with(self, draw, text, start_point, character_count, font, color, correction=0):
rozmiar_osemki = font.getsize("8")[0]
start_point_tmp = start_point[0]
for znak in range(len(text), character_count):
start_point_tmp += rozmiar_osemki-correction
for znak in range(0,len(text)):
rozmiar_act = font.getsize(text[znak])[0]
draw.text((start_point_tmp + rozmiar_osemki - rozmiar_act, start_point[1]), text[znak], font=font, fill=color)
start_point_tmp += rozmiar_osemki-correction

def print_center(self, draw, text, X, Y, font, color):
w = draw.textsize(text, font)
draw.text(((X-w[0]/2),(Y-w[1]/2)), text, font=font, fill=color)

Prędkościomierz:
W metodzie render (musi odczytywać prędkość co klatkę), odczytujemy wartość prędkości liniowej pojazdu (nie łapie poślizgu zestawów niestety; może kiedyś zmienimy).
speed = float(state['velocity'])Pod zmienną lokalną "speed" podstawiamy wartość wysłaną przez moduł fizyki jako zmiennoprzecinkową float.
Umieszczamy ją jako napis, podobnie jak z zegarkiem.
draw.text((21, 96), '%d' % speed, fill=self.zolty, font=self.pixel)"%d"-formatowanie; tylko część całkowita. Zamiast tego można by skonwertować ją do int.

Pasek procentu prędkości:
Musimy ograniczyć odczyt prędkości by nam nie wychodził poza zakres jak ktoś zacznie majstrować przy lokomotywie. SP32 ma Vmax=100km/h i taki zakres przyjmę, ze względu na brak wyskalowania prędkościomierza na ekranie.
if speed > 100:
speed = 100
Gdy zmienna przekracza 100, ucinamy do setki.

Mierzymy nasz pasek na maksymalnym wypełnieniu. Nie mam zdjęcia i nie wiem gdzie on się kończy, ale by się komponował na ekranie przyjmę następujące wartości:
Zero prostokąta (lewy górny róg): (17,150)
Rozmiar: (108,12)
Czyli rogi będą we współrzędnych: (17,150),(17,162),(125,150),(125,162)
Wzór na długość paska zależnie od prędkości, to:
x2=x1+(V/Vmax*dx)
Podstawiamy nasze dane i mamy:
x2=17+(speed/100*108)=17+1.08*speed
Rysujemy prostokąt którego lewa krawędź będzie w x1=17 a prawa w x2. Dla V=0 x2=x1 czyli pasek jest jednostkowy. Dla V=Vmax wypełnia cały zakres do x2=125. Podajemy dwa przeciwległe narożniki, poczynając od tego o mniejszych wartościach współrzędnych.
x2=17+1.08*speed
draw.rectangle(((17,150),(x2,162)), fill=self.zolty)

Prąd trakcyjny i pasek siły trakcyjnej:

Pasek siły trakcyjnej wymagał zmian w exe, stąd będzie działał tylko na 472+. Dodawanie nowych zmiennych jest banalne. Wystarczy odszukać ją w którymś z modułów pojazdu (mover/dynobj/train) i przekazać do pythonowego słownika w PyObject *TTrain::GetTrainState().
Siłę trakcyjną pobieramy jako "tractionforce" i wrzucamy jako pasek analogicznie do prędkości. Wcześniej musimy sobie zmierzyć siłę maksymalną, ale że mamy ją na ekranach diagnostycznych F1/F2, to nie jest to problemem. W innym przypadku można wyprowadzić tymczasowo wartość jako tekst na ekran pythonowy. Pomaga to w debugowaniu gdy dzieją się cuda, zwłaszcza przy implementacji nowych odczytów.
Prąd trakcyjny jest bardziej problematyczny. Mamy zmienną "im", ale w dieselelectric podaje ona prąd na wyjściu prądnicy głównej. Dokładnie to jest wyprowadzane na amperomierz analogowy. Oprócz prądu trakcyjnego mamy w nim prąd ogrzewania. Mamy dwie opcje. Możemy wbić się w funkcję liczącą ten prąd w mover.pas i dodać zmienną pomocniczą, łapiącą prąd przed dodaniem do niego prądu ogrzewania i to ją wyprowadzić na ekran. Wymaga to rekompilacji movera, co jest odrobinę problematyczne, przez błędnie generujące się nagłówki i gryzłoby się z przepisywaniem go na cpp. Druga opcja, to policzyć prąd ogrzewania w pythonie i odjąć go od odczytanego prądu całkowitego. Nie będę się w to zagłębiał, nie wiem czy ma on dostępne wszystkie potrzebne dane, bo nie to jest istotą tworzenia ekranu.

Całość kodu:
from PIL import ImageDraw, ImageFont, Image #Ładujemy biblioteki

class ekranik(abstractscreenrenderer): #klasa renderera
def __init__(self,lookup_path,name,cab): #inicjalizacja stałych
self.pixel = ImageFont.truetype(lookup_path + "Alterebro Pixel Font Regular.ttf", 68) #definicja czcionki na napisy
self.zolty = (193,164,50) #kolor na napisy

def _render(self, state): #pętla rendera

#czas
if state['hours']<10: #dodaje zero przed liczbą gdy ma tylko jedną cyfrę
godz = "0" + str(state['hours'])
else:
godz = str(state['hours']) #zapisuje do zmiennej "godz" liczbę godzin jako string
if state['minutes']<10:
min = "0" + str(state['minutes'])
else:
min = str(state['minutes'])
if state['seconds']<10:
sec = "0" +str(state['seconds'])
else:
sec = str(state['seconds'])


obrazek=Image.new(RGB, (256,256), color=(57,57,57)) #tworzymy nowy obrazek tła
draw=ImageDraw.Draw(obrazek) #ładujemy go do edycji

draw.text((7, 20), godz +":"+ min +":"+ sec, fill=self.zolty, font=self.pixel) #napis-zegarek

#prędkość
speed = float(state['velocity']) #odczyt prędkości
draw.text((21, 96), '%d' % speed, fill=self.zolty, font=self.pixel) #napis-prędkość

if speed > 100: #ucięcie prędkości jakby wyszła poza zakres
speed = 100
x2=17+1.08*speed #długość paska prędkości jako procent Vmax x2=17+(speed/100*108)
draw.rectangle(((17,150),(x2,162)), fill=self.zolty) #prostokąt procentu prędkości

return obrazek #wysyłamy finalny obrazek do bufora

Inne funkcjonalności:

Włączenie wraz z baterią:
Całość rendera wrzucamy w warunek na stan 'battery' a na tło po którym rysujemy dajemy wygaszony ekran, możliwie ciemny, bo musi mieć selfillum=true w materiale.

Mierniki kołowe:
Czyli coś w stylu siłomierza traxxa. Figury ograniczonej krzywymi nie możemy narysować o ile mi wiadomo. Obszedłem to przez rysowanie wycinku koła i zakrycie go prostokątną maską w kolorze tła z przezroczystym wycięciem na część która ma być widoczna. Uwaga na błąd powodujący osiąganie przez wartość fizyczną liczby niezgodnej z argumentem wypełnienia wycinka koła. Odsyłam do traxxa, bo jest ona przepuszczana przez gotową funkcję filtrującą, której nie rozumiem do końca.

Mierniki obrotowe:
Tu wymagane są podstawy geometrii analitycznej. Liczymy wskazówkę w stanie "na dwunastą" jako krzywą łamaną zdefiniowaną n punktów. Potem Każdy z tych punktów wyrażamy we współrzędnych biegunowych z zerem w osi obrotu naszej wskazówki. Za amplitudę przyjmujemy naszą wartość fizyczną po znormalizowaniu do zakresu miernika i skompensowaniu obrotem w lewo od położenia pionowego do zera na skali miernika. Przeliczamy to na współrzędne kartezjańskie i wyświetlamy. Uwaga, w istniejących ekranach mogą być błędy w zastosowanych funkcjach trygonometrycznych, skutkujące złym znakiem na wyjściu, co zostało zamaskowane mnożeniem wszystkiego przez -1. Zamiast kopiować kod, warto ustawić je prawidłowo.
« Ostatnia zmiana: 29 Grudnia 2021, 21:18:38 wysłana przez Stele »
Mój kanał youtube

Offline firleju

  • Zasłużony dla Symulatora
  • Wiadomości: 1588
  • bawię się (w) exe...
    • Zobacz profil
  • Otrzymane polubienia: 121
Odp: [INNE] Ekran komputera pokładowego w pythonie
« Odpowiedź #1 dnia: 21 Grudnia 2016, 07:23:59 »
Masz błąd, gdyż używamy wersji 2.7 pythona w związku z czym składnia i niektóre funkcje mogą się różnić.
Skrypty do Blendera dostępne tutaj
W miarę aktualne wiki EXE wiki.eu07.es

Offline Stele

  • Zasłużony dla Symulatora
  • Wiadomości: 10133
    • Zobacz profil
  • Otrzymane polubienia: 2609
Odp: [INNE] Ekran komputera pokładowego w pythonie
« Odpowiedź #2 dnia: 21 Grudnia 2016, 11:46:19 »
Ok, podlinkuję starszy manual.
Mój kanał youtube

Offline firleju

  • Zasłużony dla Symulatora
  • Wiadomości: 1588
  • bawię się (w) exe...
    • Zobacz profil
  • Otrzymane polubienia: 121
Odp: [INNE] Ekran komputera pokładowego w pythonie
« Odpowiedź #3 dnia: 21 Grudnia 2016, 12:10:04 »
Ale przetestowałbym podłączenie nowej wersji. Może będą jakieś konkretne zyski na FPS-ach. Pamiętaj żeby przerobić tylko lib na zgodny z BCB (jest narzędzie razem z BCB).
Skrypty do Blendera dostępne tutaj
W miarę aktualne wiki EXE wiki.eu07.es

Offline EP08_015

  • Zasłużony dla Symulatora
  • Wiadomości: 4330
    • Zobacz profil
  • Otrzymane polubienia: 307
Odp: [INNE] Ekran komputera pokładowego w pythonie
« Odpowiedź #4 dnia: 21 Grudnia 2016, 16:07:23 »
Przy okazji opisz tez jak zrobic by ekran mozna bylo przyciemnic uniwersalem podswietlenia. Jak zrobic by ekran pojawil sie przy wlaczeniu baterii. Dzieki za podjecie tematu. Zastanawiam sie tez jak zrobiles w smoku kontrolki stanu patykow.
Koniec tworczosci unoffowej i prywatnej.
http://chomikuj.pl/EP08-015

Offline Stele

  • Zasłużony dla Symulatora
  • Wiadomości: 10133
    • Zobacz profil
  • Otrzymane polubienia: 2609
Odp: [INNE] Ekran komputera pokładowego w pythonie
« Odpowiedź #5 dnia: 21 Grudnia 2016, 17:11:51 »
Przyciemnić? Submodele on/off różniące się diffuse materiału. Ewentualnie filtr na finalny obrazek zależny od universala.
Patyki w smoku to ikonki on-off albo linie rysowane wektorowo. Nie pamiętam już jak to zrobiłem.
Mój kanał youtube

Offline EP08_015

  • Zasłużony dla Symulatora
  • Wiadomości: 4330
    • Zobacz profil
  • Otrzymane polubienia: 307
Odp: [INNE] Ekran komputera pokładowego w pythonie
« Odpowiedź #6 dnia: 21 Grudnia 2016, 20:12:07 »
A exe obsługuje ikonki on i off? Nie przypominam sobie takich lampek. Tak samo czy mamy odłącznik baterii jako sw coś <> tam? Warto by zaktualizować tego posta dotyczącego wpisów do mmd.

http://eu07.pl/forum/index.php/topic,8949.msg89305.html#top

A co do tego > obrazek=Image.new(RGB, (256,256),  może lepiej 1024x512? Lepiej będzie wygladalo. A i czy koniecznie musi to być *.PNG?

Regulamin prawa 4, zakazy 10.
Poprawiłem.
jakubg1


Kolejny nawiedzony.
« Ostatnia zmiana: 21 Grudnia 2016, 23:28:46 wysłana przez EP08_015 »
Koniec tworczosci unoffowej i prywatnej.
http://chomikuj.pl/EP08-015

Offline Stele

  • Zasłużony dla Symulatora
  • Wiadomości: 10133
    • Zobacz profil
  • Otrzymane polubienia: 2609
Odp: [INNE] Ekran komputera pokładowego w pythonie
« Odpowiedź #7 dnia: 21 Grudnia 2016, 20:19:54 »
Ikonki w pythonie.
battery (bool) - stan baterii w pojeździe kontrolowanymJako warunek z podłączonymi ikonkami.
eimp_u + (nr zespołu) + _ + (parametr)
gdzie:

    (nr zespołu) to liczba z zakresu od 1 do 8,
    (parametr) przyjmuje wartości:
        pf - podniesiony przedni pantograf
        pr - podniesiony tylny pantograf
Jako warunki z ikonkami patyków góra-dół.
Mój kanał youtube

Offline EP08_015

  • Zasłużony dla Symulatora
  • Wiadomości: 4330
    • Zobacz profil
  • Otrzymane polubienia: 307
Odp: [INNE] Ekran komputera pokładowego w pythonie
« Odpowiedź #8 dnia: 21 Grudnia 2016, 20:52:56 »
Zrobilem czesc tego skryptu i zrobilo mi rozowego kompa. Cos zle poszlo?
Koniec tworczosci unoffowej i prywatnej.
http://chomikuj.pl/EP08-015

Offline Stele

  • Zasłużony dla Symulatora
  • Wiadomości: 10133
    • Zobacz profil
  • Otrzymane polubienia: 2609
Odp: [INNE] Ekran komputera pokładowego w pythonie
« Odpowiedź #9 dnia: 21 Grudnia 2016, 21:38:10 »
Może kolor skopałem albo masz ten błąd co ktoś w traksie i ci przestrzeń kolorów odwraca. Choć nie, to szary, więc zawsze będzie szary. Piszę na papierze; skończę to zobaczę efekt i poprawię ewentualne błędy. Dziś mam inne rzeczy na głowie, ale do świąt opiszę ten ekranik do końca. ...i posprzątam wątek. ;)
Mój kanał youtube

Offline EP08_015

  • Zasłużony dla Symulatora
  • Wiadomości: 4330
    • Zobacz profil
  • Otrzymane polubienia: 307
Odp: [INNE] Ekran komputera pokładowego w pythonie
« Odpowiedź #10 dnia: 21 Grudnia 2016, 22:57:02 »
STel a jak wyswietlic prad tekstowo?
prad = state['im']
       
               self.print_fixed_with(draw_txt, prad, (250,250), 30, self.segment_font, (255,127,39), 7)
« Ostatnia zmiana: 21 Grudnia 2016, 23:10:15 wysłana przez Stele »
Koniec tworczosci unoffowej i prywatnej.
http://chomikuj.pl/EP08-015

Offline Stele

  • Zasłużony dla Symulatora
  • Wiadomości: 10133
    • Zobacz profil
  • Otrzymane polubienia: 2609
Odp: [INNE] Ekran komputera pokładowego w pythonie
« Odpowiedź #11 dnia: 21 Grudnia 2016, 23:09:36 »
W spal-ele może to nie działać. Trzeba zerknąć jaka zmienna jest prądem silników. Ekrany były projektowane pod et22, potem pod impulsa, traxxa i turboklopa. Diesli nikt nie implementował.
Mój kanał youtube

Offline EP08_015

  • Zasłużony dla Symulatora
  • Wiadomości: 4330
    • Zobacz profil
  • Otrzymane polubienia: 307
Odp: [INNE] Ekran komputera pokładowego w pythonie
« Odpowiedź #12 dnia: 22 Grudnia 2016, 15:10:44 »
Tylko ze wiesz prad to prad. Jakbys mogl zweryfikuj te linijke co napisalem ok? Jak ja ocenisz ze skladnia ok to bede dalej eksperymentowal.

  Dodano: 22 Grudnia 2016, 23:54:38
Jak zrobić jeszcze by ekran swiecil jako true w nocy? bo puki co zachowuje się jak zwykly material.
« Ostatnia zmiana: 22 Grudnia 2016, 23:54:38 wysłana przez EP08_015 »
Koniec tworczosci unoffowej i prywatnej.
http://chomikuj.pl/EP08-015

Offline Stele

  • Zasłużony dla Symulatora
  • Wiadomości: 10133
    • Zobacz profil
  • Otrzymane polubienia: 2609
Odp: [INNE] Ekran komputera pokładowego w pythonie
« Odpowiedź #13 dnia: 23 Grudnia 2016, 00:18:08 »
Cytuj
Ekranik musi się świecić w nocy. Świecenie jest atrybutem materiału obiektu a nie tekstury, więc pythonem na nie nie wpłyniemy. Ekranik mu się więc świecić cały czas/być podłączony pod universala. Częścią świecącą będzie sam czarny prostokącik (świecenie na czarno=brak świecenia).
Mój kanał youtube

Offline EP08_015

  • Zasłużony dla Symulatora
  • Wiadomości: 4330
    • Zobacz profil
  • Otrzymane polubienia: 307
Odp: [INNE] Ekran komputera pokładowego w pythonie
« Odpowiedź #14 dnia: 23 Grudnia 2016, 00:29:13 »
Czyli co? Submodel o nazwie komp musi miec selfilum true?

  Dodano: 23 Grudnia 2016, 00:33:24
A zeby przyciemnic w nocy to?
« Ostatnia zmiana: 23 Grudnia 2016, 00:33:24 wysłana przez EP08_015 »
Koniec tworczosci unoffowej i prywatnej.
http://chomikuj.pl/EP08-015

Offline Stele

  • Zasłużony dla Symulatora
  • Wiadomości: 10133
    • Zobacz profil
  • Otrzymane polubienia: 2609
Odp: [INNE] Ekran komputera pokładowego w pythonie
« Odpowiedź #15 dnia: 23 Grudnia 2016, 00:47:05 »
Przecież napomniałem dwie metody w swoim trzecim poście tu. Chciałeś tutka to czytaj. Skończę to skompiluję tą dyskusję w jakieś faq i wywalę resztę.
Mój kanał youtube

Offline jakubg1

  • Wydział Repozytorium
  • Wiadomości: 1492
  • MaSzyna ma szynę, szyna ma MaSzynę - na kołach.
    • Zobacz profil
  • Otrzymane polubienia: 1118
Odp: [INNE] Ekran komputera pokładowego w pythonie
« Odpowiedź #16 dnia: 23 Grudnia 2016, 17:01:32 »
Da się zrobić migający tekst, tak jak tutaj? https://youtu.be/GbJySWneDaI?t=7s
10 lat na forum MaSzyny!

Offline Stele

  • Zasłużony dla Symulatora
  • Wiadomości: 10133
    • Zobacz profil
  • Otrzymane polubienia: 2609
Odp: [INNE] Ekran komputera pokładowego w pythonie
« Odpowiedź #17 dnia: 23 Grudnia 2016, 17:13:50 »
Miałem z tym problem w Dragonie i chyba go nie obszedłem. Używając ostatecznie taktowania sekundnika a złej częstotliwości. Spróbuj wymyśleć coś lepszego. Mi na taktowaniu procesora nie chciało działać.
Mój kanał youtube

Offline jakubg1

  • Wydział Repozytorium
  • Wiadomości: 1492
  • MaSzyna ma szynę, szyna ma MaSzynę - na kołach.
    • Zobacz profil
  • Otrzymane polubienia: 1118
Odp: [INNE] Ekran komputera pokładowego w pythonie
« Odpowiedź #18 dnia: 23 Grudnia 2016, 17:24:34 »
Mam pomysł na takie coś:
czas += 1
if czas == 300:
czas = 0
takt += 1
if takt == 2:
takt = 0
if takt == 1:
(tutaj funkcja rysująca tekst)
Niestety nie działa. Wiesz może jak zrobić by dane polecenie wywoływało się tylko raz na początku?
« Ostatnia zmiana: 23 Grudnia 2016, 17:29:34 wysłana przez jakubg1 »
10 lat na forum MaSzyny!

Offline EP08_015

  • Zasłużony dla Symulatora
  • Wiadomości: 4330
    • Zobacz profil
  • Otrzymane polubienia: 307
Odp: [INNE] Ekran komputera pokładowego w pythonie
« Odpowiedź #19 dnia: 23 Grudnia 2016, 20:30:24 »
Oto jak mi to wyszlo. Screny off on i on-prezyciemniony po wlaczeniu osw przyrzadow. Caly czas nie mam pomysłu na cyfrowe wyświetlenie pobieranego pradu z prądnicy i na te paski. Python nie obsluguje dizli.
Koniec tworczosci unoffowej i prywatnej.
http://chomikuj.pl/EP08-015

Offline youBy

  • Deweloper
  • Wiadomości: 6163
  • Co tam?
    • Zobacz profil
    • Automat Weryfikujący Regulację i Lambdę
  • Otrzymane polubienia: 865
Odp: [INNE] Ekran komputera pokładowego w pythonie
« Odpowiedź #20 dnia: 15 Stycznia 2017, 14:41:47 »
Zapisywanie i wczytywanie przebiegu pojazdu z komputerem

Istnieje możliwość, aby przy uruchomieniu pojazdu stan licznika kilometrów pokrywał się* z tym, jaki był przy wyłączaniu symulacji i przez były zliczane kilometr przejechane przez użytkownika.

1. W funkcji __init__ należy zapisać
# przeniesienie ścieżki do funkcji zapisującej
self.lookup_path = lookup_path
# zapisywanie ostatniej sekundy od liczenia przebiegu
self.last_time_update = 0
# losowanie przebiegustartowego
self.kilometry = PS+(random()*PL)+(1+self.rok-RokProd)*PR+self.dzis*PD
# ostatni zapisany przebieg
self.kilometry_z = 0
# otwieranie pliku
plik = open(lookup_path + "tacho.txt")
try:
tempkm = plik.read()
if tempkm == "":
tempkm = "x"
else:
self.kilometry = float(tempkm)
self.kilometry_z = self.kilometry
finally:
plik.close()
Gdzie zastosowano zmienne czasu:
self.dzis = datetime.now().timetuple().tm_yday
self.rok = datetime.now().year
przy losowaniu przebiegu zastosowane są również parametry:
PS – stały przebieg początkowy (ewentualnie w pierwszym roku kalendarzowym),
PL – losowana wartość przebiegu pojazdu,
RokProd – rok produkcji pojazdu,
PR – przebieg roczny,
PD – przebieg dzienny.
W ich miejsce należy wpisać po prostu wybrane liczby.

2. W funkcji _render należy dodać funkcję liczącą przebieg:
#liczenie przebiegu co sekundę
if state['seconds'] != self.last_time_update:
dt = state['seconds'] - self.last_time_update
if dt < 0:
dt+=60
self.kilometry += dt*speed * 0.0002778
self.last_time_update = state['seconds']
gdzie zastosowano zmienną:
speed = float(state['velocity'])
3. W funkcji _render (pod koniec) należy dodać funkcję zapisującą:
#zapis stanu licznika do pliku
if self.kilometry>(self.kilometry_z + (0.1+0.005*speed)):
plik = open(self.lookup_path + "tacho.txt", 'wb')
try:
plik.write(str(self.kilometry))
self.kilometry_z = self.kilometry
finally:
plik.close()

* – w związku z częstotliwością zapisu stanu licznika, różnica może wynieść od 100 (wyłączanie symulacji w czasie postoju pojazdu) do 900 (wyłączanie symulacji przy jeździe z prędkością 160 km/h) metrów.
Xoov
Powyższy post wyraża jedynie opinię autora w chwili publikacji. Autor zastrzega sobie prawo do zmiany poglądów bez podawania przyczyny, jak również informowania o tym.

Offline EP08_015

  • Zasłużony dla Symulatora
  • Wiadomości: 4330
    • Zobacz profil
  • Otrzymane polubienia: 307
Odp: [INNE] Ekran komputera pokładowego w pythonie
« Odpowiedź #21 dnia: 16 Stycznia 2017, 19:44:49 »
Yb mnie by sie przydaly paranetry dla dizli. Prady napiecia obroty. Takze hamulec dynamiczny (niewiem jak dziala ale sp32 go ma).
Koniec tworczosci unoffowej i prywatnej.
http://chomikuj.pl/EP08-015

Offline jakubg1

  • Wydział Repozytorium
  • Wiadomości: 1492
  • MaSzyna ma szynę, szyna ma MaSzynę - na kołach.
    • Zobacz profil
  • Otrzymane polubienia: 1118
Odp: [INNE] Ekran komputera pokładowego w pythonie
« Odpowiedź #22 dnia: 12 Marca 2017, 12:05:56 »
Odgrzewam wątek. Dzisiaj rozpocząłem kreowanie ekranu uruchamiania lokomotywy w ET22-2000. Aby to jednak zrobić, muszę uzależnić wszystko od wybranego kierunku jazdy. Póki co ta modyfikacja ma na celu coś takiego:
jeżeli nawrotnik jest w pozycji 0
wyświetl pusty ekran
w przeciwnym razie
wyświetl ekran normalnie (tak jak obecnie)
Niestety wywala błąd. Teoretycznie wszystko zrobiłem dobrze, a błąd polega na tym że nie ma odwołania do lokomotywy (!) mimo że nie znalazłem tej definicji. Jak go naprawić? Podaję plik pythona i log.
PS. Dodać do dozwolonych typów plików rozszerzenie *.py.

EDIT: Jakieś pomysły? Już tydzień bez rozwiązania...
« Ostatnia zmiana: 18 Marca 2017, 12:37:30 wysłana przez jakubg1 »
10 lat na forum MaSzyny!

Offline Stele

  • Zasłużony dla Symulatora
  • Wiadomości: 10133
    • Zobacz profil
  • Otrzymane polubienia: 2609
Odp: [INNE] Ekran komputera pokładowego w pythonie
« Odpowiedź #23 dnia: 18 Marca 2017, 17:58:15 »
Przecież ci tłumaczyłem, że zjadłeś jedną z głównych metod. Poprawiłeś to?
Mój kanał youtube

Offline youBy

  • Deweloper
  • Wiadomości: 6163
  • Co tam?
    • Zobacz profil
    • Automat Weryfikujący Regulację i Lambdę
  • Otrzymane polubienia: 865
Odp: [INNE] Ekran komputera pokładowego w pythonie
« Odpowiedź #24 dnia: 18 Marca 2017, 22:15:52 »
Po pierwsze, funkcja __init__ wykonuje się tylko raz, więc pakowanie tam warunków nie ma sensu. Po drugie, funkcja __init__ nie ma dostępu do słownika (state). Wynika to wprost z argumentów, jakie ona przyjmuje. Moja propozycja jest taka: w __init__ wczytujesz oba tła (jako moj_obrazek i moj_obrazek2), a następnie w _render sprawdzasz kierunek i dopiero wtedy albo używasz moj_obrazek i nie robisz nic, albo moj_obrazek2 i rysujesz wszystko.
Xoov
Powyższy post wyraża jedynie opinię autora w chwili publikacji. Autor zastrzega sobie prawo do zmiany poglądów bez podawania przyczyny, jak również informowania o tym.

Offline jakubg1

  • Wydział Repozytorium
  • Wiadomości: 1492
  • MaSzyna ma szynę, szyna ma MaSzynę - na kołach.
    • Zobacz profil
  • Otrzymane polubienia: 1118
Odp: [INNE] Ekran komputera pokładowego w pythonie
« Odpowiedź #25 dnia: 19 Marca 2017, 09:40:34 »
Niestety teraz kończy się to jeszcze gorzej - wysypuje symulator.
Problem został dawno rozwiązany. Nikt nie musi już podawać rozwiązania.
« Ostatnia zmiana: 19 Marca 2017, 20:47:34 wysłana przez jakubg1 »
10 lat na forum MaSzyny!

Offline tmj

  • Zasłużony dla Symulatora
  • Wiadomości: 3808
    • Zobacz profil
  • Otrzymane polubienia: 2351
Odp: [INNE] Ekran komputera pokładowego w pythonie
« Odpowiedź #26 dnia: 21 Marca 2017, 03:03:58 »
Mierniki kołowe:
Czyli coś w stylu siłomierza traxxa. Figury ograniczonej krzywymi nie możemy narysować o ile mi wiadomo.
Mozliwym rozwiazaniem jest tutaj zwykle oszustwo: krzywa modelujesz jako osobny pasek geometrii, nalozony "na" ekran (czyli umieszczony pare mm przed nim zeby ograniczyc z-fighting) zawiniety w wymagany ksztalt i z przypisana ta sama tekstura, ktorej uzywa ekran. Rezerwujesz dla niego waski pas np na dole tekstury, i w kodzie pythona rysujesz tam odpowiedniej wielkosci wypelniony prostokat z dowolnymi bajerami, odpowiadajacy stopniowi wypelnienia krzywej... a z punktu widzenia uzytkownika wyglada to na rosnaca krzywa na ekranie.
« Ostatnia zmiana: 21 Marca 2017, 03:05:09 wysłana przez tmj »

Offline Stele

  • Zasłużony dla Symulatora
  • Wiadomości: 10133
    • Zobacz profil
  • Otrzymane polubienia: 2609
Odp: [INNE] Ekran komputera pokładowego w pythonie
« Odpowiedź #27 dnia: 21 Marca 2017, 12:56:09 »
No ale tu już chyba lepiej dawać maskę w pythonie, niż wracać do ekranów pseudocyfrowych, na dziurach i analogowych suwaczkach.
Mój kanał youtube

Offline tmj

  • Zasłużony dla Symulatora
  • Wiadomości: 3808
    • Zobacz profil
  • Otrzymane polubienia: 2351
Odp: [INNE] Ekran komputera pokładowego w pythonie
« Odpowiedź #28 dnia: 21 Marca 2017, 14:58:47 »
To juz imo kwestia gustu, lenistwa (w sensie, dla mnie wymodelowanie paska jest latwiejsze/szybsze niz zabawy w dodatkowe oskryptowanie) jakosci efektu koncowego i wymaganych zasobow. Przy odrebnym elemencie nie ma na przyklad wiekszych problemow z rysowaniem takich rzeczy jak wybrana wartosc tempomatu, poruszajaca sie plynnie 'co do piksela' i dostosowana do orientacji krzywej, jaka by ona nie byla; nie trzeba tu sie bawic w zadne trygonometrie, obracanie itp. Odpada tez zuzycie pamieci na maske, a i operacje graficzne na waskim prostokatnym elemencie powinny byc szybsze niz aplikacja maski, bo mamy do czynienia z duzo mniejsza powierzchnia.
« Ostatnia zmiana: 21 Marca 2017, 15:01:31 wysłana przez tmj »

Offline Balaclava

  • Zasłużony dla Symulatora
  • Wiadomości: 936
  • vel. krzysiuup
    • Zobacz profil
  • Otrzymane polubienia: 726
Odp: [INNE] Ekran komputera pokładowego w pythonie
« Odpowiedź #29 dnia: 25 Maja 2017, 16:48:05 »
Nieco usprawniona wersja kodu odpowiedzialnego za zapis przebiegu do pliku.
1. Doklejamy poniższy kod na koniec metody __init__
# przeniesienie ścieżki do funkcji zapisującej
self.lookup_path = lookup_path
# zapisywanie ostatniej sekundy od liczenia przebiegu
self.last_time_update = 0
# losowanie przebiegustartowego
self.kilometry = PS+(random()*PL)+(1+self.rok-RokProd)*PR+self.dzis*PD
# ostatni zapisany przebieg
self.kilometry_z = 0
try:
with open(lookup_path + "tacho.txt", "r") as tacho_file:
tempkm = tacho_file.read()
if tempkm == "":
    raise IOError
except IOError:
tempkm = randint(1, 499000)
finally:
self.kilometry = float(tempkm)
self.kilometry_z = self.kilometry
with open(lookup_path + "tacho.txt", "w") as tacho_file:
tacho_file.write(str(tempkm))
2. Na końcu funkcji render dopisujemy:
#zapis stanu licznika do pliku
if self.kilometry>(self.kilometry_z + (0.1+0.005*speed)):
    with open(self.lookup_path + "tacho.txt", 'w') as tacho_file:
tacho_file.write(str(self.kilometry))
self.kilometry_z = self.kilometry
« Ostatnia zmiana: 09 Lipca 2017, 22:51:58 wysłana przez KrzysztofGliwice »
Dokumentacja dla przyszłych pokoleń deweloperów:
MaSzynowa Wiki
Narzędzia deweloperskie - Blender