To wielostronicowy widok tej sekcji do wydrukowania. Kliknij aby wydrukować.

Wróć do zwykłego widoku tej strony.

Dokumentacja Symulatora Okrążenia

Tutaj znajdują się instrukcje jak korzystać z symulacji okrążenia wyścigowego w środowisku Matlab.

Wstęp

W wypisanych poniżej podstronach znajdują się elementy dokumentacji zawierające informacje o poszczególnych jej elementach, ułożone wedle elementu bolidu (opony, układ napędowy etc.). Symulacja NIE jest naszego autorstwa, oryginalni autorzy to zespół Baltic Racing.

Linki do repozytorium:
Oryginał: Repozytorium Baltic Racing

Wraz z postępem prac dokumentacja będzie aktualizowana.

1 - paramtery akumulatora

działanie/obliczanie zmiennych akumulaotra

Wstęp

calculateAccumulatorData.m - jest to opisywany plik

DZIAŁANIE PLIKU

  1. pierwsze 4 linie służą do ładowania danych z plików MAT do zmiennych w skrypcie.

  2. Następnie zapisane są funkcje, które służą do liczenia poszczególnych danych.

Accumulator.V_i(i) = sum(Accumulator.Voltage_Cellpack(:,i)); - Oblicza sumę napięć wszystkich ogniw w akumulatorze dla danego punktu czasowego (i), przechowuje tę wartość w Accumulator.V_i(i).

Accumulator.A_accu_cell(i) = P_el(i) / Accumulator.V_i(i) / setup.nZellen_Parallel; - Oblicza prąd akumulatora dla danego punktu czasowego (i) korzystając z mocy elektrycznej (P_el), napięcia (Accumulator.V_i(i)) i liczby ogniw równoległych (setup.nZellen_Parallel).

Accumulator.Current_Cellpack_Pointer(i) - Określa wskaźnik aktualnego prądu dla pakietu ogniw w 0,1A na podstawie mocy elektrycznej i napięcia.

Warunki “if” sprawdzają i ograniczają wartość Accumulator.Current_Cellpack_Pointer(i) w określonym zakresie.

Accumulator.VirtualCurrent_Cellpack(i) - Oblicza wirtualny prąd dla pakietu ogniw na podstawie skorygowanych danych rozładowania.

Accumulator.Energy_Cellpack(i) - Oblicza zużycie energii dla pakietu ogniw w jednostkach Ah na podstawie wirtualnego prądu i czasu.

Accumulator.Energy_Cellpack_Total(i+1) - Sumuje całkowite zużycie energii do tego punktu czasowego.

Accumulator.Capacity_Cellpack(1:131,i+1) - Aktualizuje pojemność pakietu ogniw na podstawie zużycia energii.

Accumulator.SOC_Cellpack(1:131,i+1) - Oblicza stan naładowania (SOC) pakietu ogniw na podstawie aktualnej i początkowej pojemności.

Accumulator.SOC_Pointer(1:131,i+1) - Określa wskaźnik SOC w milicentylach na podstawie obliczonego SOC.

Accumulator.Current_Cellpack_Pointer_Voltage(1,i+1) - Określa wskaźnik napięcia pakietu ogniw na podstawie obliczonego wskaźnika prądu.

Kolejne dwa warunki if ograniczają wartości wskaźnika napięcia i SOC do dopuszczalnego zakresu.

W bloku try-catch jest próba dostępu do danych napięcia pakietu ogniw na podstawie obliczonych wskaźników prądu i SOC. Jeśli operacja się nie powiedzie, kod nie rzuca błędem.

2 - paramtery akumulatora

interfejs do wprowadzania zmiennych akumulatora

Wstęp

Interfejs i jego oddziaływanie poszczególnych danych. Dany plik zaprojektowany jest w App Designer i jest podzielony na Design View oraz Code View

Działanie

  1. Uruchomienie aplikacji:

Gdy aplikacja zostaje uruchomiona, jej konstruktor “Accumulator” jest wywoływany. Tworzy on interfejs użytkownika poprzez wywołanie metody createComponents. Następnie uruchamiana jest funkcja startupFcn, która inicjuje działanie aplikacji poprzez załadowanie danych, obliczenie i wyświetlenie pojemności akumulatora oraz zmianę schematu kolorów interfejsu.

AccumulatorSetupUIFigure: Główne okno aplikacji.

AccumulatorPanel: Panel zawierający wszystkie komponenty interfejsu użytkownika związane z akumulatorem.

Przyciski: SaveButton, ResetButton, DeleteCellButton, SaveCellButton.

Pola edycji numerycznej: NominalVoltageVEditField, CellCapacitymAhEditField, CellsInParallelEditField, CellsInRowEditField, itp.

Etykiety: OverallCapacityLabel, NumberofCellsLabel, OverallCellWeightLabel, AccumulatorVoltageLabel, itp.

SelectCellDropDown: Lista rozwijana umożliwiająca wybór typu ogniwa.

CellDataPanel: Panel zawierający dane dotyczące pojedynczego ogniwa.

app.CallingApp = mainapp;

loadData(app) – Wczytuje dane z aplikacji głównej

updateCapacity(app) – aktualizuje całkowitą pojemność akumulatora

changeColorScheme(app) – wiele zmiennych obsługujących zmiane kolorów interfejsu

  1. Zamykanie aplikacji:

Gdy użytkownik próbuje zamknąć aplikację, wywoływana jest funkcja zwrotna AccumulatorSetupUIFigureCloseRequest, która zapisuje dane i usuwa aplikację.

  1. Wprowadzanie danych:

Wartości wprowadzone przez użytkownika, takie jak pojemność ogniwa, liczba ogniw w rzędzie i równolegle, są automatycznie aktualizowane poprzez funkcje zwrotne, takie jak CellCapacitymAhEditFieldValueChanged czy CellsinrowEditFieldValueChanged. Po zmianie tych danych, wywoływana jest funkcja updateCapacity, która aktualizuje wyświetlane wartości związane z pojemnością akumulatora.

  1. Podsumowanie

Interfejs umożliwia użytkownikwi prowadzanie danych dotyczących akumulatora, ich zapisywanie, resetowanie oraz prezentuje obliczone wartości. Dodatkowo, interfejs jest dostosowywany do zdefiniowanego schematu kolorów.

3 - calculateSteeringData

Funkcja służąca do obliczenia kątów skrętu, odchylenia, kierownicy, obrotu odchylenia i ackermanna

Opisany plik: calculateSteeringData.m

Wywoływanie funkcji i wartości które zwraca

Funkcja przyjmuje 16 parametrów:

wheelbase - rozstaw osi
R - promień łuku
lr - odległość tylnej osi od środka masy
lf - odległość przedniej osi od środka masy
vV - prędkość bolidu
FWZ_fl, FWZ_rl, FWZ_fr, FWZ_rr - nacisk na poszczególne opony (nieużywane)
track_f - szerokość toru
cZ_fl, cZ_fr, cZ_rl, cZ_rr - interpolowane sztywności poszczególnych opon (nieużywane)
alpha_f - kąt poślizgu przedniej osi
alpha_r - kąt poślizgu tylnej osi

Funkcja zwraca 14 parametrów:

delta - kąt skrętu
beta - kąt odchylenia (Schwimmwinkel)
psi1 - obrót odchylenia (Gierrate)
alpha_f, alpha_r - kąty poślizgu osi
alpha_fr, alpha_fl, alpha_rr, alpha_rl - kąty poślizgu poszczególnych opon
delta_fl - kąt skrętu lewego koła
delta_fr - kąt skrętu prawego koła
delta_sw - kąt skrętu kierownicy
ackermann - "Kąt Ackermanna to geometria związana z układem kierowniczym pojazdu, która określa różnicę w kącie skrętu pomiędzy przednimi kołami w momencie skręcania."
ackermannPercent - ackermann w wartości procentowej

Kąt odchylenia i obrót odchylenia grafika poglądowa

Kąt odchylenia i obrót odchylenia grafika poglądowa

Ackermann grafika poglądowa

Ackermann grafika poglądowa

Działanie funkcji

Sprawdzenie kierunku skrętu:

%%Sprawdzenie kierunku zakrętu, gdy R jest dodatnie - skręt w prawo
 if R > 0
        f = -1;
    else
        f = 1;
    end

Obliczanie kątów skrętu, odchylenia, kierownicy i obrotu odchylenia:

delta = wheelbase/1000/R;  
%kąt skrętu (dzielenie przez 1000 w celu konwersji na metry)

beta = f*atan((lr/1000)/sqrt(R^2-(lr/1000)^2)); 
%kąt odchylenia

psi1 = vV/R;
%kąt obrotu odchylenia

delta_sw = delta * 180/pi * 5.093;
%kąt skrętu kierownicy (5.093 to mnożnik zależny od układu kierowniczego)

Obliczanie kątów skrętu dla koła wewnętrznego i zewnętrznego:

if R > 0    %Gdy R jest dodatnie - skręt w prawo, a prawe koło jest wewnętrznym do łuku
    delta_fl = atan((wheelbase/1000)/(R+(track_f/1000/2)));     %kąt skrętu lewego koła
    delta_fr = atan((wheelbase/1000)/(R-(track_f/1000/2)));     %kąt skrętu lewego koła

    ackermann = atan(wheelbase/((wheelbase/tan(delta_fl))-track_f));    %wartość ackermanna
    ackermannPercent = delta_fr/ackermann*100;  %procentowa wartość ackermanna
else
    delta_fl = atan((wheelbase/1000)/(R-(track_f/1000/2))); 
    delta_fr = atan((wheelbase/1000)/(R+(track_f/1000/2)));           

    ackermann = atan(wheelbase/((wheelbase/tan(delta_fr))-track_f));
    ackermannPercent = delta_fl/ackermann*100;                       
end  

4 - Inicjalizacja powtórki symulacji

initializeSimulationReplay.m

Wstęp

Przebieg inicjalizacji powtórki symulacji w pliku initializeSimulationReplay.m

Funkcja initalizeSimulationReplay()

Opisywane niżej linie są wykresami prezentującymi trasę przejechaną przez bolid w trakcie symulacji.
Na początku funkcja ładuje plik z zapisem symulacji przejazdu oraz czyści linie wyświetlane w interfejsie.

Następnie na elemencie app.RunNumberSpinner program próbuje wykonać poniższe operacje (zablokować interakcje z nim oraz ustawić jego wartość na 1). Jeśli wystąpi jakiś błąd i nie będzie się tego dało zrobić to jest włączany oraz jego zakres jest zmieniany na od 1 do ilości przejazdów.


RunNumberSpinner

RunNumberSpinner

drawPedalPlots() - tworzy elementy obrazujące nacisk pedałów. Deklaracja funkcji na końcu pliku.

Następnie ustawiane są kolory zależne od wybranego motywu.

Funkcja hold() z parametrem ‘on’ sprawia, że kolejne rysowane linie nie wymazują poprzednich. Następnie na GUI są przeprowadzane poniższe operacje:

Do struktory o nazwie saveFileData przypisywane są wszystkie wartości z wybranego wcześniej pliku z zapisem przejazdu (saveFile), żeby później te informacje zostały wpisane do elementów GUI (app.DropDown).

Wykonując poniższe funkcje program kolejno:
-zmienia limity rysowania linii
-rysuje zaznaczone w checkboxach rodzaje linii
-rysuje apexy jeśli odpowiedni checkbox jest zaznaczony

gdzie:

gdzie:


Parametr ‘app’ - aplikacja
Parametr ‘1’ - numer przejazdu
Parametr ‘saveFile’ - result; plik z zapisem telemetrii

Funkcja drawPedalPlots()

Ustawia właściwości elementów obrazujących nacisk pedałów.

Funkcja recordPedalPlot()

Pobierając plik z telemetrią ustawia wartości elementów obrazujących nacisk pedałów.

5 - Inicjowanie Opon do symulacji

Wdrożenie parametrów opon do symulacji LapSim (plik LoadTIR.m)

Wstęp

Plik LoadTIR.m umożliwia załadowanie pliku z danymi opony do symulacji. Wszystkie odniesienia do danej linii kodu odnoszą się do pliku dostępnego w oryginalnym repozytorium, bez żadnych uprzednich modyfikacji kodu.

Wybór pliku

Plik rozpoczyna sie deklaracją funkcji loadTIR z parametrem w postaci lokalizacji pliku zawierającego parametry opony. Parametr ten pojawia się także w plikach Conti_Tire_Plots zarówno dla obliczeń w płaszczyźnie wzdłużnej i poprzecznej, a także w pliku Find_maximum_corner_speed. Celem modyfikacji rodzaju opony konieczne będzie dostosowanie kodu, aby możliwy był wybór większej ilości opon i przeprowadzenia obliczeń na ich parametrach.

Rys.1 Odwołania do lokalizacji pliku z parametrycznym opisem opony

Rys.1 Odwołania do lokalizacji pliku z parametrycznym opisem opony

Następnie w linii 7 plik jest otwierany w trybie tylko do odczytu i inicjowane są dwie zmienne pełniące funkcję liczników.

Inicjacja parametrów

Rys.2 Fragment kodu zczytujący parametry opon z pliku

Rys.2 Fragment kodu zczytujący parametry opon z pliku

W pętli działającej do momentu zakończenia pliku zawierającego parametry zczytywane są kolejne parametry. Osobno przetwarzając każdą linijkę pliku. W pierwszej kolejności sprawdzane jest, czy dana linia kodu nie jest komentarzem bądź tytułem. korzystając z ustandaryzowanego sposobu wpisywania parametrów kolejne dane i ich nazwy są zczytywane i zapisywane do pamięci. Po zczytaniu danych plik jest zamykany i niepotrzebne dane są usuwane z pamięci.

Sprawdzenie masy

Rys.3 Podmiana masy

Rys.3 Podmiana masy

Ze względu na konflikt nazw zmiennych podmieniana jest nazwa zmiennej opisującej masę na nazwę pomocniczą.

Generowanie opon

Korzystając z pobranych wcześniej danych generowana jest parametryczna struktura opony.

Rys.4 Generowanie opon

Rys.4 Generowanie opon

Program przepisuje odczytane wcześniej dane do formatu właściwego, który ułatwia pracę nad danymi. Sprawdzane jest między innymi, czy odczytywana wartość ma format tekstowy czy liczbowy.

Rys.5 Dodawanie opisów opon

Rys.5 Dodawanie opisów opon

Finalnie zapisane dane są opisywane korzystając z nazw zmiennych.

6 - paramtery układu napędowego

interfejs do wprowadzania zmiennych układu napędowego

Wstęp

Interfejs i jego oddziaływanie poszczególnych danych. Dany plik zaprojektowany jest w App Designer i jest podzielony na Design View oraz Code View

DrivetrainSetupUIFigure: Objekt reprezentujący figurę w UI PowertrainDataPanel: Panel przedstawiający dane o układzie napędowym UITable: Tablica przedstawiająca tablicę w UI idle_rpm1minEditField: Miejsce do edytowania obrotów na luzie TorquemultiplierEditField: Miejsce do edytowania mnożnika momentu obrotowego n_max1minEditField: Miejsce do edycji maksymalnych obrotów DrivetrainEfficencyEditField: Miejsce do edycji efektywności układu napędowego LayoutDropDown: Rozwijane UI do wyboru układu LayoutDropDownLabel: Etykieta do rozwijanego elemntu UI PowertrainSwitch: Przycisk do wyboru układu napędowego EPowertrainParametersPanel: Panel zawierający parametry elektryczne układu napędowego InverterEfficiencyEditField: Miejsce do edycji efektywności falownika PowerlimitWEditField: Miejsce do edycji limitu mocy w watach DeleteEngineButton: Przycisk, który usuwa parametry silnika EnginePresetDropDown: Rozwijany element UI do wybory presetów silnika Panel_2: Obiekt reprezentujący panel. z_chaindriveEditField: Obiekt NumericEditField reprezentujący pole edycji dla napędu łańcuchowego. z_sprocketEditField: Obiekt NumericEditField reprezentujący pole edycji dla zębatki. ChaindriveSingleGearsetCheckBox: Obiekt CheckBox reprezentujący pole wyboru dla pojedynczego układu napędowego łańcuchowego. loadPanel: Obiekt Panel reprezentujący panel dla obciążenia. TY20BaselineButton: Obiekt Button reprezentujący przycisk dla podstawowej konfiguracji TY20. SaveButton: Obiekt Button reprezentujący przycisk do zapisu. ResetButton: Obiekt Button reprezentujący przycisk do resetowania. ElectricBaselineButton: Obiekt Button reprezentujący przycisk dla podstawowej konfiguracji elektrycznej. TY19BaselineButton: Obiekt Button reprezentujący przycisk dla podstawowej konfiguracji TY19. ChaindrivePanel: Obiekt Panel reprezentujący panel dla napędu łańcuchowego. i_PEditField: Obiekt NumericEditField reprezentujący pole edycji dla i_P. GearboxPanel: Obiekt Panel reprezentujący panel dla skrzyni biegów. n_downshift1minEditField: Obiekt NumericEditField reprezentujący pole edycji dla obrotów przy redukcji biegów. EnableGearboxCheckBox: Obiekt CheckBox reprezentujący pole wyboru dla włączenia skrzyni biegów. PlotGearboxdataButton: Obiekt Button reprezentujący przycisk do generowania wykresu danych skrzyni biegów. GearboxTable: Obiekt Table reprezentujący tabelę dla danych skrzyni biegów. Button_4: Obiekt Button reprezentujący kolejny przycisk. Button_3: Obiekt Button reprezentujący jeszcze jeden przycisk. n_shift1minEditField: Obiekt NumericEditField reprezentujący pole edycji dla obrotów przy zmianie biegów. t_shiftsEditField: Obiekt NumericEditField reprezentujący pole edycji dla czasu zmiany biegów. UIAxes3: Obiekt UIAxes reprezentujący osie do generowania wykresów. UIAxes2: Obiekt UIAxes reprezentujący kolejne osie do generowania wykresów. UIAxes: Obiekt UIAxes reprezentujący jeszcze inne osie do generowania wykresów.

Klasa Drivetrain reprezentuje obiekt odpowiedzialny za aktualizację wykresu dla krzywych momentu i mocy silnika.

  • Obiekt głównej aplikacji
CallingApp   
  • Metoda updateMotorGraph(app) aktualizuje wykresy dla jednego silnika. Metoda ta pobiera dane z tabeli UITable, oblicza moc i moment dla każdej wartości obrotów, a następnie rysuje wykresy dla momentu i mocy.

  • Aktualizuje etykietę przekładni i zwraca wartość przekładni

i_tot = updateGearRatio(app);
  • Pobiera wartość mnożnika momentu
torque_multiplier = app.TorquemultiplierEditField.Value;
  • Pobiera dane z tabeli UITable
data = app.UITable.Data;
  • Separuje dane na dwie 1D tablice, dodając 0 na początku, ponieważ obie osie powinny zaczynać się od zera
x = [1; data(:,1)]; n = RPM
y = [0; data(:,2)] * torque_multiplier; M = Moment
  • Oblicza moc silnika dla danej wartości obrotów i momentu
p = zeros(1:size(x,1));
for n = 1 : length(x)
p(n) = (y(n) * x(n)) / 9.5488 / 1000;
end
  • Czyści wykres UIAxes, aby można go było ponownie utworzyć
cla(app.UIAxes,'reset');
  • Ustawia osie
app.UIAxes.XLabel.String='RPM [1/min]';
yyaxis(app.UIAxes,'left'); 
  • Rysuje wykres momentu
plot(app.UIAxes,x,y);
  • Zatrzymuje wykres, aby można było narysować nową oś
hold(app.UIAxes);
title(app.UIAxes,"Single Motor");
yyaxis(app.UIAxes,'right');
app.UIAxes.YLabel.String='Moc [kW]';
  • Rysuje wykres mocy
plot(app.UIAxes,x,p);
  • Wyłącza możliwość przybliżania dla wykresu
disableDefaultInteractivity(app.UIAxes);
  • Sprawdza, który układ silnika jest wybrany i dostosowuje liczbę silników
Motorsdropdown = app.LayoutDropDown.Value;
if (Motorsdropdown == "2 Motor RWD")
    numberMotors = 2;
elseif (Motorsdropdown == "1 Motor RWD")
    numberMotors = 1;
elseif (Motorsdropdown == "AWD")
    numberMotors = 4;
end
  • Oblicza moment wytworzony przez daną liczbę silników
y_2 = y * numberMotors;
p_2 = zeros(1:length(x));
  • Oblicza moc silników dla danej wartości obrotów i momentu
for n = 1 : length(x)
p_2(n) = (y_2(n) * x(n)) / 9.5488 / 1000;
end
  • Czyści wykres UIAxes2, aby można go było ponownie utworzyć
cla(app.UIAxes2,'reset');
  • Metoda rysująca wykresy dla przekładni wtórnej. x - Tablica wartości osi X. y_2 - Tablica wartości osi Y dla momentu obrotowego. p_2 - Tablica wartości osi Y dla mocy.

  • Motorsdropdown - Wybrany rodzaj silnika.

(void)drawPlotsWithX:(NSArray *)x y_2:(NSArray *)y_2 p_2:(NSArray *)p_2 Motorsdropdown:(NSString *)Motorsdropdown {
  • Aktualizuje przekładnię wtórną.
return Wartość całkowitego przekładniowego stosunku.
(double)updateGearRatio
return i_tot;
  • Zmienia schemat kolorów aplikacji.
(void)changeColorScheme

-Poniżej znajdują się zmienne reprezentujące kolory i style aplikacji. PrimaryColor: Kolor podstawowy aplikacji. OnPrimaryColor: Kolor tekstu na tle PrimaryColor. PrimaryVariantColor: Wariant koloru podstawowego aplikacji. OnPrimaryVariantColor: Kolor tekstu na tle PrimaryVariantColor. SecondaryColor: Kolor drugorzędny aplikacji. OnSecondaryColor: Kolor tekstu na tle SecondaryColor. BackgroundColor: Kolor tła aplikacji. OnBackgroundColor: Kolor tekstu na tle BackgroundColor. SurfaceColor: Kolor powierzchni aplikacji. OnSurfaceColor: Kolor tekstu na tle SurfaceColor. ErrorColor: Kolor błędu aplikacji. OnErrorColor: Kolor tekstu na tle ErrorColor. BorderType: Typ obramowania aplikacji. Host_Logo: Logo hosta aplikacji.

  • Ustawia kolor tła dla interfejsu użytkownika DrivetrainSetupUIFigure.
app.DrivetrainSetupUIFigure.Color = BackgroundColor;
  • Ustawia kolor czcionki dla etykiety Copyright2021BalticRacingbyEricDorniedenLabel.
app.Copyright2021BalticRacingbyEricDorniedenLabel.FontColor = OnBackgroundColor;
  • Ustawia kolor czcionki, tła i typ obramowania dla panelu PowertrainDataPanel.
app.PowertrainDataPanel.ForegroundColor = OnBackgroundColor;
app.PowertrainDataPanel.BackgroundColor = BackgroundColor;
app.PowertrainDataPanel.BorderType = BorderType;
  • Ustawia kolor czcionki, tła i typ obramowania dla panelu loadPanel.
app.loadPanel.ForegroundColor = OnSurfaceColor;
app.loadPanel.BackgroundColor = SurfaceColor;
app.loadPanel.BorderType = BorderType;
  • Ustawia kolor czcionki, tła i typ obramowania dla panelu Panel.
app.Panel.ForegroundColor = OnSurfaceColor;
app.Panel.BackgroundColor = SurfaceColor;
app.Panel.BorderType = BorderType;
  • Ustawia kolor czcionki, tła i typ obramowania dla panelu EPowertrainParametersPanel.
app.EPowertrainParametersPanel.ForegroundColor = OnSurfaceColor;
app.EPowertrainParametersPanel.BackgroundColor = SurfaceColor;
app.EPowertrainParametersPanel.BorderType = BorderType;
  • Ustawia kolor czcionki, tła i typ obramowania dla panelu ChaindrivePanel.
app.ChaindrivePanel.ForegroundColor = OnSurfaceColor;
app.ChaindrivePanel.BackgroundColor = SurfaceColor;
app.ChaindrivePanel.BorderType = BorderType;
  • Ustawia kolor czcionki, tła i typ obramowania dla panelu GearboxPanel.
app.GearboxPanel.ForegroundColor = OnSurfaceColor;
app.GearboxPanel.BackgroundColor = SurfaceColor;
app.GearboxPanel.BorderType = BorderType;
  • Ustawia kolor czcionki dla przycisku PowertrainSwitch.
app.PowertrainSwitch.FontColor = OnSurfaceColor;
  • Ustawia kolor czcionki dla etykiety LayoutDropDownLabel oraz kolor tła i czcionki dla rozwijanej listy LayoutDropDown.
app.LayoutDropDownLabel.FontColor = OnSurfaceColor;
app.LayoutDropDown.BackgroundColor = PrimaryColor;
app.LayoutDropDown.FontColor = OnPrimaryColor;

Analogicznie są ustawiane inne kolory.

  • Funkcja saveData zapisuje dane z aplikacji do obiektu CallingApp. app - Obiekt aplikacji zawierający dane do zapisania.
function saveData(app)
  • Zapisuje dane z rozwijanej listy EnginePresetDropDown do obiektu CallingApp.engineData
app.CallingApp.engineData = app.EnginePresetDropDown.Items;
  • Zapisuje wartość z pola PowerlimitWEditField do obiektu CallingApp.p_max
app.CallingApp.p_max = app.PowerlimitWEditField.Value;
  • Zapisuje wartość z pola DrivetrainEfficencyEditField do obiektu CallingApp.drivetrain_eff
app.CallingApp.drivetrain_eff = app.DrivetrainEfficencyEditField.Value;

Analogicznie są zapisywane inne wartości.

  • Sprawdza, który układ silnika jest wybrany i dostosowuje liczbę silników w obiekcie CallingApp.num_motors
var Motorsdropdown = app.LayoutDropDown.Value;
  • Wybiera odpowiednią liczbę silników na podstawie wartości wybranej z rozwijanej listy. Motorsdropdown - wartość wybrana z rozwijanej listy
if (Motorsdropdown == "2 Motor RWD") {
    app.CallingApp.num_motors = 2;
} else if (Motorsdropdown == "1 Motor RWD") {
    app.CallingApp.num_motors = 1;
} else if (Motorsdropdown == "AWD") {
    app.CallingApp.num_motors = 4;
}
  • Ustawienie elementów rozwijanej listy EnginePresetDropDown na wartości z app.CallingApp.engineData
app.EnginePresetDropDown.Items = app.CallingApp.engineData;
  • Ustawienie wartości pola PowerlimitWEditField na app.CallingApp.p_max
app.PowerlimitWEditField.Value = app.CallingApp.p_max;
  • Ustawienie wartości pola DrivetrainEfficencyEditField na app.CallingApp.drivetrain_eff
app.DrivetrainEfficencyEditField.Value = app.CallingApp.drivetrain_eff;
  • Ustawienie wartości pola TorquemultiplierEditField na app.CallingApp.trq_multiplier
app.TorquemultiplierEditField.Value = app.CallingApp.trq_multiplier;
  • Ustawienie danych tabeli GearboxTable na app.CallingApp.i_param
app.GearboxTable.Data = app.CallingApp.i_param;
  • Ustawienie wartości pola InverterEfficiencyEditField na app.CallingApp.invertor_eff
app.InverterEfficiencyEditField.Value = app.CallingApp.invertor_eff;
  • Ustawienie wartości pola EnableGearboxCheckBox na app.CallingApp.gearbox
app.EnableGearboxCheckBox.Value = app.CallingApp.gearbox;

Analogicznie są ustawiane inne pola wartości.

  • Ustawienie tekstu rozwijanej listy EngineLayoutDropDown w zależności od wartości app.CallingApp.num_motors
if (app.CallingApp.num_motors == 1) {
    app.LayoutDropDown.Value = "1 Motor RWD";
} else if (app.CallingApp.num_motors == 2) {
    app.LayoutDropDown.Value = "2 Motor RWD";
} else if (app.CallingApp.num_motors == 4) {
    app.LayoutDropDown.Value = "AWD";
}
  • Aktywacja/dezaktywacja parametrów E/C Panelu w zależności od wartości pola PowertrainSwitch
if (app.PowertrainSwitch.Value == "Electric") {
    app.PowerlimitWEditField.Enable = true;
    app.InverterEfficiencyEditField.Enable = true;
} else {
    app.PowerlimitWEditField.Enable = false;
    app.InverterEfficiencyEditField.Enable = false;
}
  • Dla każdego wiersza w tabeli, funkcja wywołuje funkcję updateGearRatio(app) w celu obliczenia całkowitego przełożenia. Następnie funkcja aktualizuje wartości w drugiej i trzeciej kolumnie tabeli na podstawie obliczonych wartości.
for i = 1:size(app.GearboxTable.Data, 1)
    i_tot = updateGearRatio(app);
    
    app.GearboxTable.Data(i,2) = app.GearboxTable.Data(i,1) * i_tot;
    app.GearboxTable.Data(i,3) =  app.n_max1minEditField.Value/(30/pi*app.GearboxTable.Data(i,2)/app.CallingApp.R0)*3.6;
  • Włącza możliwość edycji pól związanych z przesunięciami biegów.
app.t_shiftsEditField.Enable
  • Włącza lub wyłącza możliwość edycji etykiety pola t_shiftsEditField.
app.t_shiftsEditFieldLabel.Enable
  • Włącza lub wyłącza możliwość edycji pola n_shift1minEditField.
app.n_shift1minEditField.Enable

Analogicznie są włączabne możliwości edycji w innych polach.

  • Kod wykonywany po utworzeniu komponentu
function startupFcn(app, mainapp)
  • Aktualizuje wykres momentu i mocy silnika na podstawie danych z UITable
updateMotorGraph(app);
  • Callback edycji komórki: UITable
function UITableCellEdit(app, event)
updateMotorGraph(app);
  • Funkcja wywoływana po zmianie wartości: LayoutDropDown
function LayoutDropDownValueChanged(app, event)
updateMotorGraph(app);
  • Funkcja wywoływana po zmianie wartości: TorquemultiplierEditField
function TorquemultiplierEditFieldValueChanged(app, event)
updateMotorGraph(app);

Analogicznie są wywoływane inne funckje

  • Dodaje wpis do UITable
data = app.UITable.Data;
app.UITable.Data = [data; [0 0]];
  • Funkcja wywoływana po naciśnięciu przycisku Button_2. Usuwa ostatni wpis w tabeli UITable.
    data = app.UITable.Data;
    data((length(data)),:) = [];
    app.UITable.Data = data;
  • Funkcja wywoływana przy próbie zamknięcia okna DrivetrainSetupUIFigure. Zapisuje dane i wyłącza przycisk Drivetrain Options w głównym oknie aplikacji.
function DrivetrainSetupUIFigureCloseRequest(app, event)
    saveData(app);
    app.CallingApp.DrivetrainButton.Enable = 'on';
    delete(app)
  • Funkcja wywoływana po naciśnięciu przycisku SaveButton.
function SaveButtonPushed(app, event)
    saveData(app);
  • Funkcja wywoływana po naciśnięciu przycisku ResetButton.
function ResetButtonPushed(app, event)
    loadData(app);
  • Funkcja wywoływana po zmianie wartości pola InverterEfficiencyEditField. Aktualizuje wykres silnika.
function InverterEfficiencyEditFieldValueChanged(app, event)
    updateMotorGraph(app);
  • Funkcja wywoływana po zmianie wartości przełącznika PowertrainSwitch. Aktualizuje parametry zależne od rodzaju napędu.
function PowertrainSwitchValueChanged(app, event)
    value = app.PowertrainSwitch.Value;
    if value == "Electric"      
        app.PowerlimitWEditField.Enable = true;
        app.InverterEfficiencyEditField.Enable = true;
        app.CallingApp.ptype = 1; 
    else   
        app.PowerlimitWEditField.Enable = false;
        app.InverterEfficiencyEditField.Enable = false;
        app.CallingApp.ptype = 0;      
    end
    updateMotorGraph(app)
    updateGearRatio(app)
  • Funkcja wywoływana po naciśnięciu przycisku Button_3. Dodaje nowy wiersz do tabeli GearboxTable.
function Button_3Pushed(app, event)
    data = app.GearboxTable.Data;
    app.GearboxTable.Data = [data; 0,0,0];
  • Funkcja wywoływana po naciśnięciu przycisku Button_4. Usuwa ostatni wpis w tabeli GearboxTable.
function Button_4Pushed(app, event)
    Deletes the last entry in the UITable
    data = app.GearboxTable.Data;
    data((size(data,1)),:,:) = [];
    app.GearboxTable.Data = data;
  • Funkcja wywoływana po zmianie wartości pola i_PEditField. Aktualizuje wykres silnika.
function i_PEditFieldValueChanged(app, event)
    updateMotorGraph(app);
  • Funkcja wywoływana po naciśnięciu przycisku PlotGearboxdataButton. Wyświetla wykres danych z tabeli GearboxTable.
function PlotGearboxdataButtonPushed(app, event)
    plotGearboxData(app.GearboxTable.Data,app.n_shift1minEditField.Value,app.t_shiftsEditField.Value,app.n_max1minEditField.Value);
  • Funkcja wywoływana po edycji komórki w tabeli GearboxTable. Aktualizuje przekładnie.
function GearboxTableCellEdit(app, event)
    updateGearRatios(app);      
  • Funkcja wywoływana po zmianie wartości pola EnableGearboxCheckBox. Aktualizuje przekładnie.
function EnableGearboxCheckBoxValueChanged(app, event)
    updateGearbox(app);    
  • Funkcja wywoływana po naciśnięciu przycisku TY19BaselineButton. Ustawia wartości związane z układem napędowym dla trybu spalinowego, ładuje dane z pliku “Dynojet Momentenverlauf.mat”, ustawia parametry układu napędowego dla symulacji oraz wywołuje funkcję loadData(app) w celu załadowania danych.
function TY19BaselineButtonPushed(app, event)
    app.PowertrainSwitch.Value = "Combustion";
    app.PowerlimitWEditField.Enable = false;
    app.InverterEfficiencyEditField.Enable = false;
    app.EnableGearboxCheckBox.Value = 1;

    triumphEngine = load('Dynojet Momentenverlauf.mat'); 

ptype - Typ napędu. n_max - Maksymalna prędkość obrotowa. i_param - Parametry prądowe. i_P - Wzmocnienie regulatora prądu. z_chaindrive - Liczba zębów w łańcuchu napędowym. z_sprocket - Liczba zębów w zębatce. gearbox - Przełożenie skrzyni biegów. engine_param - Parametry silnika. num_motors - Liczba silników. idleRPM - Prędkość obrotowa na biegu jałowym.

    app.CallingApp.ptype = 0; 
    app.CallingApp.n_max = 11000;
    app.CallingApp.i_param = [1.857; 1.565; 1.35; 1.238; 1.136];
    app.CallingApp.i_P = 1.848;
    app.CallingApp.z_chaindrive = 37;
    app.CallingApp.z_sprocket = 11;  
    app.CallingApp.gearbox = 1;
    app.CallingApp.engine_param = [triumphEngine.n(:) triumphEngine.M(:)];
    app.CallingApp.num_motors = 1;
    app.CallingApp.idleRPM = 2000;
    loadData(app);
end
  • Funkcja wywoływana po naciśnięciu przycisku ElectricBaselineButton, ustawia wartości związane z układem napędowym dla trybu elektrycznego, umożliwia edycję pól PowerlimitWEditField i InverterEfficiencyEditField, wyłącza pole EnableGearboxCheckBox, ustawia parametry układu napędowego dla symulacji oraz wywołuje funkcję loadData(app) w celu załadowania danych.
function ElectricBaselineButtonPushed(app, event)
    app.PowertrainSwitch.Value = "Electric";
    app.PowerlimitWEditField.Enable = true;
    app.InverterEfficiencyEditField.Enable = true;
    app.EnableGearboxCheckBox.Value = 0;

    app.CallingApp.ptype = 1; 
    app.CallingApp.n_max = 6000;
    app.CallingApp.i_param = 1;
    app.CallingApp.i_P = 1;
    app.CallingApp.z_chaindrive = 66;
    app.CallingApp.z_sprocket = 17;     
    app.CallingApp.gearbox = 0;
    app.CallingApp.engine_param = [0 140; 1000 140; 2000 138; 3000 136; 4000 135; 5000 127; 6000 115];
    app.CallingApp.num_motors = 2;
    app.CallingApp.idleRPM = 0;

    loadData(app);
end
  • Funkcja wywoływana po naciśnięciu przycisku TY20BaselineButton, ustawia wartości związane z układem napędowym dla trybu spalania, ładuje dane z pliku “Dynojet Momentenverlauf.mat”, Ustawia parametry układu napędowego dla symulacji oraz wywołuje funkcję loadData(app) w celu załadowania danych.
function TY20BaselineButtonPushed(app, event)
    app.PowertrainSwitch.Value = "Combustion";
    app.PowerlimitWEditField.Enable = false;
    app.InverterEfficiencyEditField.Enable = false;
    app.EnableGearboxCheckBox.Value = 1;

    triumphEngine = load('Dynojet Momentenverlauf.mat'); 

    app.CallingApp.ptype = 0; 
    app.CallingApp.n_max = 11000;
    app.CallingApp.i_param = [2.579; 1.720; 1.429; 1.238];
    app.CallingApp.i_P = 1.848;
    app.CallingApp.z_chaindrive = 37;
    app.CallingApp.z_sprocket = 11;  
    app.CallingApp.gearbox = 1;
    app.CallingApp.engine_param = [triumphEngine.n(:) triumphEngine.M(:)];
    app.CallingApp.num_motors = 1;
    app.CallingApp.idleRPM = 2000;

    loadData(app);
  • Funkcja wywoływana po zmianie wartości pola ChaindriveSingleGearsetCheckBox, ustawia wartość zmiennej i_chain na podstawie wartości pól związanych z przekładnią, jeśli pole ChaindriveSingleGearsetCheckBox jest zaznaczone, włącza pole związane z ilością zębów koła zębatego.
function ChaindriveSingleGearsetCheckBoxValueChanged(app, event)
    value = app.ChaindriveSingleGearsetCheckBox.Value;

    if value
        app.i_chain = app.z_sprocketEditField.Value * app.z_chaindriveEditField.Value;
        app.z_sprocketEditField.Enable =  'true';
    else
        app.i_chain = 1;
  • Funkcja wywoływana po zmianie wartości w polu EnginePresetDropDown, aktualizuje parametry silnika na podstawie wybranego silnika oraz Aktualizuje interfejs użytkownika.
function EnginePresetDropDownValueChanged(app, event)
    value = app.EnginePresetDropDown.Value;
  • Wczytaj plik .mat dla wybranego silnika
engine = load([value '.mat']); 
  • Wczytaj parametry silnika z pliku .mat
app.CallingApp.engine_param = [engine.n(:) engine.M(:)];
  • Funkcja wywoływana po naciśnięciu przycisku SaveEngineButton, zapisuje zmienne silnika do pliku .mat oraz dodaje nowy silnik do listy rozwijanej, jeśli nazwa nie jest już częścią listy.
function SaveEngineButtonPushed(app, event)
    data = app.UITable.Data;     
    n = data(:,1);
    M = data(:,2);
  • Otwiera okno dialogowe do zapisu pliku
    [filename, pathname] = uiputfile('*.mat','Zapisz zmienne silnika jako','NowySilnik.mat');
    newfilename = fullfile(pathname, filename);
  • Zapisuje plik z podanymi parametrami
    save(newfilename, 'n','M');
  • Dodaje nowy silnik do listy rozwijanej, jeśli nazwa nie jest już częścią listy.
    if ~strcmp(app.EnginePresetDropDown.Items, filename(1:end-4))
    data = app.EnginePresetDropDown.Items;
    data(end) = [];
    app.EnginePresetDropDown.Items = [data filename(1:end-4) "NowySilnik"];
    app.CallingApp.engineData = app.EnginePresetDropDown.Items;
  • Funkcja wywoływana po naciśnięciu przycisku DeleteEngineButton, usuwa wybrany silnik z listy rozwijanej oraz aktualizuje interfejs użytkownika.
function DeleteEngineButtonPushed(app, event)
    selected = app.EnginePresetDropDown.Value;
  • Sprawdza, czy użytkownik próbuje usunąć wpis “NowySilnik”
    if selected == "NowySilnik"
    app.CallingApp.engine_param = [0 0; 1000 0; 2000 0; 3000 0; 4000 0; 5000 0; 6000 0];
    return;
end
    data = app.EnginePresetDropDown.Items;
  • Znajduje indeks wybranego silnika i usuwa go z listy
    ind = find(strcmp(data,selected));
    data(ind) = [];
  • Aktualizuj listę rozwijaną
    app.EnginePresetDropDown.Items = data;
    app.CallingApp.engineData = data;
  • Przełącza na pierwszy silnik
    app.EnginePresetDropDown.Value = app.EnginePresetDropDown.Items(1);
  • Tworzenie UIFigure i komponentów
function createComponents(app)
  • Ustawia widoczność figury na wyłączoną.
app.DrivetrainSetupUIFigure = uifigure('Visible', 'off');
  • Ustawia pozycję figury na [100 100 1107 764].
app.DrivetrainSetupUIFigure.Position = [100 100 1107 764];
  • Ustawia nazwę figury na ‘Drivetrain Setup’.
app.DrivetrainSetupUIFigure.Name = 'Drivetrain Setup';
  • Ustawia ikonę figury na ‘Baltic.png’.
app.DrivetrainSetupUIFigure.Icon = 'Baltic.png';
  • Wyłącza możliwość zmiany rozmiaru figury.
app.DrivetrainSetupUIFigure.Resize = 'off';
  • Ustawia funkcję wywoływaną przy próbie zamknięcia figury na DrivetrainSetupUIFigureCloseRequest.
app.DrivetrainSetupUIFigure.CloseRequestFcn = createCallbackFcn(app, @DrivetrainSetupUIFigureCloseRequest, true);
  • Tworzenie panelu PowertrainDataPanel
app.PowertrainDataPanel = uipanel(app.DrivetrainSetupUIFigure);
app.PowertrainDataPanel.Title = 'Dane napędu';
app.PowertrainDataPanel.Position = [2 1 1107 764];
  • Tworzenie UIAxes
app.UIAxes = uiaxes(app.PowertrainDataPanel);
title(app.UIAxes, 'Pojedynczy silnik')
xlabel(app.UIAxes, 'RPM [1/min]')
ylabel(app.UIAxes, 'Moment obrotowy [Nm]')
app.UIAxes.XTickLabelRotation = 0;
app.UIAxes.YTickLabelRotation = 0;
app.UIAxes.ZTickLabelRotation = 0;
app.UIAxes.Position = [552 535 525 185];
  • Tworzenie UIAxes2
app.UIAxes2 = uiaxes(app.PowertrainDataPanel);
title(app.UIAxes2, 'Tytuł')
xlabel(app.UIAxes2, 'X')
ylabel(app.UIAxes2, 'Y')
app.UIAxes2.XTickLabelRotation = 0;
app.UIAxes2.YTickLabelRotation = 0;
app.UIAxes2.ZTickLabelRotation = 0;
app.UIAxes2.Position = [552 130 525 185];
  • Tworzenie UIAxes3
app.UIAxes3 = uiaxes(app.PowertrainDataPanel);
title(app.UIAxes3, 'Tytuł')
xlabel(app.UIAxes3, 'X')
ylabel(app.UIAxes3, 'Y')
app.UIAxes3.XTickLabelRotation = 0;
app.UIAxes3.YTickLabelRotation = 0;
app.UIAxes3.ZTickLabelRotation = 0;
app.UIAxes3.Position = [552 333 525 185];
  • Tworzenie panelu GearboxPanel
app.GearboxPanel = uipanel(app.PowertrainDataPanel);
app.GearboxPanel.TitlePosition = 'centertop';
app.GearboxPanel.Title = 'Skrzynia biegów';
app.GearboxPanel.Position = [263 83 257 480];
  • Tworzenie etykiety t_shiftsEditFieldLabel
app.t_shiftsEditFieldLabel = uilabel(app.GearboxPanel);
app.t_shiftsEditFieldLabel.HorizontalAlignment = 'right';
app.t_shiftsEditFieldLabel.Position = [77 398 55 23];
app.t_shiftsEditFieldLabel.Text = 't_shift [s]';
  • Tworzenie pola edycyjnego t_shiftsEditField
app.t_shiftsEditField = uieditfield(app.GearboxPanel, 'numeric');
app.t_shiftsEditField.LowerLimitInclusive = 'off';
app.t_shiftsEditField.UpperLimitInclusive = 'off';
app.t_shiftsEditField.Limits = [0 Inf];
app.t_shiftsEditField.Position = [150 399 87 22];
app.t_shiftsEditField.Value = 0.035;
  • Tworzenie etykiety n_shift1minEditFieldLabel
app.n_shift1minEditFieldLabel = uilabel(app.GearboxPanel);
app.n_shift1minEditFieldLabel.HorizontalAlignment = 'right';
app.n_shift1minEditFieldLabel.Position = [51 371 80 23];
app.n_shift1minEditFieldLabel.Text = 'n_shift [1/min]';
  • Tworzenie pola edycyjnego n_shift1minEditField
app.n_shift1minEditField = uieditfield(app.GearboxPanel, 'numeric');
app.n_shift1minEditField.UpperLimitInclusive = 'off';
app.n_shift1minEditField.Limits = [1 Inf];
app.n_shift1minEditField.ValueDisplayFormat = '%.0f';
app.n_shift1minEditField.Tooltip = {''};
app.n_shift1minEditField.Position = [150 372 87 22];
app.n_shift1minEditField.Value = 10500;
  • Tworzenie przycisku Button_3
app.Button_3 = uibutton(app.GearboxPanel, 'push');
app.Button_3.ButtonPushedFcn = createCallbackFcn(app, @Button_3Pushed, true);
app.Button_3.Position = [10 26 37 22];
app.Button_3.Text = '+';
  • Tworzenie przycisku Button_4
app.Button_4 = uibutton(app.GearboxPanel, 'push');
app.Button_4.ButtonPushedFcn = createCallbackFcn(app, @Button_4Pushed, true);
app.Button_4.Position = [47 26 37 22];
app.Button_4.Text = '-';
  • Tworzenie tabeli GearboxTable
app.GearboxTable = uitable(app.GearboxPanel);
app.GearboxTable.ColumnName = {'Gear Ratio'; 'Final Ratio'; 'Vmax [km/h]'};
app.GearboxTable.RowName = {};
app.GearboxTable.ColumnEditable = [true false false];
app.GearboxTable.CellEditCallback = createCallbackFcn(app, @GearboxTableCellEdit, true);
app.GearboxTable.Position = [7 47 245 282];
  • Tworzenie przycisku PlotGearboxdataButton
app.PlotGearboxdataButton = uibutton(app.GearboxPanel, 'push');
app.PlotGearboxdataButton.ButtonPushedFcn = createCallbackFcn(app, @PlotGearboxdataButtonPushed, true);
app.PlotGearboxdataButton.Position = [136 14 112 22];
app.PlotGearboxdataButton.Text = 'Plot Gearbox data';
  • Tworzenie pola wyboru EnableGearboxCheckBox
app.EnableGearboxCheckBox = uicheckbox(app.GearboxPanel);
app.EnableGearboxCheckBox.ValueChangedFcn = createCallbackFcn(app, @EnableGearboxCheckBoxValueChanged, true);
app.EnableGearboxCheckBox.Text = 'Enable Gearbox';
app.EnableGearboxCheckBox.Position = [7 435 109 22];
  • Tworzenie etykiety n_downshift1minEditFieldLabel
app.n_downshift1minEditFieldLabel = uilabel(app.GearboxPanel);
app.n_downshift1minEditFieldLabel.HorizontalAlignment = 'right';
app.n_downshift1minEditFieldLabel.Position = [15 344 116 23];
app.n_downshift1minEditFieldLabel.Text = 'n_downshift [1/min]';
  • Tworzenie pola edycyjnego n_downshift1minEditField
app.n_downshift1minEditField = uieditfield(app.GearboxPanel, 'numeric');
app.n_downshift1minEditField.UpperLimitInclusive = 'off';
app.n_downshift1minEditField.Limits = [1 Inf];
app.n_downshift1minEditField.ValueDisplayFormat = '%.0f';
app.n_downshift1minEditField.Tooltip = {''};
app.n_downshift1minEditField.Position = [150 345 87 22];
app.n_downshift1minEditField.Value = 6000;
  • Tworzenie panelu ChaindrivePanel
app.ChaindrivePanel = uipanel(app.PowertrainDataPanel);
app.ChaindrivePanel.Title = 'Chaindrive';
app.ChaindrivePanel.Position = [264 576 256 162];
  • Tworzenie etykiety i_PLabel
app.i_PLabel = uilabel(app.ChaindrivePanel);
app.i_PLabel.HorizontalAlignment = 'right';
app.i_PLabel.Position = [136 112 55 23];
app.i_PLabel.Text = 'i_P [-]';
  • Tworzenie pola edycyjnego i_PEditField
app.i_PEditField = uieditfield(app.ChaindrivePanel, 'numeric');
app.i_PEditField.LowerLimitInclusive = 'off';
app.i_PEditField.UpperLimitInclusive = 'off';
app.i_PEditField.Limits = [0 Inf];
app.i_PEditField.ValueChangedFcn = createCallbackFcn(app, @i_PEditFieldValueChanged, true);
app.i_PEditField.Position = [200 112 48 22];
app.i_PEditField.Value = 1;
  • Tworzenie panelu loadPanel
app.loadPanel = uipanel(app.PowertrainDataPanel);
app.loadPanel.Title = 'load';
app.loadPanel.Position = [566 42 524 56];
  • Tworzenie przycisku TY19BaselineButton
app.TY19BaselineButton = uibutton(app.loadPanel, 'push');
app.TY19BaselineButton.ButtonPushedFcn = createCallbackFcn(app, @TY19BaselineButtonPushed, true);
app.TY19BaselineButton.Position = [14 8 100 22];
app.TY19BaselineButton.Text = 'TY-19 Baseline';
  • Tworzenie przycisku ElectricBaselineButton
app.ElectricBaselineButton = uibutton(app.loadPanel, 'push');
app.ElectricBaselineButton.ButtonPushedFcn = createCallbackFcn(app, @ElectricBaselineButtonPushed, true);
app.ElectricBaselineButton.Position = [232 8 108 22];
app.ElectricBaselineButton.Text = 'Electric Baseline';
  • Tworzenie przycisku ResetButton
app.ResetButton = uibutton(app.loadPanel, 'push');
app.ResetButton.ButtonPushedFcn = createCallbackFcn(app, @ResetButtonPushed, true);
app.ResetButton.FontSize = 14;
app.ResetButton.Position = [352 6 56 26];
app.ResetButton.Text = 'Reset';
  • Tworzenie przycisku SaveButton
app.SaveButton = uibutton(app.loadPanel, 'push');
app.SaveButton.ButtonPushedFcn = createCallbackFcn(app, @SaveButtonPushed, true);
app.SaveButton.FontSize = 14;
app.SaveButton.Position = [415 6 99 26];
app.SaveButton.Text = 'Save';
  • Tworzenie przycisku TY20BaselineButton
app.TY20BaselineButton = uibutton(app.loadPanel, 'push');
app.TY20BaselineButton.ButtonPushedFcn = createCallbackFcn(app, @TY20BaselineButtonPushed, true);
app.TY20BaselineButton.Position = [123 8 100 22];
app.TY20BaselineButton.Text = 'TY-20 Baseline';
  • Tworzenie panelu Panel_2
app.Panel_2 = uipanel(app.PowertrainDataPanel);
app.Panel_2.Position = [264 575 256 107];
  • Tworzenie CheckBoxa dla napędu łańcuchowego / pojedynczego układu biegów
app.ChaindriveSingleGearsetCheckBox = uicheckbox(app.Panel_2);
app.ChaindriveSingleGearsetCheckBox.ValueChangedFcn = createCallbackFcn(app, @ChaindriveSingleGearsetCheckBoxValueChanged, true);
app.ChaindriveSingleGearsetCheckBox.Text = {'Napęd łańcuchowy /'; 'Pojedynczy układ biegów'};
app.ChaindriveSingleGearsetCheckBox.Position = [6 74 101 28];
  • Tworzenie etykiety dla pola edycji zębów koła zębatego
app.z_sprocketEditFieldLabel = uilabel(app.Panel_2);
app.z_sprocketEditFieldLabel.HorizontalAlignment = 'right';
app.z_sprocketEditFieldLabel.Position = [112 77 78 22];
app.z_sprocketEditFieldLabel.Text = 'z_sprocket [-]';
  • Tworzenie pola edycji zębów koła zębatego
app.z_sprocketEditField = uieditfield(app.Panel_2, 'numeric');
app.z_sprocketEditField.UpperLimitInclusive = 'off';
app.z_sprocketEditField.Limits = [1 Inf];
app.z_sprocketEditField.ValueChangedFcn = createCallbackFcn(app, @z_sprocketEditFieldValueChanged, true);
app.z_sprocketEditField.Position = [198 77 49 22];
app.z_sprocketEditField.Value = 17;
  • Tworzenie etykiety dla pola edycji zębów napędu łańcuchowego
app.z_chaindriveEditFieldLabel = uilabel(app.Panel_2);
app.z_chaindriveEditFieldLabel.HorizontalAlignment = 'right';
app.z_chaindriveEditFieldLabel.Position = [103 43 87 22];
app.z_chaindriveEditFieldLabel.Text = 'z_chaindrive [-]';
  • Tworzenie pola edycji zębów napędu łańcuchowego
app.z_chaindriveEditField = uieditfield(app.Panel_2, 'numeric');
app.z_chaindriveEditField.UpperLimitInclusive = 'off';
app.z_chaindriveEditField.Limits = [1 Inf];
app.z_chaindriveEditField.ValueChangedFcn = createCallbackFcn(app, @z_chaindriveEditFieldValueChanged, true);
app.z_chaindriveEditField.Position = [198 43 49 22];
app.z_chaindriveEditField.Value = 66;
  • Tworzenie etykiety dla współczynnika przekładni
app.GearRatioLabel = uilabel(app.Panel_2);
app.GearRatioLabel.Position = [159 8 89 22];
app.GearRatioLabel.Text = 'Gear Ratio';
  • Tworzenie etykiety dla rozwijanej listy wyboru silnika
app.EnginePresetDropDownLabel = uilabel(app.PowertrainDataPanel);
app.EnginePresetDropDownLabel.HorizontalAlignment = 'right';
app.EnginePresetDropDownLabel.Position = [21 378 81 22];
app.EnginePresetDropDownLabel.Text = 'Engine Preset';
  • Tworzenie rozwijanej listy wyboru silnika
app.EnginePresetDropDown = uidropdown(app.PowertrainDataPanel);
app.EnginePresetDropDown.Items = {'Triumph_D67LD', 'EMRAX_188_TorqueData_Peak', 'EMRAX_208_TorqueData_Peak', 'Emrax 228', 'Emrax 268', 'Emrax 348', 'Rotax_125_Junior_MAX_evo', 'Rotax_125_MAX_DD2_evo', 'Rotax_125_MAX_evo', 'new Engine'};
app.EnginePresetDropDown.ValueChangedFcn = createCallbackFcn(app, @EnginePresetDropDownValueChanged, true);
app.EnginePresetDropDown.Position = [112 378 135 22];
app.EnginePresetDropDown.Value = 'Triumph_D67LD';
  • Tworzenie przycisku do usuwania silnika
app.DeleteEngineButton = uibutton(app.PowertrainDataPanel, 'push');
app.DeleteEngineButton.ButtonPushedFcn = createCallbackFcn(app, @DeleteEngineButtonPushed, true);
app.DeleteEngineButton.Tooltip = {'Usuwa aktualnie wybrany silnik, jeśli pozostało więcej niż jeden typ silnika.'};
app.DeleteEngineButton.Position = [155 97 91 22];
app.DeleteEngineButton.Text = 'Delete Engine';
  • Tworzenie przycisku do zapisywania silnika
app.SaveEngineButton = uibutton(app.PowertrainDataPanel, 'push');
app.SaveEngineButton.ButtonPushedFcn = createCallbackFcn(app, @SaveEngineButtonPushed, true);
app.SaveEngineButton.Position = [68 97 84 22];
app.SaveEngineButton.Text = 'Save Engine';
  • Tworzenie panelu dla parametrów napędu elektrycznego
app.EPowertrainParametersPanel = uipanel(app.PowertrainDataPanel);
app.EPowertrainParametersPanel.TitlePosition = 'centertop';
app.EPowertrainParametersPanel.Title = 'E Powertrain Parameters';
app.EPowertrainParametersPanel.Position = [18 411 230 92];
  • Tworzenie etykiety dla pola edycji limitu mocy
app.PowerlimitWEditFieldLabel = uilabel(app.EPowertrainParametersPanel);
app.PowerlimitWEditFieldLabel.HorizontalAlignment = 'right';
app.PowerlimitWEditFieldLabel.Position = [33 43 86 22];
app.PowerlimitWEditFieldLabel.Text = 'Power limit [W]';
  • Tworzenie pola edycji limitu mocy
app.PowerlimitWEditField = uieditfield(app.EPowertrainParametersPanel, 'numeric');
app.PowerlimitWEditField.LowerLimitInclusive = 'off';
app.PowerlimitWEditField.UpperLimitInclusive = 'off';
app.PowerlimitWEditField.Limits = [0 Inf];
app.PowerlimitWEditField.ValueDisplayFormat = '%.0f';
app.PowerlimitWEditField.Position = [136 43 87 22];
app.PowerlimitWEditField.Value = 80000;
  • Tworzenie etykiety dla pola edycji sprawności falownika
app.InverterEfficiencyEditFieldLabel = uilabel(app.EPowertrainParametersPanel);
app.InverterEfficiencyEditFieldLabel.HorizontalAlignment = 'right';
app.InverterEfficiencyEditFieldLabel.Position = [1 12 116 22];
app.InverterEfficiencyEditFieldLabel.Text = 'Inverter Efficiency [-]';
  • Tworzenie pola edycji sprawności falownika
app.InverterEfficiencyEditField = uieditfield(app.EPowertrainParametersPanel, 'numeric');
app.InverterEfficiencyEditField.LowerLimitInclusive = 'off';
app.InverterEfficiencyEditField.UpperLimitInclusive = 'off';
app.InverterEfficiencyEditField.Limits = [0 Inf];
app.InverterEfficiencyEditField.ValueChangedFcn = createCallbackFcn(app, @InverterEfficiencyEditFieldValueChanged, true);
app.InverterEfficiencyEditField.Position = [137 12 86 22];
app.InverterEfficiencyEditField.Value = 0.95;
  • Tworzenie panelu
app.Panel = uipanel(app.PowertrainDataPanel);
app.Panel.Title = 'Panel';
app.Panel.Position = [17 517 227 220];
  • Tworzenie przełącznika dla wyboru napędu
app.PowertrainSwitch = uiswitch(app.Panel, 'slider');
app.PowertrainSwitch.Items = {'Electric', 'Combustion'};
app.PowertrainSwitch.ValueChangedFcn = createCallbackFcn(app, @PowertrainSwitchValueChanged, true);
app.PowertrainSwitch.Position = [85 170 45 20];
app.PowertrainSwitch.Value = 'Electric';
  • Tworzenie etykiety dla rozwijanej listy wyboru układu
app.LayoutDropDownLabel = uilabel(app.Panel);
app.LayoutDropDownLabel.HorizontalAlignment = 'right';
app.LayoutDropDownLabel.Position = [40 132 42 22];
app.LayoutDropDownLabel.Text = 'Layout';
  • Tworzenie rozwijanej listy rozmieszczenia napędu.
app.LayoutDropDown = uidropdown(app.Panel);
app.LayoutDropDown.Items = {'2 Motor RWD', '1 Motor RWD', 'AWD'};
app.LayoutDropDown.ValueChangedFcn = createCallbackFcn(app, @LayoutDropDownValueChanged, true);
app.LayoutDropDown.Position = [93 132 107 22];
app.LayoutDropDown.Value = '2 Motor RWD';
  • Tworzenie etykiety pola edycji dla sprawności układu napędowego.
app.DrivetrainEfficencyEditFieldLabel = uilabel(app.Panel);
app.DrivetrainEfficencyEditFieldLabel.HorizontalAlignment = 'right';
app.DrivetrainEfficencyEditFieldLabel.Position = [22 98 123 22];
app.DrivetrainEfficencyEditFieldLabel.Text = 'Sprawność układu napędowego [-]';
  • Tworzenie pola edycji dla sprawności układu napędowego.
app.DrivetrainEfficencyEditField = uieditfield(app.Panel, 'numeric');
app.DrivetrainEfficencyEditField.LowerLimitInclusive = 'off';
app.DrivetrainEfficencyEditField.Limits = [0 1];
app.DrivetrainEfficencyEditField.ValueChangedFcn = createCallbackFcn(app, @DrivetrainEfficencyEditFieldValueChanged, true);
app.DrivetrainEfficencyEditField.Position = [155 98 52 22];
app.DrivetrainEfficencyEditField.Value = 0.95;
  • Tworzenie etykiety pola edycji dla maksymalnej prędkości obrotowej.
app.n_max1minEditFieldLabel = uilabel(app.Panel);
app.n_max1minEditFieldLabel.HorizontalAlignment = 'right';
app.n_max1minEditFieldLabel.Position = [51 68 81 22];
app.n_max1minEditFieldLabel.Text = 'n_max [1/min]';
  • Tworzenie pola edycji dla maksymalnej prędkości obrotowej.
app.n_max1minEditField = uieditfield(app.Panel, 'numeric');
app.n_max1minEditField.UpperLimitInclusive = 'off';
app.n_max1minEditField.Limits = [1 Inf];
app.n_max1minEditField.ValueDisplayFormat = '%.0f';
app.n_max1minEditField.Position = [155 68 53 22];
app.n_max1minEditField.Value = 6000;
  • Tworzenie etykiety pola edycji dla mnożnika momentu obrotowego.
app.TorquemultiplierEditFieldLabel = uilabel(app.Panel);
app.TorquemultiplierEditFieldLabel.HorizontalAlignment = 'right';
app.TorquemultiplierEditFieldLabel.Position = [20 38 108 22];
app.TorquemultiplierEditFieldLabel.Text = 'Mnożnik momentu obrotowego [-]';
  • Tworzenie pola edycji dla mnożnika momentu obrotowego.
app.TorquemultiplierEditField = uieditfield(app.Panel, 'numeric');
app.TorquemultiplierEditField.LowerLimitInclusive = 'off';
app.TorquemultiplierEditField.UpperLimitInclusive = 'off';
app.TorquemultiplierEditField.Limits = [0 Inf];
app.TorquemultiplierEditField.ValueChangedFcn = createCallbackFcn(app, @TorquemultiplierEditFieldValueChanged, true);
app.TorquemultiplierEditField.Position = [155 38 54 22];
app.TorquemultiplierEditField.Value = 1;
  • Tworzenie etykiety pola edycji dla prędkości jałowej.
app.idle_rpm1minEditFieldLabel = uilabel(app.Panel);
app.idle_rpm1minEditFieldLabel.HorizontalAlignment = 'right';
app.idle_rpm1minEditFieldLabel.Position = [42 8 91 22];
app.idle_rpm1minEditFieldLabel.Text = 'Prędkość jałowa [1/min]';
  • Tworzenie pola edycji dla prędkości jałowej.
app.idle_rpm1minEditField = uieditfield(app.Panel, 'numeric');
app.idle_rpm1minEditField.UpperLimitInclusive = 'off';
app.idle_rpm1minEditField.Limits = [0 Inf];
app.idle_rpm1minEditField.Position = [156 8 53 22];
app.idle_rpm1minEditField.Value = 2000;
  • Tworzenie etykiety z informacją o prawach autorskich.
app.Copyright2021BalticRacingbyEricDorniedenLabel = uilabel(app.PowertrainDataPanel);
app.Copyright2021BalticRacingbyEricDorniedenLabel.Position = [834 1 274 22];
app.Copyright2021BalticRacingbyEricDorniedenLabel.Text = 'Copyright © 2021 Baltic Racing by Eric Dornieden';
  • Wyświetlanie logo Baltic Racing.
app.Image2 = uiimage(app.PowertrainDataPanel);
app.Image2.Position = [7 6 196 77];
app.Image2.ImageSource = 'balticracing_logo_transparent.png';
  • Tworzenie przycisku dodawania.
app.Button = uibutton(app.PowertrainDataPanel, 'push');
app.Button.ButtonPushedFcn = createCallbackFcn(app, @ButtonPushed, true);
app.Button.Position = [25 98 21 21];
app.Button.Text = '+';
  • Tworzenie przycisku odejmowania.
app.Button_2 = uibutton(app.PowertrainDataPanel, 'push');
app.Button_2.ButtonPushedFcn = createCallbackFcn(app, @Button_2Pushed, true);
app.Button_2.Position = [45 98 20 21];
app.Button_2.Text = '-';
  • Tworzenie tabeli do wyświetlania danych napędu.
app.UITable = uitable(app.PowertrainDataPanel);
app.UITable.ColumnName = {'RPM [1/min]'; 'Moment obrotowy [Nm]'};
app.UITable.RowName = {};
app.UITable.ColumnEditable = true;
app.UITable.CellEditCallback = createCallbackFcn(app, @UITableCellEdit, true);
app.UITable.Position = [24 119 222 258];
  • Wyświetlanie okna po utworzeniu wszystkich komponentów.
app.DrivetrainSetupUIFigure.Visible = 'on';
  • Konstruktor aplikacji, tworzy obiekt aplikacji Drivetrain, przyjmuje opcjonalne argumenty wejściowe
function app = Drivetrain(varargin)
  • Tworzenie UIFigure i komponentów
createComponents(app)
  • Rejestrowanie aplikacji w App Designer
registerApp(app, app.DrivetrainSetupUIFigure)
  • Wykonanie funkcji startupFcn
runStartupFcn(app, @(app)startupFcn(app, varargin{:}))
  • Jeśli nie ma argumentów wyjściowych, usuń obiekt aplikacji
if nargout == 0
    clear app
  • Usunięcie UIFigure przy usuwaniu aplikacji
delete(app.DrivetrainSetupUIFigure)

7 - Linia Krzywa 2D

Funkcja LineCurvature2D oblicza krzywiznę linii 2D. Najpierw dopasowuje wielokąty do punktów, a następnie oblicza krzywiznę analityczną na podstawie wielokątów.

Zmienne wejściowe:

1. Vertices:

  • Macierz M x 2
  • Opis: Lista punktów tworzących linię, gdzie każda z M wierszy zawiera współrzędne x i y danego punktu.
  • Przykład: Vertices = [x1, y1; x2, y2; ...; xM, yM]

2. Lines (opcjonalnie):

  • Macierz N x 2
  • Opis: Lista odcinków linii zdefiniowana przez indeksy punktów z Vertices. Każdy wiersz zawiera dwa indeksy, które definiują odcinek linii.
  • Przykład: Lines = [index1, index2; index2, index3; ...; indexN-1, indexN]
  • Domyślnie: Jeśli Lines nie jest podane, przyjmuje się, że Lines = [1 2; 2 3; ...; M-1 M], co oznacza, że punkty są połączone w kolejności, w jakiej są podane.

Zmienna wyjściowa:

1. k:

  • Wektor M x 1
  • Opis: Wartości krzywizny dla każdego z M punktów linii. Każdy element wektora k odpowiada krzywiźnie w odpowiednim punkcie Vertices.
  • Przykład: k = [k1; k2; ...; kM], gdzie ki to krzywizna w punkcie i.

Przykład użycia:

Jeśli mamy punkty linii:

Vertices = [0, 0; 1, 1; 2, 0; 3, -1]; i chcemy obliczyć krzywiznę, możemy wywołać funkcję: k = LineCurvature2D(Vertices);

Jeśli chcemy określić własne odcinki linii:

Lines = [1, 2; 2, 3; 3, 4];
k = LineCurvature2D(Vertices, Lines);

Przykłady:

Koło

1. Generowanie losowych kątów:

r = sort(rand(15,1)) * 2 * pi;

  • Generujemy 15 losowych liczb w zakresie od 0 do 1 (rand(15,1)).
  • Sortujemy te liczby rosnąco (sort).
  • Przekształcamy je na kąty w zakresie od 0 do 2π poprzez mnożenie przez 2π.

2. Tworzenie punktów okręgu:

Vertices = [sin(r) cos(r)] * 10;

  • Używamy funkcji trygonometrycznych sin i cos, aby przekształcić kąty na współrzędne punktów na okręgu.
  • Skalujemy współrzędne przez 10, aby uzyskać punkty na okręgu o promieniu 10.
  • Vertices to macierz 15x2, gdzie każda para [sin(r_i) cos(r_i)] * 10 reprezentuje współrzędne punktu.

3. Tworzenie linii:

Lines = [(1:size(Vertices,1))' (2:size(Vertices,1)+1']; Lines(end,2) = 1;

  • Tworzymy macierz Lines, która definiuje odcinki linii przez indeksy punktów w Vertices.
  • Każdy wiersz Lines łączy punkt i z punktem i+1.
  • Ostatnia para jest specjalnie ustawiona (Lines(end,2) = 1), aby zamknąć okrąg, łącząc ostatni punkt z pierwszym.

4. Obliczenie krzywizny:

k = LineCurvature2D(Vertices, Lines);

  • Wywołujemy funkcję LineCurvature2D z punktami Vertices i liniami Lines, aby obliczyć krzywiznę.
  • k to wektor wartości krzywizny dla każdego punktu.

figure, hold on;

  • Tworzy nowe okno wykresu.
  • Włącza tryb hold on, co pozwala na nałożenie wielu wykresów na jednej figurze bez ich nadpisywania.

5. Obliczenie normalnych do linii:

N = LineNormals2D(Vertices,Lines);

  • Wywołuje funkcję LineNormals2D, która oblicza normalne do linii w punktach Vertices na podstawie Lines.
  • N to macierz zawierająca wektory normalne dla każdego punktu.

6. Skalowanie wartości krzywizny:

k = k * 100;

  • Skaluje wartości krzywizny k przez mnożenie przez 100, aby lepiej widoczne były na wykresie.
  • N to macierz zawierająca wektory normalne dla każdego punktu.

7. Wykreślanie normalnych do linii:

plot([Vertices(:,1) Vertices(:,1)+k.*N(:,1)]',[Vertices(:,2) Vertices(:,2)+k.*N(:,2)]','g');

  • Wykreśla wektory normalne w każdym punkcie Vertices.
  • Vertices(:,1) to współrzędne x punktów początkowych.
  • Vertices(:,1) + k.*N(:,1) to współrzędne x końców wektorów normalnych.
  • Vertices(:,2) to współrzędne y punktów początkowych.
  • Vertices(:,2) + k.*N(:,2) to współrzędne y końców wektorów normalnych.
  • Kolor wykresu: zielony ('g').

8. Wykreślanie linii:

plot([Vertices(Lines(:,1),1) Vertices(Lines(:,2),1)]',[Vertices(Lines(:,1),2) Vertices(Lines(:,2),2)]','b');

  • Wykreśla linie łączące punkty z Vertices zgodnie z Lines.

  • Vertices(Lines(:,1),1) i Vertices(Lines(:,2),1) to współrzędne x punktów początkowych i końcowych odcinków linii.

  • Vertices(Lines(:,1),2) i Vertices(Lines(:,2),2) to współrzędne y punktów początkowych i końcowych odcinków linii.

  • Kolor wykresu: niebieski ('b').

9. Wykreślanie idealnego okręgu:

plot(sin(0:0.01:2*pi)*10, cos(0:0.01:2*pi)*10, 'r.');

  • Wykreśla idealny okrąg o promieniu 10.

  • sin(0:0.01:2*pi)*10 i cos(0:0.01:2*pi)*10 to współrzędne x i y punktów na okręgu.

  • Kolor wykresu: czerwony ('r').

10. Ustawienie równej skali osi:

axis equal;

  • Ustawia równe jednostki na osiach x i y, co sprawia, że okrąg wygląda proporcjonalnie.

Przykład, Ręka:

1. Wczytanie danych z pliku:

load('testdata');

  • Wczytuje dane z pliku testdata.mat, które zawierają zmienne Vertices (współrzędne punktów) i Lines (lista odcinków linii).

2. Obliczenie krzywizny linii:

k = LineCurvature2D(Vertices, Lines);

  • Wywołuje funkcję LineCurvature2D, która oblicza wartości krzywizny dla punktów zdefiniowanych w Vertices i Lines.
  • k to wektor zawierający wartości krzywizny dla każdego punktu.

3. Utworzenie nowej figury i włączenie trybu hold on:

figure, hold on;

  • Tworzy nowe okno wykresu.
  • Włącza tryb hold on, co pozwala na nałożenie wielu wykresów na jednej figurze bez ich nadpisywania.

4. Obliczenie normalnych do linii:

N = LineNormals2D(Vertices, Lines);

  • Wywołuje funkcję LineNormals2D, która oblicza wektory normalne dla punktów z Vertices na podstawie Lines.
  • N to macierz zawierająca wektory normalne dla każdego punktu.

5. Skalowanie wartości krzywizny:

k = k * 100;

  • Skaluje wartości krzywizny k przez mnożenie przez 100, aby lepiej widoczne były na wykresie.

6. Wykreślanie normalnych do linii:

plot([Vertices(:,1) Vertices(:,1) + k .* N(:,1)]', [Vertices(:,2) Vertices(:,2) + k .* N(:,2)]', 'g');

  • Wykreśla wektory normalne w każdym punkcie Vertices.
  • Vertices(:,1) to współrzędne x punktów początkowych.
  • Vertices(:,1) + k .* N(:,1) to współrzędne x końców wektorów normalnych.
  • Vertices(:,2) to współrzędne y punktów początkowych.
  • Vertices(:,2) + k .* N(:,2) to współrzędne y końców wektorów normalnych.
  • Kolor wykresu: zielony ('g').

7. Wykreślanie linii:

plot([Vertices(Lines(:,1),1) Vertices(Lines(:,2),1)]', [Vertices(Lines(:,1),2) Vertices(Lines(:,2),2)]', 'b'); `

  • Wykreśla linie łączące punkty z Vertices zgodnie z Lines.
  • Vertices(Lines(:,1),1) i Vertices(Lines(:,2),1) to współrzędne x punktów początkowych i końcowych odcinków linii.
  • Vertices(Lines(:,1),2) i Vertices(Lines(:,2),2) to współrzędne y punktów początkowych i końcowych odcinków linii.
  • Kolor wykresu: niebieski ('b').

8. Wykreślanie punktów:

plot(Vertices(:,1), Vertices(:,2), 'r.');

  • Wykreśla punkty Vertices.
  • Kolor wykresu: czerwony ('r').

9. Ustawienie równej skali osi:

axis equal;

  • Ustawia równe jednostki na osiach x i y, co zapewnia proporcjonalne wyświetlanie.

10. Lista zmiennych i ich opis:

Vertices:

  • Typ: Macierz M x 2
  • Opis: Współrzędne punktów (wierzchołków) linii.

Lines:

  • Typ: Macierz N x 2
  • Opis: Lista odcinków linii, zdefiniowana przez indeksy punktów w Vertices.

k:

  • Typ: Wektor M x 1
  • Opis: Wartości krzywizny dla punktów Vertices, skalowane przez 100.

N:

  • Typ: Macierz M x 2
  • Opis: Wektory normalne dla punktów z Vertices, obliczone przez LineNormals2D.

Funkcja

Obliczenie krzywizny linii na podstawie zadanych wierzchołków (Vertices) i odcinków linii (Lines). Obejmuje on kroki takie jak uzupełnianie brakujących sąsiadów, przeliczanie wektorów normalnych oraz obliczanie krzywizny na podstawie dopasowania wielomianu do wierzchołków.

Kod:

% Function is written by D.Kroon University of Twente (August 2011)

% If no line-indices, assume a x(1) connected with x(2), x(3) with x(4) ...
if(nargin<2)
    Lines=[(1:(size(Vertices,1)-1))' (2:size(Vertices,1))'];
end

% Get left and right neighbor of each points
Na=zeros(size(Vertices,1),1); Nb=zeros(size(Vertices,1),1);
Na(Lines(:,1))=Lines(:,2); Nb(Lines(:,2))=Lines(:,1);

% Check for end of line points, without a left or right neighbor
checkNa=Na==0; checkNb=Nb==0;
Naa=Na; Nbb=Nb;
Naa(checkNa)=find(checkNa); Nbb(checkNb)=find(checkNb);

% If no left neighbor use two right neighbors, and the same for right... 
Na(checkNa)=Nbb(Nbb(checkNa)); Nb(checkNb)=Naa(Naa(checkNb));

% Correct for sampeling differences
Ta=-sqrt(sum((Vertices-Vertices(Na,:)).^2,2));
Tb=sqrt(sum((Vertices-Vertices(Nb,:)).^2,2)); 

% If no left neighbor use two right neighbors, and the same for right... 
Ta(checkNa)=-Ta(checkNa); Tb(checkNb)=-Tb(checkNb);

% Fit a polygons to the vertices 
% x=a(3)*t^2 + a(2)*t + a(1) 
% y=b(3)*t^2 + b(2)*t + b(1) 
% we know the x,y of every vertice and set t=0 for the vertices, and
% t=Ta for left vertices, and t=Tb for right vertices,  
x = [Vertices(Na,1) Vertices(:,1) Vertices(Nb,1)];
y = [Vertices(Na,2) Vertices(:,2) Vertices(Nb,2)];
M = [ones(size(Tb)) -Ta Ta.^2 ones(size(Tb)) zeros(size(Tb)) zeros(size(Tb)) ones(size(Tb)) -Tb Tb.^2];
invM=inverse3(M);
a(:,1)=invM(:,1,1).*x(:,1)+invM(:,2,1).*x(:,2)+invM(:,3,1).*x(:,3);
a(:,2)=invM(:,1,2).*x(:,1)+invM(:,2,2).*x(:,2)+invM(:,3,2).*x(:,3);
a(:,3)=invM(:,1,3).*x(:,1)+invM(:,2,3).*x(:,2)+invM(:,3,3).*x(:,3);
b(:,1)=invM(:,1,1).*y(:,1)+invM(:,2,1).*y(:,2)+invM(:,3,1).*y(:,3);
b(:,2)=invM(:,1,2).*y(:,1)+invM(:,2,2).*y(:,2)+invM(:,3,2).*y(:,3);
b(:,3)=invM(:,1,3).*y(:,1)+invM(:,2,3).*y(:,2)+invM(:,3,3).*y(:,3);

% Calculate the curvature from the fitted polygon
k = 2*(a(:,2).*b(:,3)-a(:,3).*b(:,2)) ./ ((a(:,2).^2+b(:,2).^2).^(3/2));

function  Minv  = inverse3(M)
% This function does inv(M) , but then for an array of 3x3 matrices
adjM(:,1,1)=  M(:,5).*M(:,9)-M(:,8).*M(:,6);
adjM(:,1,2)=  -(M(:,4).*M(:,9)-M(:,7).*M(:,6));
adjM(:,1,3)=  M(:,4).*M(:,8)-M(:,7).*M(:,5);
adjM(:,2,1)=  -(M(:,2).*M(:,9)-M(:,8).*M(:,3));
adjM(:,2,2)=  M(:,1).*M(:,9)-M(:,7).*M(:,3);
adjM(:,2,3)=  -(M(:,1).*M(:,8)-M(:,7).*M(:,2));
adjM(:,3,1)=  M(:,2).*M(:,6)-M(:,5).*M(:,3);
adjM(:,3,2)=  -(M(:,1).*M(:,6)-M(:,4).*M(:,3));
adjM(:,3,3)=  M(:,1).*M(:,5)-M(:,4).*M(:,2);
detM=M(:,1).*M(:,5).*M(:,9)-M(:,1).*M(:,8).*M(:,6)-M(:,4).*M(:,2).*M(:,9)+M(:,4).*M(:,8).*M(:,3)+M(:,7).*M(:,2).*M(:,6)-M(:,7).*M(:,5).*M(:,3);
Minv=bsxfun(@rdivide,adjM,detM);

Kroki działania:

1. Sprawdzenie i przypisanie domyślnych indeksów linii:

if(nargin<2) Lines=[(1:(size(Vertices,1)-1))' (2:size(Vertices,1))']; end

  • Jeśli nie podano Lines, domyślnie zakłada, że punkty są połączone sekwencyjnie.

2. Znalezienie lewego i prawego sąsiada dla każdego punktu:

Na=zeros(size(Vertices,1),1); Nb=zeros(size(Vertices,1),1); Na(Lines(:,1))=Lines(:,2); Nb(Lines(:,2))=Lines(:,1);

  • Na i Nb przechowują indeksy lewych i prawych sąsiadów dla każdego punktu.

3. Sprawdzenie punktów bez sąsiadów i uzupełnienie braków:

checkNa=Na==0; checkNb=Nb==0;
Naa=Na; Nbb=Nb;
Naa(checkNa)=find(checkNa); Nbb(checkNb)=find(checkNb);

Na(checkNa)=Nbb(Nbb(checkNa)); Nb(checkNb)=Naa(Naa(checkNb));
  • Jeśli punkt nie ma lewego lub prawego sąsiada, używa dwóch sąsiadów z przeciwnej strony.

4. Korekta różnic próbkowania:

Ta=-sqrt(sum((Vertices-Vertices(Na,:)).^2,2));
Tb=sqrt(sum((Vertices-Vertices(Nb,:)).^2,2)); 

Ta(checkNa)=-Ta(checkNa); Tb(checkNb)=-Tb(checkNb);
  • Oblicza odległości do sąsiadów, uwzględniając brakujące wartości.

5. Dopasowanie wielomianu do wierzchołków:

x = [Vertices(Na,1) Vertices(:,1) Vertices(Nb,1)]; y = [Vertices(Na,2) Vertices(:,2) Vertices(Nb,2)]; M = [ones(size(Tb)) -Ta Ta.^2 ones(size(Tb)) zeros(size(Tb)) zeros(size(Tb)) ones(size(Tb)) -Tb Tb.^2]; invM=inverse3(M); a(:,1)=invM(:,1,1).*x(:,1)+invM(:,2,1).*x(:,2)+invM(:,3,1).*x(:,3); a(:,2)=invM(:,1,2).*x(:,1)+invM(:,2,2).*x(:,2)+invM(:,3,2).*x(:,3); a(:,3)=invM(:,1,3).*x(:,1)+invM(:,2,3).*x(:,2)+invM(:,3,3).*x(:,3); b(:,1)=invM(:,1,1).*y(:,1)+invM(:,2,1).*y(:,2)+invM(:,3,1).*y(:,3); b(:,2)=invM(:,1,2).*y(:,1)+invM(:,2,2).*y(:,2)+invM(:,3,2).*y(:,3); b(:,3)=invM(:,1,3).*y(:,1)+invM(:,2,3).*y(:,2)+invM(:,3,3).*y(:,3);

  • Dopasowuje wielomiany do współrzędnych punktów, biorąc pod uwagę sąsiadów.

6. Obliczenie krzywizny:

k = 2*(a(:,2).*b(:,3)-a(:,3).*b(:,2)) ./ ((a(:,2).^2+b(:,2).^2).^(3/2));

7. Odwracanie macierzy 3x3:

function  Minv  = inverse3(M)
adjM(:,1,1)=  M(:,5).*M(:,9)-M(:,8).*M(:,6);
adjM(:,1,2)=  -(M(:,4).*M(:,9)-M(:,7).*M(:,6));
adjM(:,1,3)=  M(:,4).*M(:,8)-M(:,7).*M(:,5);
adjM(:,2,1)=  -(M(:,2).*M(:,9)-M(:,8).*M(:,3));
adjM(:,2,2)=  M(:,1).*M(:,9)-M(:,7).*M(:,3);
adjM(:,2,3)=  -(M(:,1).*M(:,8)-M(:,7).*M(:,2));
adjM(:,3,1)=  M(:,2).*M(:,6)-M(:,5).*M(:,3);
adjM(:,3,2)=  -(M(:,1).*M(:,6)-M(:,4).*M(:,3));
adjM(:,3,3)=  M(:,1).*M(:,5)-M(:,4).*M(:,2);
detM=M(:,1).*M(:,5).*M(:,9)-M(:,1).*M(:,8).*M(:,6)-M(:,4).*M(:,2).*M(:,9)+M(:,4).*M(:,8).*M(:,3)+M(:,7).*M(:,2).*M(:,6)-M(:,7).*M(:,5).*M(:,3);
Minv=bsxfun(@rdivide,adjM,detM);

Lista zmiennych i ich opis:

Vertices:

  • Typ: Macierz M x 2
  • Opis: Współrzędne punktów (wierzchołków) linii.

Lines:

  • Typ: Macierz N x 2
  • Opis: Lista odcinków linii, zdefiniowana przez indeksy punktów w Vertices.

Na:

  • Typ: Wektor M x 1
  • Opis: Indeksy lewych sąsiadów dla każdego punktu.

Nb:

  • Typ: Wektor M x 1
  • Opis: Indeksy prawych sąsiadów dla każdego punktu.

checkNa, checkNb:

  • Typ: Wektory logiczne M x 1
  • Opis: Wskazuje, które punkty nie mają lewego lub prawego sąsiada.

Naa, Nbb:

  • Typ: Wektory M x 1
  • Opis: Kopie Na i Nb, używane do uzupełniania braków.

Ta, Tb:

  • Typ: Wektory M x 1
  • Opis: Odległości do lewych i prawych sąsiadów.

x, y:`

  • Typ: Macierze M x 3
  • Opis: Współrzędne x i y dla punktów i ich sąsiadów.

M:

  • Typ: Macierz M x 9
  • Opis: Macierz współczynników dla dopasowania wielomianu.

invM:

  • Typ: Macierz M x 3 x 3
  • Opis: Odwrotność macierzy M.

a, b:

  • Typ: Macierze M x 3
  • Opis: Współczynniki wielomianów dopasowanych do współrzędnych x i y.

k:

  • Typ: Wektor M x 1
  • Opis: Wartości krzywizny dla punktów Vertices.

8 - Linia Znormalizowana 2D

Funkcja LineNormals2D oblicza normalne do punktów linii, wykorzystując sąsiednie punkty każdego punktu konturu oraz różnice w przód i w tył na końcach.

Wejście i wyjście:

Fragment kodu przyjmuje listę punktów/wierzchołków V o wymiarach 2 x M jako dane wejściowe. Opcjonalnie można podać listę odcinków Lines, która jest listą N x 2 zawierającą indeksy wierzchołków definiujących poszczególne odcinki linii (jeśli nie jest podana, zakłada się, że Lines=[1 2; 2 3 ; ... ; M-1 M]). Jako wynik zwraca normalne do wierzchołków N o wymiarach 2 x M.

  • V = Lista punktów/wierzchołków w postaci macierzy 2 x M.
  • Lines (opcjonalny) = Lista o wymiarach N x 2 zawierająca odcinki linii, wyrażone przez indeksy wierzchołków (jeśli nie jest podana, zakładamy, że Lines=[1 2; 2 3 ; ... ; M-1 M]).
  • N = Normalne do wierzchołków w postaci macierzy 2 x M.

Przykład:

Ten fragment kodu to przykładowe użycie funkcji LineNormals2D w celu obliczenia normalnych do linii na płaszczyźnie 2D. Dane wejściowe są wczytywane z pliku testowego (testdata). Następnie funkcja LineNormals2D jest wywoływana, aby obliczyć normalne do linii na podstawie podanych wierzchołków (Vertices) i odcinków (Lines). Otrzymane normalne są następnie wykorzystywane do wygenerowania wykresu, który przedstawia oryginalne linie oraz normalne do tych linii, przedstawione jako linie przechodzące przez wierzchołki i skierowane w kierunku normalnej zwiększonej dziesięciokrotnie.

  • testdata = nazwa pliku testowego.

FUNKCJA:

Funkcja napisana przez D. Kroona z Uniwersytetu w Twente (sierpień 2011)

Początek kodu odpowiada za ustalenie listy odcinków linii w przypadku, gdy nie są podane indeksy linii. Lista zmiennych:

  • nargin = Liczba argumentów wejściowych funkcji.
  • Lines = Lista odcinków linii, gdzie każdy odcinek jest połączeniem kolejnych punktów. Jeśli nie są podane indeksy linii, ta lista jest automatycznie generowana.

Obliczanie wektorów stycznych do krzywej poprzez różnicę pomiędzy współrzędnymi punktów końcowych i początkowych odcinków linii.

  • Lines(:,1) = indeksy początkowych punktów odcinków linii.
  • Lines(:,2) = indeksy końcowych punktów odcinków linii.
  • Vertices(Lines(:,1),:) = współrzędne początkowych punktów odcinków linii.
  • Vertices(Lines(:,2),:) = współrzędne końcowych punktów odcinków linii.

Wpływ wektorów stycznych na odległość dla każdego punktu/wierzchołka krzywej:

  • LL: Obliczana jest długość wektorów stycznych DT za pomocą funkcji sqrt(DT(:,1).^2+DT(:,2).^2).

  • DT(:,1)=DT(:,1)./max(LL.^2,eps): Normalizowane są współrzędne x wektorów stycznych przez kwadrat długości wektora (LL), z tym że minimalna wartość to eps (najmniejsza wartość reprezentowalna w danej precyzji arytmetyki).

  • DT(:,2)=DT(:,2)./max(LL.^2,eps): Normalizowane są współrzędne y wektorów stycznych przez kwadrat długości wektora (LL), z tym że minimalna wartość to eps.

  • D1=zeros(size(Vertices)); D1(Lines(:,1),:)=DT;: Tworzona jest macierz zerowa D1 o takim samym rozmiarze jak lista punktów/wierzchołków. Następnie wiersze odpowiadające początkowym punktom odcinków linii otrzymują wartości wektorów stycznych DT.

  • D2=zeros(size(Vertices)); D2(Lines(:,2),:)=DT;: Tworzona jest macierz zerowa D2 o takim samym rozmiarze jak lista punktów/wierzchołków. Następnie wiersze odpowiadające końcowym punktom odcinków linii otrzymują wartości wektorów stycznych DT.

  • D=D1+D2;: Sumowane są macierze D1 i D2, uzyskując macierz D, która zawiera wpływ wektorów stycznych na odległość dla każdego punktu/wierzchołka krzywej.

Normalizowanie wektorów normalnych:

  • LL: Obliczana jest długość wektorów normalnych D za pomocą funkcji sqrt(D(:,1).^2+D(:,2).^2).

  • N(:,1)=-D(:,2)./LL: Współrzędna x normalizowanego wektora normalnego jest ujemnym ilorazem współrzędnej y wektora normalnego przez długość LL.

  • N(:,2)= D(:,1)./LL: Współrzędna y normalizowanego wektora normalnego jest ilorazem współrzędnej x wektora normalnego przez długość LL.

Ostatecznie macierz N zawiera znormalizowane wektory normalne.

9 - Maksymalna prędkość na łuku

Opis kodu wyliczającego maksymalną prędkość bolidu na łuku korzystając z pliku zawierającego parametryczny opis opon i pliku opisującego model aerodynamiczny bolidu.

Opisany plik: Find_maximum_corner_speed.m

  • Czyszczenie środowiska
clear all
close all

Te dwie linie służą do czyszczenia środowiska MATLAB. clear all usuwa wszystkie zmienne z przestrzeni roboczej, a close all zamyka wszystkie otwarte okna graficzne.

  • Wczytywanie danych
load('Aero Downforce Daten.mat');    % Aero Daten

Ta linia wczytuje dane dotyczące sił aerodynamicznych z pliku .mat.

  • Wczytywanie danych opon
FileNameLocation = ('C19_CONTINENTAL_FORMULASTUDENT_205_470_R13_65kPa.tir');
TIRparam = loadTIR(FileNameLocation);

Te dwie linie wczytują dane o oponach z pliku .tir za pomocą funkcji loadTIR.

  • Inicjalizacja zmiennych
R = 10;
m = 280;
FZ_stat = 800;
k = 0;

Te linie inicjalizują zmienne używane w późniejszych obliczeniach. R to promień, m to masa, FZ_stat to statyczne obciążenie pionowe, a k to krok iteracji.

  • Pętla główna
for i = 1:8
    v1 = 5;
    v2 = 100;
    FZ_stat = 800 + (i-1)*200;
    ...
end

Ta pętla wykonuje obliczenia dla różnych wartości obciążenia pionowego. W każdej iteracji, FZ_stat jest zwiększane o 200 jednostek.

  • Obliczenia w pętli
while v1 < v2
    v1 = v1 + k;        
    Faero = interp1(v,FA,v1*3.6,'linear','extrap'); % [N] Abtriebskraft interpoliert        
    FZ(i) = FZ_stat + Faero/2;       
    v2 = sqrt(max(MF52_Fy_cs(0:-0.1:-12,FZ(i),0,0,TIRparam))*R/m);        
    k = k+0.0001;
end

Wewnątrz pętli głównej znajduje się pętla while, która wykonuje obliczenia dla danego obciążenia pionowego, dopóki pewien warunek nie zostanie spełniony. W każdej iteracji, v1 jest zwiększane o k, a k jest zwiększane o 0.0001.

  • Interpolacja siły aerodynamicznej
Faero = interp1(v,FA,v1*3.6,'linear','extrap'); % [N] Abtriebskraft interpoliert

Ta linia interpoluje siłę aerodynamiczną (Faero) na podstawie prędkości (v1).

  • Obliczanie obciążenia pionowego
FZ(i) = FZ_stat + Faero/2;

Ta linia oblicza obciążenie pionowe (FZ) na podstawie statycznego obciążenia pionowego (FZ_stat) i siły aerodynamicznej (Faero).

  • Obliczanie prędkości
v2 = sqrt(max(MF52_Fy_cs(0:-0.1:-12,FZ(i),0,0,TIRparam))*R/m);

Ta linia oblicza prędkość (v2) na podstawie obciążenia pionowego (FZ), promienia (R) i masy (m).

  • Obliczanie maksymalnego przyspieszenia bocznego
aQmax(i) = v2^2/R/9.81;

Ta linia oblicza maksymalne przyspieszenie boczne (aQmax) na podstawie prędkości (v2) i promienia (R).

  • Wykres wyników
scatter(FZ,aQmax)

Ta linia tworzy wykres punktowy (scatter plot), pokazujący maksymalne przyspieszenie boczne (aQmax) w funkcji obciążenia pionowego (FZ).

10 - Manadżer symulacji

simulationManager.m

Wstęp

simulationManager

Co się dzieje w ciele funkcji

  1. Na początku podejmowana jest próba przypisania zmiennej sensitivityID2 z klasy startingParameters załadowanej z pliku generateStartingParameters.m do zmiennej lokalnej o tej samej nazwie. Jeśli się nie uda przypisywana jest jej wartość “0”.

    W praktyce try powinien być wykonany, bo z pliku generateStartingParameters.m możemy wywnioskować, że w każdym przypadku będzie ta zmienna przechowywała jakąś wartość.


  1. Jeśli ilość kroków symulacji (numSteps) będzie większa od 1 oraz zmienna sensitivityID będzie różna od 0 (w praktyce; jeśli sensitivity analysis będzie wyłączone) to wykonuje się kod przedstawiony wyżej, gdzie funkcja zeros() tworzy tablicę o wymiarach 1 x numSteps wypełnioną zerami.

  1. W warunku mamy drugą wartość do śledzenia przy rysowaniu wykresu, czyli jeśli zaznaczony zostanie CheckBox włączający ją to warunek się spełni i wtedy:
    tic - uruchamia stoper
    wykonuje się pętla od 1 do numSteps z pętlą wewnętrzną z tym samym zakresem z przedstawionymi działaniami arytmetycznymi. Rezultatem tej pętli są wypiełnione tablice minValue i minValue2

    Ale jeśli warunek się nie spełni, czyli nie włączymy drugiej wartości do śledzenia to:
    tic - uruchamia stoper
    wykonuje się analogiczna pętla ale tylko dla minValue jak przedstawiono poniżej:


  1. Następnie zmienna steps jest zmniejszana o 1, żeby nie przekroczyć zakresu w następującej pętli równoległej, która do kolejnych komórek w tablicy result przypisuje wartości zwracane przez wywoływaną funkcję Vehiclesim_Endurance_GUI_Version() z parametrami
  • startingParameters
  • minValue()
  • minValue2()
  • sensitivityID
  • sensitivityID2

Do pliku z logami przez funkcję writeToLogfile zostaje zapisany czas wykonywania wszystkich powyższych operacji od momentu procedury tic do toc (zliczającej upłynięty czas).

Ładowana jest nazwa pliku z setupem.

Rezultaty są zapisywane do pliku .mat, dodając “_result” do nazwy, w tej samej lokalizacji co jest plik z setupem.

Jeśli jednak warunek 2. się nie spełni to wywoływana jest funkcja Vehiclesim_Endurance_GUI_Version(startingParameters).

11 - Parametry opon, poślizgi i siły

Opis parametryczny opon wraz z wyliczeniami poślizgów łączonych i czystych w osiach X i Y i sił działających na opony

Użyte pliki:

-Tires/C19_CONTINENTAL_FORMULASTUDENT_205_470_R13_65kPa.tir
-MF52_ALPHA_cs.m
-MF52_Fx_cs.m
-MF52_Fx_ps.m
-MF52_Fy_cs.m
-MF52_Fy_ps.m
-calculateLatTireforces.m
-calculateLongiTireForces.m
-calculateWheelloadLongDisp.m
-calculateWheelloadLatDisp.m
-calculateVTireStiff.m

Dokumentacja pliku parametrycznego opisu opony Continental

Plik zawiera parametryczny opis opony Continental, który jest używany do modelowania jej zachowania. Poniżej znajduje się dokumentacja poszczególnych sekcji tego pliku. WstępPlik zawiera informacje o marce opony, modelu, klasie, rozmiarze oraz innych parametrach fizycznych opony. Został wygenerowany przez Wilke Eikermanna i Hannesa Dettmanna z działu badań i rozwoju Continental Reifen Deutschland GmbH. Plik jest własnością Continental AG i jego dystrybucja jest możliwa tylko za wyraźnym zezwoleniem Continental AG lub jej spółek zależnych.

! : FILE_TYPE : TOF                                     
! : FILE_VERSION : 3                                       
! : TIRE_VERSION : MF-Tyre 5.2                             
!
! : COMMENT    : Tire Brand                                 CONTINENTAL                   
! : COMMENT    : Tire Trade                                 FORMULA STUDENT C19              
! : COMMENT    : Tire Class                                 Competition                    
! : COMMENT    : Tire Size                                  205/470 R13                    
! : COMMENT    : Tire Width                            [m]  0.200                         
! : COMMENT    : Tire Unloaded Radius                  [m]  0.235                         
! : COMMENT    : Tire Aspect Ratio                     [-]  0.34                           
! : COMMENT    : Rim Width                            [in]  7                             
! : COMMENT    : Rim Radius                            [m]  0.1651                        
! : COMMENT    : Inflation Pressure                  [kPa]  65                            

USE_MODE w modelu opony

USE_MODE to parametr w modelu opony, który określa, jakie obliczenia są wykonywane. Każda wartość USE_MODE odpowiada innemu zestawowi obliczeń:

  • 0: Oblicza tylko Fz (siłę pionową), nie wykonuje ewaluacji Magic Formula.
  • 1: Oblicza tylko Fx (siłę podłużną).
  • 2: Oblicza tylko Fy, Mx, Mz (siłę boczną, moment względem osi X i moment względem osi Z).
  • 3: Oblicza Fx, Fy, Mx, Mz bez kombinacji sił/momenty.
  • 4: Oblicza Fx, Fy, Mx, Mz z kombinacją sił/momenty. Dodanie 10 do dowolnej z powyższych wartości uwzględnia efekty relaksacji w obliczeniach. Na przykład, USE_MODE = 12 oznacza, że obliczenia są wykonywane tylko dla Fy, Mx, Mz i uwzględniają efekty relaksacji. Ważne jest, aby zauważyć, że model opony jest ważny tylko dla określonego USE_MODE. Inne tryby mogą nie dostarczyć dokładnych wyników, ponieważ model został skonstruowany do pracy w określonym trybie.

Jednostki

W pliku parametrycznym wszystkie dane podawane są w odniesieniu do jednostek układu SI

[UNITS]
LENGTH                    = 'meter'   
FORCE                     = 'newton'  
ANGLE                     = 'radians'
MASS                      = 'kg'      
TIME                      = 'second'

Model

Sekcja modelu zawiera informacje o typie modelu opony, wersji formatu pliku, stronie opony, trybie użycia i innych parametrach związanych z modelem opony.

[MODEL]
TYRESIDE                  = 'Right'   
PROPERTY_FILE_FORMAT      = 'MF_05'   
TYPE                      = 'TIR'     
FITTYP                    =           5    $typarr(  2)
USE_MODE                  =          14    $typarr(  1)
MFSAFE1                   =         121    $typarr(  3)
MFSAFE2                   =         121    $typarr(  4)
MFSAFE3                   =         242    $typarr(  5)
VXLOW                     = +1.000e+000    $typarr( 29)
LONGVL                    = +1.111e+001    $typarr( 30)

Wymiary

Sekcja wymiarów zawiera informacje o fizycznych wymiarach opony, takich jak promień opony bez obciążenia, szerokość opony, stosunek wysokości do szerokości, promień obręczy i szerokość obręczy.

[DIMENSION]
UNLOADED_RADIUS           = +2.350e-001    $typarr(  7)
WIDTH                     = +2.000e-001    $typarr(  8)
ASPECT_RATIO              = +3.400e-001    $typarr(  6)
RIM_RADIUS                = +1.651e-001    $typarr(  9)
RIM_WIDTH                 = +1.778e-001    $typarr( 10)

Kształt

Ten kod definiuje kształt opony za pomocą profilu bocznego opony wzdłuż jej szerokości. Każda linia reprezentuje punkt na profilu opony, gdzie pierwsza wartość to odległość od środka opony (wzdłuż promienia), a druga wartość to szerokość opony w tym punkcie.

  • 1.0 0.0 oznacza, że na początku (w środku opony), szerokość opony wynosi 0.0.
  • 1.0 0.4 oznacza, że gdy przechodzimy na zewnątrz opony, szerokość opony zwiększa się do 0.4.
  • 1.0 0.9 oznacza, że szerokość opony nadal rośnie, osiągając 0.9.
  • 0.9 1.0 oznacza, że na zewnątrz opony, szerokość opony osiąga swoje maksimum (1.0), ale odległość od środka opony nieznacznie się zmniejsza (0.9).

W ten sposób kod definiuje kształt opony jako profil boczny, który jest symetryczny względem osi opony. Wizualizacja tego kształtu przypominałaby krzywą, która jest szeroka na zewnątrz, ale zwęża się do środka opony.

[SHAPE]
{radial width}
 1.0    0.0
 1.0    0.4
 1.0    0.9
 0.9    1.0

Parametry pionowe

  • VERTICAL_STIFFNESS = Sztywność pionowa opony.
  • VERTICAL_DAMPING = Tłumienie pionowe opony.
  • BREFF = Parametr BREFF opony.
  • DREFF = Parametr DREFF opony.
  • FREFF = Parametr FREFF opony.
  • FNOMIN = Nominalna siła F opony.
[VERTICAL]
VERTICAL_STIFFNESS        = +8.600e+004    $typarr( 15)
VERTICAL_DAMPING          = +3.885e+003    $typarr( 16)
BREFF                     = +3.811E+000    $typarr( 11)
DREFF                     = +4.088e-001    $typarr( 12)
FREFF                     = +3.564e-002    $typarr( 13)
FNOMIN                    = +8.000e+002    $typarr( 14)

Zakresy

Sekcja: LONG_SLIP_RANGE

KPUMIN = -0.250e+000    $typarr( 23)
KPUMAX = +0.250e+000    $typarr( 24)
  • KPUMIN = Minimalna wartość długotrwałego poślizgu (KPU) dla opony.
  • KPUMAX = Maksymalna wartość długotrwałego poślizgu (KPU) dla opony.

Sekcja: SLIP_ANGLE_RANGE

ALPMIN = -2.094e-001    $typarr( 25)
ALPMAX = +2.094e-001    $typarr( 26)
  • ALPMIN = Minimalny kąt poślizgu (ALP) dla opony.
  • ALPMAX = Maksymalny kąt poślizgu (ALP) dla opony.

Sekcja: INCLINATION_ANGLE_RANGE

CAMMIN = -1.047e-001    $typarr( 27)
CAMMAX = +1.047e-001    $typarr( 28)
  • CAMMIN = Minimalny kąt nachylenia (CAM) dla opony.
  • CAMMAX = Maksymalny kąt nachylenia (CAM) dla opony.

Sekcja: VERTICAL_FORCE_RANGE

FZMIN = +2.286e+002    $typarr( 21)
FZMAX = +1.600e+003    $typarr( 22)
  • FZMIN = Minimalna siła pionowa (FZ) dla opony.
  • FZMAX = Maksymalna siła pionowa (FZ) dla opony.

Współczynniki

Współczynniki skalujące

LFZO  = 1  # Współczynnik skalowania nominalnego (ocenianego) obciążenia
LCX   = 1  # Współczynnik skalowania kształtu Fx
LMUX  = 1  # Współczynnik skalowania szczytowego współczynnika tarcia Fx
LEX   = 1  # Współczynnik skalowania czynnika krzywizny Fx
LKX   = 1  # Współczynnik skalowania sztywności poślizgu Fx
LHX   = 0  # Współczynnik skalowania przesunięcia poziomego Fx
LVX   = 0  # Współczynnik skalowania przesunięcia pionowego Fx
LGAX  = 1  # Współczynnik skalowania skrętu dla Fx
LCY   = 1  # Współczynnik skalowania kształtu Fy
LMUY  = 1  # Współczynnik skalowania szczytowego współczynnika tarcia Fy
LEY   = 1  # Współczynnik skalowania czynnika krzywizny Fy
LKY   = 1  # Współczynnik skalowania sztywności skrętnej Fy
LHY   = 0  # Współczynnik skalowania przesunięcia poziomego Fy
LVY   = 0  # Współczynnik skalowania przesunięcia pionowego Fy
LGAY  = 1  # Współczynnik skalowania skrętu dla Fy
LTR   = 1  # Współczynnik skalowania szczytu śladu pneumatycznego
LRES  = 0  # Współczynnik skalowania przesunięcia momentu resztkowego
LGAZ  = 1  # Współczynnik skalowania skrętu dla Mz
LXAL  = 1  # Współczynnik skalowania wpływu alfa na Fx
LYKA  = 1  # Współczynnik skalowania wpływu alfa na Fy
LVYKA = 1  # Współczynnik skalowania Fy indukowanego przez kappę
LS    = 1  # Współczynnik skalowania ramienia momentu Fx
LSGKP = 1  # Nie zdefiniowano
LSGAL = 1  # Nie zdefiniowano
LGYR  = 1  # Nie zdefiniowano
LMX   = 1  # Współczynnik skalowania momentu wywracającego
LVMX  = 0  # Współczynnik skalowania przesunięcia pionowego Mx
LMY   = 1  # Współczynnik skalowania momentu oporu toczenia  

Współczynniki w płaszczyźnie wzdłużnej i poprzecznej

Współczynniki w płaszczyźnie wzdłużnej opisują zachowanie opony podczas poślizgu podłużnego, zarówno w stanie czystego poślizgu, jak i poślizgu łączonego.

[LONGITUDINAL_COEFFICIENTS]
% Współczynniki - poślizg podłużny (poślizg czysty)
PCX1 = +1.786E+000 $typarr(61) % Współczynnik kształtu Cfx dla siły podłużnej
PDX1 = +2.933E+000 $typarr(62) % Tarcie podłużne Mux przy Fznom
PDX2 = -4.400E-001 $typarr(63) % Zmienność tarcia Mux z obciążeniem
PDX3 = +2.080E+001 $typarr(60) % Zmienność tarcia Mux z pochyleniem
PEX1 = +8.710E-001 $typarr(64) % Krzywizna podłużna Efx przy Fznom
PEX2 = -3.800E-002 $typarr(65) % Zmienność krzywizny Efx z obciążeniem
PEX3 = +0.000E+000 $typarr(66) % Zmienność krzywizny Efx z kwadratem obciążenia
PEX4 = +7.100E-002 $typarr(67) % Czynnik w krzywiznie Efx podczas jazdy
PKX1 = +8.531E+001 $typarr(68) % Sztywność poślizgu podłużnego Kfx/Fz przy Fznom
PKX2 = -2.025E+001 $typarr(69) % Zmienność sztywności poślizgu Kfx/Fz z obciążeniem
PKX3 = +5.000E-001 $typarr(70) % Wykładnik w sztywności poślizgu Kfx/Fz z obciążeniem
PHX1 = +0.000E+000 $typarr(71) % Przesunięcie poziome Shx przy Fznom
PHX2 = +0.000E+000 $typarr(72) % Zmienność przesunięcia Shx z obciążeniem
PVX1 = +0.000E+000 $typarr(73) % Przesunięcie pionowe Svx/Fz przy Fznom
PVX2 = +0.000E+000 $typarr(74) % Zmienność przesunięcia Svx/Fz z obciążeniem

% Współczynniki - poślizg podłużny (poślizg łączony)
RBX1 = +2.372E+001 $typarr(75) % Czynnik nachylenia dla redukcji Fx poślizgu łączonego
RBX2 = +2.597E+001 $typarr(76) % Zmienność nachylenia redukcji Fx z kappa
RCX1 = +7.495E-001 $typarr(77) % Czynnik kształtu dla redukcji Fx poślizgu łączonego
REX1 = -4.759E-001 $typarr(82) % Czynnik krzywizny łączonego Fx
REX2 = +8.109E-001 $typarr(83) % Czynnik krzywizny łączonego Fx z obciążeniem
RHX1 = +0.000E+000 $typarr(78) % Czynnik przesunięcia dla redukcji Fx poślizgu łączonego

Współczynniki w płaszczyźnie poprzecznej opisują zachowanie opony podczas poślizgu poprzecznego, zarówno w stanie czystego poślizgu, jak i poślizgu łączonego.

[LATERAL_COEFFICIENTS]
% Współczynniki - poślizg poprzeczny (poślizg czysty)
PCY1 = +1.725E+000 $typarr(91) % Współczynnik kształtu Cfx dla siły podłużnej
PDY1 = +2.733E+000 $typarr(92) % Tarcie podłużne Mux przy Fznom
PDY2 = -6.022E-001 $typarr(93) % Zmienność tarcia Mux z obciążeniem
PDY3 = +4.007E+000 $typarr(94) % Zmienność tarcia Mux z pochyleniem
PEY1 = -5.000E-001 $typarr(95) % Krzywizna podłużna Efx przy Fznom
PEY2 = -2.000E+000 $typarr(96) % Zmienność krzywizny Efx z obciążeniem
PEY3 = +2.260E-001 $typarr(97) % Zmienność krzywizny Efx z kwadratem obciążenia
PEY4 = -3.367E-002 $typarr(98) % Czynnik w krzywiznie Efx podczas jazdy
PKY1 = -5.047E+001 $typarr(99) % Sztywność poślizgu podłużnego Kfx/Fz przy Fznom
PKY2 = +1.923E+000 $typarr(100) % Zmienność sztywności poślizgu Kfx/Fz z obciążeniem
PKY3 = +2.877E-001 $typarr(101) % Wykładnik w sztywności poślizgu Kfx/Fz z obciążeniem
PHY1 = +0.000E+000 $typarr(102) % Przesunięcie poziome Shx przy Fznom
PHY2 = +0.000E+000 $typarr(103) % Zmienność przesunięcia Shx z obciążeniem
PHY3 = -1.810E-002 $typarr(104) % Zmienność przesunięcia Shx z obciążeniem
PVY1 = +0.000E+000 $typarr(105) % Przesunięcie pionowe Svx/Fz przy Fznom
PVY2 = +0.000E+000 $typarr(106) % Zmienność przesunięcia Svx/Fz z obciążeniem
PVY3 = -2.649E+000 $typarr(107) % Przesunięcie pionowe Svx/Fz przy Fznom
PVY4 = -1.058E+000 $typarr(108) % Zmienność przesunięcia Svx/Fz z obciążeniem

% Współczynniki - poślizg poprzeczny (poślizg łączony)
RBY1 = +2.033E+001 $typarr(109) % Czynnik nachylenia dla redukcji Fx poślizgu łączonego
RBY2 = +8.152E+000 $typarr(110) % Zmienność nachylenia redukcji Fx z kappa
RBY3 = -1.243E-002 $typarr(111) % Zmienność nachylenia redukcji Fx z kappa
RCY1 = +9.317E-001 $typarr(112) % Czynnik kształtu dla redukcji Fx poślizgu łączonego
REY1 = -3.982E-004 $typarr(113) % Czynnik krzywizny łączonego Fx
REY2 = +3.077E-001 $typarr(114) % Czynnik krzywizny łączonego Fx z obciążeniem
RHY1 = +0.000E+000 $typarr(115) % Czynnik przesunięcia dla redukcji Fx poślizgu łączonego
RHY2 = +0.000E+000 $typarr(116) % Czynnik przesunięcia dla redukcji Fx poślizgu łączonego
RVY1 = +0.000E+000 $typarr(117) % Czynnik przesunięcia dla redukcji Fx poślizgu łączonego
RVY2 = +0.000E+000 $typarr(118) % Czynnik przesunięcia dla redukcji Fx poślizgu łączonego
RVY3 = +0.000E+000 $typarr(119) % Czynnik przesunięcia dla redukcji Fx poślizgu łączonego
RVY4 = +0.000E+000 $typarr(120) % Czynnik przesunięcia dla redukcji Fx poślizgu łączonego
RVY5 = +0.000E+000 $typarr(121) % Czynnik przesunięcia dla redukcji Fx poślizgu łączonego
RVY6 = +0.000E+000 $typarr(122) % Czynnik przesunięcia dla redukcji Fx poślizgu łączonego
PTY1 = +3.260e+000 $typarr(123) % Czynnik przesunięcia dla redukcji Fx poślizgu łączonego
PTY2 = +2.250e+000 $typarr(124) % Czynnik przesunięcia dla redukcji Fx poślizgu łączonego

Współczynniki toczenia

QSY1 				= -3.090E-002			$typarr(126)
QSY2 				= -9.210E-002			$typarr(127)
QSY3 				= +0.000e+000			$typarr(128)
QSY4 				= +0.000e+000			$typarr(129)

Współczynniki nadsterowności (overturning)

QSX1 				= +0.000E+000			$typarr( 86)
QSX2 				= +1.269E+000			$typarr( 87)
QSX3 				= -2.807E-003			$typarr( 88)

Współczynniki korygujące (aligning)

QBZ1				= +6.895E+000			$typarr(131)
QBZ2				= +2.394E+000			$typarr(132)
QBZ3				= -3.945E+000			$typarr(133)
QBZ4				= +0.000E+000			$typarr(134)
QBZ5				= -1.369E-003			$typarr(135)
QBZ9				= +2.684E-007			$typarr(136)
QBZ10				= +1.994E+000			$typarr(130)
QCZ1				= +1.139E+000			$typarr(137)
QDZ1				= +1.396E-001			$typarr(138)
QDZ2				= -1.797E-002			$typarr(139)
QDZ3				= +0.000E+000			$typarr(140)
QDZ4				= -9.072E+000			$typarr(141)
QDZ6				= -2.000E-001			$typarr(142)
QDZ7				= +5.000E-001			$typarr(143)
QDZ8				= -1.406E+000			$typarr(144)
QDZ9				= +4.252E-001			$typarr(145)
QEZ1				= -9.783E+000			$typarr(146)
QEZ2				= +8.208E+000			$typarr(147)
QEZ3				= -2.000E+001			$typarr(148)
QEZ4				= -1.832E-001			$typarr(149)
QEZ5				= -6.352E+000			$typarr(150)
QHZ1				= +0.000E+000			$typarr(151)
QHZ2				= +0.000E+000			$typarr(152)
QHZ3				= +1.186E-001			$typarr(153)
QHZ4				= -5.376E-002			$typarr(154)
SSZ1				= +0.000E+000			$typarr(155)
SSZ2				= +4.650E-003			$typarr(156)
SSZ3				= -1.530E+000			$typarr(157)
SSZ4				= +0.000E+000			$typarr(158)
QTZ1				= +1.000E+000			$typarr(159)
MBELT				= +2.700E+000			$typarr(160)

Niestety nie znaleziono objaśnień dla współczynników toczenia, nadsterowności i korygujących.

Obliczenia poślizgów

Poślizg łączony w kierunku wzdłużnym

SHXA = RHX1;        
ALPHAS = ALPHA + SHXA;  
BXA = (RBX1 + RBX3 .* GAMMA^2) .* cos(atan(RBX2 .* KAPPA)) .* LXAL;
CXA = RCX1;
EXA = REX1 + REX2 * DFZ;
GXA0 = cos(CXA .* atan(BXA .* ALPHAS - EXA .* (BXA .* ALPHAS - atan(BXA .* ALPHAS))));
GXA = GXA0 ./ cos(CXA .*atan(BXA .* SHXA - EXA .* (BXA .* SHXA - atan(BXA .* SHXA))));

FX = FX0 .* GXA;    

SHXA = RHX1;
Ustawienie przesunięcia poziomego SHXA na wartość współczynnika RHX1, który opisuje przesunięcie poziome dla redukcji siły Fx przy poślizgu łączonym.

ALPHAS = ALPHA + SHXA;
Korekta kąta poślizgu (ALPHA) o przesunięcie poziome (SHXA), dając skorygowany kąt poślizgu ALPHAS.

BXA = (RBX1 + RBX3 .* GAMMA^2) .* cos(atan(RBX2 .* KAPPA)) .* LXAL;
Obliczenie BXA, czynnika nachylenia dla redukcji siły Fx przy poślizgu łączonym, z uwzględnieniem kąta nachylenia GAMMA, poślizgu KAPPA oraz współczynnika skalowania LXAL, wpływającego na Fx zależnie od kąta alfa.

CXA = RCX1;
Ustawienie CXA na wartość współczynnika RCX1, który określa kształt funkcji redukcji siły Fx przy poślizgu łączonym.

EXA = REX1 + REX2 * DFZ;
Obliczenie EXA, czynnika krzywizny łączonego Fx, z uwzględnieniem zmiany obciążenia pionowego opony DFZ.

GXA0 = cos(CXA .* atan(BXA .* ALPHAS - EXA .* (BXA .* ALPHAS - atan(BXA .* ALPHAS))));
Obliczenie GXA0, pierwotnej wartości funkcji kształtu siły Fx, na podstawie skorygowanego kąta poślizgu ALPHAS, czynnika nachylenia BXA, kształtu funkcji CXA i czynnika krzywizny EXA.

GXA = GXA0 ./ cos(CXA .*atan(BXA .* SHXA - EXA .* (BXA .* SHXA - atan(BXA .* SHXA))));
Normalizacja GXA0 poprzez podzielenie przez wartość korygującą, aby uwzględnić przesunięcie poziome SHXA w obliczeniach, dając końcową wartość funkcji kształtu siły Fx GXA.

FX = FX0 .* GXA;
Obliczenie końcowej siły poślizgu podłużnego FX, mnożąc pierwotną siłę podłużną FX0 przez funkcję kształtu GXA.

Czysty poślizg w kierunku wzdłużnym

GAMMAX = GAMMA .* LGAX;
SHX = (PHX1 + PHX2 .* DFZ) .* LHX;
KAPPAX = KAPPA + SHX;
CX = PCX1 .* LCX;
MUX = (PDX1 + PDX2 .* DFZ) .* (1 - PDX3 .* GAMMAX.^2) .* LMUX;
DX = MUX .* Fz;
EX = (PEX1 + PEX2 .* DFZ + PEX3 .* DFZ.^2) .* (1 - PEX4 .* sign(KAPPAX)) .* LEX;
KX = Fz .* (PKX1 + PKX2 .* DFZ) .* exp(PKX3 .* DFZ) .* LKX;
BX = KX ./ (CX .* DX);
SVX = Fz .* (PVX1 + PVX2 .* DFZ) .* LVX .* LMUX;

FX0 = DX .* sin(CX .* atan(BX .* KAPPAX - EX .* (BX .* KAPPAX - atan(BX .* KAPPA)))) + SVX;

FX = FX0;

GAMMAX = GAMMA .* LGAX;
Korekta kąta nachylenia GAMMA przez współczynnik skalowania LGAX, dając skorygowany kąt nachylenia GAMMAX.

SHX = (PHX1 + PHX2 .* DFZ) .* LHX;
Obliczenie przesunięcia poziomego SHX w oparciu o zmianę obciążenia pionowego DFZ i współczynnik skalowania LHX, uwzględniając podstawowe przesunięcie PHX1 i jego zmienność z DFZ (PHX2).

KAPPAX = KAPPA + SHX;
Korekta poślizgu KAPPA o przesunięcie poziome SHX, dając skorygowany poślizg KAPPAX.

CX = PCX1 .* LCX;
Ustawienie sztywności kształtu CX na podstawie podstawowego współczynnika PCX1 i współczynnika skalowania LCX.

MUX = (PDX1 + PDX2 .* DFZ) .* (1 - PDX3 .* GAMMAX.^2) .* LMUX;
Obliczenie szczytowego współczynnika tarcia MUX z uwzględnieniem zmiany obciążenia pionowego DFZ, skorygowanego kąta nachylenia GAMMAX, oraz współczynnika skalowania LMUX.

DX = MUX .* Fz;
Obliczenie siły podstawowej DX jako produkt szczytowego współczynnika tarcia MUX i obciążenia pionowego Fz.

EX = (PEX1 + PEX2 .* DFZ + PEX3 .* DFZ.^2) .* (1 - PEX4 .* sign(KAPPAX)) .* LEX;
Obliczenie czynnika krzywizny EX, uwzględniając zmianę obciążenia pionowego DFZ, znak skorygowanego poślizgu KAPPAX i współczynnik skalowania LEX.

KX = Fz .* (PKX1 + PKX2 .* DFZ) .* exp(PKX3 .* DFZ) .* LKX;
Obliczenie sztywności poślizgu KX jako funkcji obciążenia pionowego Fz, zmiany obciążenia DFZ i współczynnika skalowania LKX.

BX = KX ./ (CX .* DX);
Obliczenie sztywności kształtu BX jako stosunek sztywności poślizgu KX do iloczynu sztywności kształtu CX i siły podstawowej DX.

SVX = Fz .* (PVX1 + PVX2 .* DFZ) .* LVX .* LMUX;
Obliczenie przesunięcia pionowego SVX jako funkcji obciążenia pionowego Fz, zmiany obciążenia DFZ, współczynnika skalowania LVX oraz wpływu szczytowego współczynnika tarcia LMUX.

FX0 = DX .* sin(CX .* atan(BX .* KAPPAX - EX .* (BX .* KAPPAX - atan(BX .* KAPPA)))) + SVX;
Obliczenie siły poślizgu podłużnego FX0 z uwzględnieniem podstawowej siły DX, czynnika kształtu CX, sztywności kształtu BX, skorygowanego poślizgu KAPPAX, czynnika krzywizny EX oraz przesunięcia pionowego SVX.

FX = FX0;
Przypisanie ostatecznej wartości siły poślizgu podłużnego FX na podstawie obliczonej wartości FX0.

Poślizg łączony w kierunku poprzecznym

SHYK = RHY1 + RHY2 .* DFZ;       
KAPPAS = KAPPA + SHYK;
BYK = RBY1 .* cos(atan(RBY2 .* (ALPHA - RBY3))) .* LYKA;
CYK = RCY1;
EYK = REY1 + REY2 * DFZ;
DYK = FY0 ./ (cos(CYK .* atan(BYK .* SHYK - EYK .* (BYK .* SHYK - atan(BYK .* SHYK)))));
DVYK = MUY .* Fz .* (RVY1 + RVY2 .* DFZ + RVY3 .* GAMMA) .* cos(atan(RVY4 .* ALPHA));
SVYK = DVYK .* sin(RVY5 .* atan(RVY6 .* KAPPA)) .* LVYKA;
GYK0 = cos(CYK .* atan(BYK .* KAPPAS - EYK .* (BYK .* KAPPAS - atan(BYK .* KAPPAS))));
GYK = GYK0 ./ (cos(CYK .* atan(BYK .* SHYK - EYK .* (BYK .* SHYK - atan(BYK .* SHYK)))));

FY = FY0 .* GYK + SVYK;

SHYK = RHY1 + RHY2 .* DFZ;
Obliczenie przesunięcia poziomego SHYK na podstawie zmiany obciążenia pionowego DFZ i stałych RHY1 oraz RHY2.

KAPPAS = KAPPA + SHYK;
Korekta poślizgu KAPPA o przesunięcie poziome SHYK, dając skorygowany poślizg KAPPAS.

BYK = RBY1 .* cos(atan(RBY2 .* (ALPHA - RBY3))) .* LYKA;
Obliczenie współczynnika kształtu BYK dla bocznej siły poślizgu, uwzględniając kąt poślizgu ALPHA i współczynnik skalowania LYKA, który wpływa na relację między kątem poślizgu a siłą boczną.

CYK = RCY1;
Ustawienie wartości sztywności kształtu CYK na stałą RCY1.

EYK = REY1 + REY2 * DFZ;
Obliczenie czynnika krzywizny EYK w oparciu o zmianę obciążenia pionowego DFZ i stałe REY1 oraz REY2.

DYK = FY0 ./ (cos(CYK .* atan(BYK .* SHYK - EYK .* (BYK .* SHYK - atan(BYK .* SHYK)))));
Obliczenie siły podstawowej DYK dla bocznej siły poślizgu, korzystając z podstawowej wartości siły bocznej FY0 i korygując ją o czynniki kształtu BYK, sztywności CYK oraz krzywizny EYK.

DVYK = MUY .* Fz .* (RVY1 + RVY2 .* DFZ + RVY3 .* GAMMA) .* cos(atan(RVY4 .* ALPHA));
Obliczenie wartości pionowego przesunięcia DVYK na podstawie szczytowego współczynnika tarcia MUY, obciążenia pionowego Fz, zmiany obciążenia DFZ, kąta nachylenia GAMMA i kąta poślizgu ALPHA.

SVYK = DVYK .* sin(RVY5 .* atan(RVY6 .* KAPPA)) .* LVYKA;
Obliczenie dodatkowego składnika siły bocznej SVYK, który jest funkcją przesunięcia pionowego DVYK, poślizgu KAPPA oraz współczynnika skalowania LVYKA, wpływającego na siłę boczną indukowaną przez poślizg.

GYK0 = cos(CYK .* atan(BYK .* KAPPAS - EYK .* (BYK .* KAPPAS - atan(BYK .* KAPPAS))));
Obliczenie pierwotnej wartości funkcji kształtu siły bocznej GYK0, na podstawie korygowanego poślizgu KAPPAS, czynnika kształtu BYK, sztywności CYK oraz krzywizny EYK.

GYK = GYK0 ./ (cos(CYK .* atan(BYK .* SHYK - EYK .* (BYK .* SHYK - atan(BYK .* SHYK)))));
Normalizacja GYK0 przez podzielenie przez korektę, aby uwzględnić przesunięcie poziome SHYK w obliczeniach, dając końcową wartość funkcji kształtu siły bocznej GYK.

FY = FY0 .* GYK + SVYK;
Obliczenie końcowej bocznej siły poślizgu FY, mnożąc podstawową siłę boczną FY0 przez funkcję kształtu GYK i dodając składnik przesunięcia pionowego SVYK.

Czysty poślizg w kierunku poprzecznym

GAMMAY = GAMMA .* LGAY;
SHY = (PHY1 + PHY2 .* DFZ) .* LHY + PHY3 .* GAMMAY;
ALPHAY = ALPHA + SHY;
CY = PCY1 .* LCY;
MUY = (PDY1 + PDY2 .* DFZ) .* (1 - PDY3 .* GAMMAY.^2) .* LMUY;
DY = MUY .* Fz;
EY = (PEY1 + PEY2 .* DFZ) .* (1 - (PEY3 + PEY4 .* GAMMAY) .* sign(ALPHAY)) .* LEY;
KY = PKY1 .* FZ0 .* sin(2 * atan(Fz ./ (PKY2 .* FZ0 .* LFZO))) .* (1 - PKY3 .* abs(GAMMAY)) .* LFZO .* LKY;
BY = KY ./ (CY .* DY);
SVY = Fz .* ((PVY1 + PVY2 .* DFZ) .* LVY + (PVY3 + PVY4 .* DFZ) .* GAMMAY) .* LMUY;

FY0 = DY .* sin(CY .* atan(BY .* ALPHAY - EY .* (BY .* ALPHAY - atan(BY .* ALPHAY)))) + SVY;

FY = FY0;

GAMMAY = GAMMA .* LGAY;
Skorygowany kąt nachylenia GAMMAY, który uwzględnia współczynnik skalowania LGAY.

SHY = (PHY1 + PHY2 .* DFZ) .* LHY + PHY3 .* GAMMAY;
Przesunięcie poziome SHY, które uwzględnia zmianę obciążenia pionowego (DFZ), skorygowany kąt nachylenia (GAMMAY), oraz współczynniki skalowania LHY i PHY3.

ALPHAY = ALPHA + SHY;
Skorygowany kąt poślizgu ALPHAY, który uwzględnia przesunięcie poziome SHY.

CY = PCY1 .* LCY;
Sztywność kształtu CY, obliczona na podstawie współczynnika PCY1 i współczynnika skalowania LCY.

MUY = (PDY1 + PDY2 .* DFZ) .* (1 - PDY3 .* GAMMAY.^2) .* LMUY;
Szczytowy współczynnik tarcia MUY, który uwzględnia zmianę obciążenia pionowego (DFZ), skorygowany kąt nachylenia (GAMMAY), oraz współczynnik skalowania LMUY.

DY = MUY .* Fz;
Podstawowa siła DY, obliczona jako produkt szczytowego współczynnika tarcia MUY i obciążenia pionowego Fz.

EY = (PEY1 + PEY2 .* DFZ) .* (1 - (PEY3 + PEY4 .* GAMMAY) .* sign(ALPHAY)) .* LEY;
Czynnik krzywizny EY, który uwzględnia zmianę obciążenia pionowego (DFZ), skorygowany kąt nachylenia (GAMMAY), znak skorygowanego kąta poślizgu (ALPHAY), oraz współczynnik skalowania LEY.

KY = PKY1 .* FZ0 .* sin(2 * atan(Fz ./ (PKY2 .* FZ0 .* LFZO))) .* (1 - PKY3 .* abs(GAMMAY)) .* LFZO .* LKY;
Sztywność KY, obliczona na podstawie nominalnego obciążenia pionowego FZ0, obciążenia pionowego Fz, skorygowanego kąta nachylenia (GAMMAY), oraz współczynników skalowania LFZO i LKY.

BY = KY ./ (CY .* DY);
Stosunek sztywności BY, obliczony jako stosunek sztywności KY do iloczynu sztywności kształtu CY i podstawowej siły DY.

SVY = Fz .* ((PVY1 + PVY2 .* DFZ) .* LVY + (PVY3 + PVY4 .* DFZ) .* GAMMAY) .* LMUY;
Przesunięcie pionowe SVY, które uwzględnia obciążenie pionowe Fz, zmianę obciążenia pionowego (DFZ), skorygowany kąt nachylenia (GAMMAY), oraz współczynniki skalowania LVY i LMUY.

FY0 = DY .* sin(CY .* atan(BY .* ALPHAY - EY .* (BY .* ALPHAY - atan(BY .* ALPHAY)))) + SVY;
Podstawowa siła boczna FY0, obliczona jako suma siły DY pomnożonej przez funkcję trygonometryczną, która uwzględnia sztywność kształtu CY, stosunek sztywności BY, skorygowany kąt poślizgu ALPHAY, czynnik krzywizny EY, oraz przesunięcie pionowe SVY.

FY = FY0;
Przypisanie ostatecznej wartości siły bocznej FY na podstawie obliczonej wartości FY0.

Poślizg Alfa w kierunku poprzecznym (czysty)

GAMMAY = GAMMA .* LGAY;
SHY = (PHY1 + PHY2 .* DFZ) .* LHY + PHY3 .* GAMMAY;
ALPHAY = ALPHA + SHY;
CY = PCY1 .* LCY;
MUY = (PDY1 + PDY2 .* DFZ) .* (1 - PDY3 .* GAMMAY.^2) .* LMUY;
DY = MUY .* Fz;
EY = (PEY1 + PEY2 .* DFZ) .* (1 - (PEY3 + PEY4 .* GAMMAY) .* sign(ALPHAY)) .* LEY;
KY = PKY1 .* FZ0 .* sin(2 * atan(Fz ./ (PKY2 .* FZ0 .* LFZO))) .* (1 - PKY3 .* abs(GAMMAY)) .* LFZO .* LKY;
BY = KY ./ (CY .* DY);
SVY = Fz .* ((PVY1 + PVY2 .* DFZ) .* LVY + (PVY3 + PVY4 .* DFZ) .* GAMMAY) .* LMUY;

FY0 = DY .* sin(CY .* atan(BY .* ALPHAY - EY .* (BY .* ALPHAY - atan(BY .* ALPHAY)))) + SVY;

FY = FY0;

GAMMAY = GAMMA .* LGAY;
Dostosowuje kąt nachylenia (GAMMA) przez współczynnik skalowania (LGAY), aby uwzględnić wpływ nachylenia na generowanie siły bocznej.

SHY = (PHY1 + PHY2 .* DFZ) .* LHY + PHY3 .* GAMMAY;
Oblicza poziome przesunięcie (SHY) krzywej siły bocznej spowodowane zmianą obciążenia pionowego (DFZ) i kątem nachylenia (GAMMAY), wykorzystując współczynniki skalowania LHY i PHY3.

ALPHAY = ALPHA + SHY;
Dostosowuje kąt poślizgu (ALPHA) o obliczone poziome przesunięcie (SHY), uwzględniając zmieniony efektywny kąt poślizgu ze względu na zmiany obciążenia i nachylenia.

CY = PCY1 .* LCY;
Określa współczynnik kształtu (CY) dla siły bocznej, uwzględniając podstawową wartość (PCY1) i współczynnik skalowania (LCY).

MUY = (PDY1 + PDY2 .* DFZ) .* (1 - PDY3 .* GAMMAY.^2) .* LMUY;
Oblicza szczytowy współczynnik tarcia (MUY) dla siły bocznej, uwzględniając zmianę obciążenia pionowego (DFZ), kwadrat kąta nachylenia (GAMMAY^2) i współczynnik skalowania LMUY.

DY = MUY .* Fz;
Oblicza podstawową siłę boczną (DY) poprzez pomnożenie szczytowego współczynnika tarcia (MUY) przez obciążenie pionowe (Fz).

EY = (PEY1 + PEY2 .* DFZ) .* (1 - (PEY3 + PEY4 .* GAMMAY) .* sign(ALPHAY)) .* LEY;
Określa czynnik krzywizny (EY) dla krzywej siły bocznej, biorąc pod uwagę zmianę obciążenia pionowego (DFZ), kąt nachylenia (GAMMAY), znak dostosowanego kąta poślizgu (ALPHAY) oraz współczynnik skalowania LEY.

KY = PKY1 .* FZ0 .* sin(2 * atan(Fz ./ (PKY2 .* FZ0 .* LFZO))) .* (1 - PKY3 .* abs(GAMMAY)) .* LFZO .* LKY;
Oblicza sztywność przy skręcaniu (KY), uwzględniając nominalne obciążenie pionowe (FZ0), rzeczywiste obciążenie pionowe (Fz), kąt nachylenia (GAMMAY) oraz współczynniki skalowania LFZO i LKY.

BY = KY ./ (CY .* DY);
Określa współczynnik sztywności (BY) dla krzywej siły bocznej na podstawie sztywności przy skręcaniu (KY), współczynnika kształtu (CY) i podstawowej siły bocznej (DY).

SVY = Fz .* ((PVY1 + PVY2 .* DFZ) .* LVY + (PVY3 + PVY4 .* DFZ) .* GAMMAY) .* LMUY;
Oblicza pionowe przesunięcie (SVY) krzywej siły bocznej ze względu na zmianę obciążenia pionowego (DFZ), kąt nachylenia (GAMMAY) i współczynniki skalowania LVY i LMUY.

FY0 = DY .* sin(CY .* atan(BY .* ALPHAY - EY .* (BY .* ALPHAY - atan(BY .* ALPHAY)))) + SVY;
Oblicza początkową siłę boczną (FY0) jako sumę siły (DY) pomnożonej przez funkcję trygonometryczną, uwzględniającą współczynnik kształtu (CY), współczynnik sztywności (BY), dostosowany kąt poślizgu (ALPHAY), czynnik krzywizny (EY) oraz pionowe przesunięcie (SVY).

FY = FY0;
Przypisuje końcową wartość siły bocznej (FY) na podstawie obliczonej wartości początkowej (FY0).

Obliczanie sił poprzecznych

Plik calculateLatTireforces.m zawiera funkcję służącą do obliczania maksymalnych sił bocznych (poprzecznych), które mogą być przenoszone przez opony pojazdu. Stworzona przez Erica Dorniedena z zespołu Baltic Racing, funkcja ta jest chroniona prawami autorskimi tej organizacji z roku 2021.

Obliczanie sił

Funkcja calculateLatTireforces przyjmuje jako argumenty siły pionowe działające na poszczególne koła pojazdu (FWZ_vl, FWZ_vr, FWZ_hl, FWZ_hr), kąt nachylenia opony względem podłoża (GAMMA), parametry opony (TIRparam), a także początkowe kąty poślizgu dla opon przednich (alpha_f) i tylnych (alpha_r). Zwraca maksymalne siły boczne dla każdego koła (FWYmax_fl, FWYmax_fr, FWYmax_rl, FWYmax_rr), całkowite siły boczne dla osi przedniej i tylnej (FWYmax_f, FWYmax_r), oraz obliczone kąty poślizgu dla opon przednich i tylnych (alpha_f, alpha_r).

Główna funkcja

W zależności od liczby argumentów, funkcja używa dwóch różnych metod obliczania sił bocznych:

  1. Dla ośmiu argumentów, obliczenia są bezpośrednie, wykorzystując funkcję MF52_Fy_cs do określenia maksymalnej siły bocznej dla każdej opony:

    FWYmax_fl = max(abs(MF52_Fy_cs(alpha_f,FWZ_vl,GAMMA,0,TIRparam)));
    
  2. Gdy liczba argumentów jest mniejsza niż osiem, funkcja przeprowadza iteracyjne obliczenia dla zakresu kątów poślizgu od 0 do 12 stopni (co 0,025 stopnia), wybierając wartość maksymalną i odpowiadający jej kąt poślizgu dla każdej opony:

    x = 0:0.025:12; % Zakres kątów poślizgu [deg]
    [FWYmax_fl, index] = max(abs(MF52_Fy_cs(x,FWZ_vl,GAMMA,0,TIRparam)));
    alpha_fl = x(index);
    

Wynikowe Siły Osi

Na koniec, funkcja sumuje siły boczne dla opon położonych po tej samej stronie osi, aby uzyskać całkowitą siłę boczną, jaką może przenieść oś przednia i tylna:

FWYmax_f = FWYmax_fl + FWYmax_fr; % [N] Maksymalna siła boczna osi przedniej

Obliczanie sił wzdłużnych

Plik calculateLongiTireforces.m zawiera funkcję do obliczania maksymalnych sił podłużnych, które mogą być przenoszone przez opony pojazdu. Autorem kodu jest Eric Dornieden z zespołu Baltic Racing, a prawa autorskie należą do Baltic Racing z 2021 roku.

Główna Funkcja

Funkcja calculateLongiTireforces akceptuje jako argumenty wejściowe siły pionowe działające na każde koło pojazdu (FWZ_vl, FWZ_vr, FWZ_hl, FWZ_hr), kąt nachylenia opony (GAMMA), parametry opon (TIRparam) oraz kąty poślizgu dla opon przednich (alpha_f) i tylnych (alpha_r). Funkcja zwraca maksymalne siły podłużne dla każdej z opon (FWXmax_fl, FWXmax_fr, FWXmax_rl, FWXmax_rr) oraz sumaryczne maksymalne siły podłużne dla osi przedniej i tylnej (FWXmax_f, FWXmax_r).

Obliczanie Sił

Funkcja wykorzystuje różne metody obliczania maksymalnych sił podłużnych w zależności od liczby przekazanych argumentów:

  1. Dla ośmiu argumentów funkcja bezpośrednio oblicza maksymalną siłę podłużną dla każdej opony, używając funkcji MF52_Fx_cs, która prawdopodobnie modeluje siły opon na podstawie danych takich jak kąt poślizgu, obciążenie pionowe, kąt przechylenia i parametry opony:

    FWXmax_fl = max(abs(MF52_Fx_cs(alpha_f,FWZ_vl,GAMMA,0:0.01:0.2,TIRparam)));
    
  2. Gdy liczba argumentów jest inna, funkcja zakłada kąt poślizgu równy zero i oblicza maksymalne siły podłużne dla każdej opony w oparciu o ten założony kąt poślizgu:

    FWXmax_fl = max(abs(MF52_Fx_cs(0,FWZ_vl,GAMMA,0:0.01:0.2,TIRparam)));
    

Wynikowe Siły Osi

Po obliczeniu maksymalnych sił podłużnych dla każdej opony, funkcja sumuje siły dla opon umieszczonych po tej samej stronie osi, aby określić całkowitą maksymalną siłę podłużną, którą może przenieść oś przednia i tylna:

FWXmax_f = FWXmax_fl + FWXmax_fr; % [N] Maksymalna siła podłużna osi przedniej  

Obciążenie dynamiczne w kierunku poprzecznym

Funkcja calculateWheelloadLatDisp oblicza przemieszczenie obciążenia koła w kierunku poprzecznym. Jest to kluczowy element w obliczaniu przeniesienia obciążenia koła.

Sygnatura funkcji

function [dFWZfl_y, dFWZfr_y, dFWZrl_y, dFWZrr_y, dFWZfl_geometric, dFWZfr_geometric, dFWZrl_geometric, dFWZrr_geometric, dFWZfl_elastic, dFWZfr_elastic, dFWZrl_elastic, dFWZrr_elastic] = calculateWheelloadLatDisp(h_COG, track_f, track_r, lr, lf, wheelbase, FVY, h_rc_f, h_rc_r)

Opis parametrów

  • h_COG: Wysokość środka ciężkości pojazdu.
  • track_f, track_r: Szerokość toru przedniego i tylnego koła.
  • lr, lf: Odległość od tylnego i przedniego końca pojazdu do środka ciężkości.
  • wheelbase: Rozstaw osi pojazdu.
  • FVY: Siła boczna działająca na pojazd.
  • h_rc_f, h_rc_r: Wysokość środka ciężkości przedniego i tylnego zawieszenia.

Opis działania

Funkcja oblicza przeniesienie obciążenia koła w kierunku poprzecznym na podstawie różnych parametrów pojazdu i sił działających na pojazd. Obliczenia są wykonywane dla każdego koła pojazdu.

  1. Przeniesienie obciążenia geometryczne:

    dFWZfl_geometric = -lr/wheelbase*FVY*h_rc_f/track_f;        % [N] Geometryczne przeniesienie obciążenia dla koła przedniego lewego
    dFWZfr_geometric = lr/wheelbase*FVY*h_rc_f/track_f;         % [N] Geometryczne przeniesienie obciążenia dla koła przedniego prawego
    dFWZrl_geometric = -lf/wheelbase*FVY*h_rc_r/track_r;        % [N] Geometryczne przeniesienie obciążenia dla koła tylnego lewego
    dFWZrr_geometric = lf/wheelbase*FVY*h_rc_r/track_r;         % [N] Geometryczne przeniesienie obciążenia dla koła tylnego prawego
    
  2. Przeniesienie obciążenia sprężyste:

    dFWZfl_elastic = -lr/wheelbase*FVY*(h_COG-h_rc_f)/track_f;  % [N] Elastyczne przeniesienie obciążenia dla koła przedniego lewego
    dFWZfr_elastic = lr/wheelbase*FVY*(h_COG-h_rc_f)/track_f;   % [N] Elastyczne przeniesienie obciążenia dla koła przedniego prawego
    dFWZrl_elastic = -lf/wheelbase*FVY*(h_COG-h_rc_r)/track_r;  % [N] Elastyczne przeniesienie obciążenia dla koła tylnego lewego
    dFWZrr_elastic = lf/wheelbase*FVY*(h_COG-h_rc_r)/track_r;   % [N] Elastyczne przeniesienie obciążenia dla koła tylnego prawego
    
  3. Dynamiczne przeniesienie obciążenia:

    dFWZfl_y = dFWZfl_geometric + dFWZfl_elastic;               % [N] Przeciążenie dynamiczne koła przedniego lewego
    dFWZfr_y = dFWZfr_geometric + dFWZfr_elastic;               % [N] Przeciążenie dynamiczne koła przedniego prawego
    dFWZrl_y = dFWZrl_geometric + dFWZrl_elastic;               % [N] Przeciążenie dynamiczne koła tylnego lewego
    dFWZrr_y = dFWZrr_geometric + dFWZrr_elastic;               % [N] Przeciążenie dynamiczne koła tylnego prawego
    

Obciążenie dynamiczne w kierunku wzdłużnym

Funkcja calculateWheelloadLongDisp oblicza dynamiczne przemieszczenie obciążenia koła w kierunku podłużnym. Jest to kluczowy element w obliczaniu przeniesienia obciążenia koła.

Sygnatura funkcji

function [dFWZfl_x, dFWZfr_x, dFWZrl_x, dFWZrr_x] = calculateWheelloadLongDisp(h_COG, m_ges, aVX, wheelbase)

Opis parametrów

  • h_COG: Wysokość środka ciężkości pojazdu.
  • m_ges: Masa całkowita pojazdu.
  • aVX: Przyspieszenie pojazdu w kierunku podłużnym.
  • wheelbase: Rozstaw osi pojazdu.

Opis działania

Funkcja oblicza dynamiczne przeniesienie obciążenia koła w kierunku podłużnym na podstawie różnych parametrów pojazdu i sił działających na pojazd. Obliczenia są wykonywane dla każdego koła pojazdu.

dFWZfl_x = -m_ges*aVX*h_COG/wheelbase

Sztywność pionowa opony

Funkcja calculateVtirestiff oblicza pionową sztywność opony dla każdego z czterech kół pojazdu.

Argumenty funkcji

Funkcja przyjmuje następujące argumenty:

  • Fz: Wektor sił pionowych dla różnych warunków.
  • cZ_tire: Wektor sztywności opony dla różnych warunków.
  • FWZ_fl, FWZ_fr, FWZ_rl, FWZ_rr: Siły pionowe działające na przednie lewe, przednie prawe, tylne lewe i tylne prawe koło pojazdu.

Działanie funkcji

Funkcja interpoluje sztywność opony (cZ_tire) na podstawie siły pionowej (Fz) dla każdego koła pojazdu. Interpolacja jest liniowa i ekstrapolowana poza zakres wektora Fz, jeśli to konieczne.

Wyniki funkcji

Funkcja zwraca cztery wartości: cZ_fl, cZ_fr, cZ_rl, cZ_rr, które reprezentują sztywność opony dla przedniego lewego, przedniego prawego, tylnego lewego i tylnego prawego koła pojazdu.

Snippet kodu

function [cZ_fl, cZ_fr, cZ_rl, cZ_rr] = calculateVtirestiff(Fz, cZ_tire, FWZ_fl, FWZ_fr, FWZ_rl, FWZ_rr)
    %% Vertical tire stiffness
    cZ_fl = interp1(Fz,cZ_tire,FWZ_fl,'linear','extrap'); % [N/m] Interpolated tire stiffness
    cZ_fr = interp1(Fz,cZ_tire,FWZ_fr,'linear','extrap'); % [N/m] Interpolated tire stiffness
    cZ_rl = interp1(Fz,cZ_tire,FWZ_rl,'linear','extrap'); % [N/m] Interpolated tire stiffness
    cZ_rr = interp1(Fz,cZ_tire,FWZ_rr,'linear','extrap'); % [N/m] Interpolated tire stiffness       
end

12 - Generowanie parametrów startowych

generateStartingParameters.m

Wstęp

Wyjaśnione są tutaj wszystkie parametry które ładowane są do klasy startingParameters, przekazywane dalej do funkcji simulationManager.m

Co się dzieje w ciele funkcji

  1. Na początku otwierany jest interfejs wyboru pliku. Zastosowany jest filtr na rozszerzenie pliku .mat. Do zmiennej carDatafile jest załadowywana nazwa wybranego pliku, a do zmiennej path jego ścieżka (bez nazwy samego pliku).

  2. Następnie do kolejnych zmiennych klasy startingParameters przypisywane są wartości pobrane z elementów interfejsu użytkownika (typu DropDown i CheckBox) i inne, jak przedstawiono poniżej:

Zmienna Co jest do niej przypisywane
disciplineID dyscyplina (z UI)
carDatafile carDatafile
path path
TrackFileName nazwa pliku toru
brakeFunction system hamulców (z UI)
logCellData informacja czy cell data zapisywać do pliku z logami
debugMessages informacja czy wypisywać logi do debugowania (z UI)
startingSpeed prędkość startowa dla wybranego toru
numOfLaps ilość okrążeń do przejechania dla wybranego toru
Debug wartość “0”

  1. Jeśli chcemy wyeksportować aplikację:
Zmienna Co jest do niej przypisywane
processDataButtonHandle przycisk rozpoczęcia symulacji
textAreaHandle pole tekstowe w zakładce “How-to”

W przeciwnym razie do obu tych zmiennych przypisywane są wartości “0”.


  1. Jeśli włączona jest analiza czułości:
Zmienna Co jest do niej przypisywane
sensitivityID co chcemy śledzić (z UI)
minValue minimalna wartość
stepSize rozmiar kroku
numSteps ilość kroków symulacji

Wewnątrz tej funkcji warunkowej występuje druga; jeśli zaznaczony jest CheckBox włączający drugi zestaw elementów UI to wyżej wymienione zmienne (poza numSteps) zostają powielone i przypisane do nich zostają wartości z odpowiadających im elementów UI.

W przeciwnym razie, przypisywane są do nich domyślne wartości “0” oraz dla numSteps “1”, co się tyczy zarówno pierwszej jak i drugiej funkcji warunkowej.


Na samym końcu wywoływana jest funkcja simulationManager() z parametrem klasa startingParameters czyli z całym zestawem zmiennych.

13 - Pliki .mat i .csv

Pliki .mat i .csv nie zawierają skryptów, są to zbiory danych jako wyniki symulacji, dane do symulacji czy parametryczne opisy tras.

Data Inspector

Folder zawiera pliki .csv i .mat, które są wynikami przeprowadzonych symulacji bądź danymi na których twórcy wzorowali się tworząc własną symulację.
Każdy plik z danymi o trasie ma inną strukturę a z danych wynika, że są to dane telemetryczne pojazdów podczas przejazdu na danej trasie, znajdują się tam między innymi informacje o temperaturach, balansie hamulców czy przeciążeniach.

Logged Data

Najważniejszym do analizy plikiem jest loggedDataTest.csv lub jego wariant loggedData.csv. Zawierają one informacje o przejazdach pojazdu po nieokreślonej w pliku trasie, jednak w nich najlepiej można zaobserwować zmiany parametrów pojazdu w trakcie jazdy.

Struktura pliku loggedDataTest

Struktura pliku loggedDataTest

Zdjęcie powyżej to fragment omawianego pliku, widać że są dane uzyskane z symulacji bądź zgrupowane dane z systemu telemetrycznego.

Trasy i przejazdy

Nurburgring.csv

Nurburgring.csv

Daytona.csv

Daytona.csv

Zdjęcia powyżej to przykady jak wygląda zbiór danych z przejazdu po trasie w przypadku pojazdów spoza klasy FORMULA STUDENT.

Dla przykładu plik Daytona.csv opisuje prędkości przejazdu po Daytonie przez Porsche 997. Kolejne kolumny pliku to prędkości notowane przez pojazd oraz przez GPS w różnych osiach, notowana jest także zmiana wysokości.

14 - oddziaływanie sił

działanie/obliczanie poszczególnych sił na pojazd

Wstęp

BrakeCalculation.mlx- opisywany plik, działanie poszczególnych funkcji

Działanie

  1. Zmienne wyświetlane na samym początku.

g = 9.81; - Przyspieszenie ziemskie w m/s^2. M = 282.283; - Masa pojazdu w kilogramach. prozF = 0.42582; - Procentowa masa na przedniej osi. prozR = 1 - prozF; - Procentowa masa na tylnej osi. Z = 2.3; - Współczynnik przesterowania. H = 250.338; - Wysokość środka ciężkości nad ziemią w milimetrach. l = 1530; - Środkowa odległość osi w milimetrach. lv = 878.488; - Odległość środka ciężkości pojazdu od tylnej osi w milimetrach. lh = 651.512; - Odległość środka ciężkości pojazdu od przedniej osi w milimetrach. MuR = 2.3; - Współczynnik tarcia hamulca. drV = 428; - Średnica tarczy hamulcowej przedniej w milimetrach. drH = 428; - Średnica tarczy hamulcowej tylnej w milimetrach. v = 100; - Prędkość pojazdu w km/h. dKv = 25; - Średnica tłoczka cylindra hamulcowego przedniego w milimetrach. dKh = 25; - Średnica tłoczka cylindra hamulcowego tylnego w milimetrach. diV = 199.742; - Średnica wewnętrzna tarczy hamulcowej przedniej w milimetrach. daV = 148.742; - Średnica zewnętrzna tarczy hamulcowej przedniej w milimetrach. diH = 147; - Średnica wewnętrzna tarczy hamulcowej tylnej w milimetrach. daH = 200; - Średnica zewnętrzna tarczy hamulcowej tylnej w milimetrach. MuBelag = 0.6; - Współczynnik tarcia klocków hamulcowych z tarczą. X = H / l; - Współczynnik dynamicznego rozkładu masy pojazdu.

  1. Funkcje z poszczególnymi zmiennymi oraz ich działanie.

Gesamtgewichtskraft(g, M) - Oblicza siłę ciężkości całego pojazdu.

MasseAchse(FG, proz) - Oblicza masę na osi.

Achslast(g, m) - Oblicza siłę nacisku na oś.

AchslastVorneDynamisch(FG, l, lh, Z, H) - Oblicza dynamiczne obciążenie osi przedniej.

AchslastHintenDynamisch(FG, l, lv, Z, H) - Oblicza dynamiczne obciążenie osi tylnej.

Bremskraft(FGDyn, MuR) - Oblicza siłę hamowania.

Bremsmoment(FBDyn, dr) - Oblicza moment hamowania.

AufGewichtskraftBezogeneDynBremskraftVorne(Z, H, X) - Oblicza dynamiczną siłę hamowania związana z obciążeniem osi przedniej.

AufGewichtskraftBezogeneDynBremskraftHinten(Z, H, X) - Oblicza dynamiczną siłę hamowania związana z obciążeniem osi tylnej.

VonDerBremseAufzunehmendeLeistung(M, MuR, g, v) - Oblicza moc, która musi być absorbowana przez hamulce.

KolbenflaecheVorne(dK) - Oblicza powierzchnię tłoczka cylindra hamulcowego przedniego.

KolbenflaecheHinten(dK) - Oblicza powierzchnię tłoczka cylindra hamulcowego tylnego.

BremszylinderFlaeche(dZ) - Oblicza powierzchnię cylindra hamulcowego.

EffektiverReibradius(di, da) - Oblicza efektywny promień tarczy hamulcowej.

Spannkraft(MB, MuBelag, rm) - Oblicza siłę nacisku na tarczę hamulcową.

Bremsdruck(FSP, AK) - Oblicza ciśnienie hamowania.

BetaetigungskraftBremszylinder(bremsdruck, AZ) - Oblicza siłę działającą na cylindry hamulcowe.

15 - Presety

Folder Presets zawiera pliki z przykładowymi wartościami technicznymi bolidu, jak również środowiskowymi np. temperatura i ciśnienie powietrza. Poniżej zostały opisane poszczególne zmienne. Pliki: TY19_HighDownforce.mat, TY19_LowDownforce.mat, TY19_MedDownforce.mat, TY19_NoDownforce.mat, TY20_HighDownforce.mat, TY20_LowDownforce.mat, TY20_MedDownforce.mat, TY20_NoDownforce.mat, TY22_HighDownforce.mat, TY22_LowDownforce.mat, TY22_MedDownforce.mat, TY22_NoDownforce.mat, loadSetup.m

Definicje zmiennych

Zmienna Definicja
m_ges masa pojazdu
h_cog wysokosc srodka ciezkosci
x_cog srodek masy w osi X
x_va polozenie przedniej osi
m_driver masa kierowcy
h_cog_driver wysokość środka ciężkości kierowcy
x_cog_driver położenie środka ciężkości kierowcy w osi x
m_ballast dociążenie kierowcy
h_cog_ballast wysokość środka ciężkości dociążenia kierowcy
x_cog_ballast położenie środka ciężkości dociążenia kierowcy
thetaV_X nieuzywane?
thetaV_Y nieuzywane?
thetaV_Z nieuzywane?
wheelbase rozstaw osi
track nieuzywane?
J_Tire nieuzywane?
p_Tire cisnienie opon
LMUX Longitudinal scaling factor
LMUY Lateral scaling factor
k_R uzyte: FR = k_R*FWZges; % [N] Rolling resistance
FB wartosc startowa symulacji
camber pochylenie kół
m_ph rozlozenie masy
ptype zmienna binarna uzywana jako warunek
p_max maksymalna moc silnika
n_max maksymalne obroty silnika
drivertrain_eff sprawnosc ukladu napedowego
invertor_eff sprawnosc falownika
z_chaindriver rozmiar zebatki po stronie kol
z_sprocket rozmiar zebatki po stronie silnika
trq_multiplier nieuzywane?
engine_param macierz parametrów silnika
num_motors liczba silnikow
gearbox zmienna do okreslenie czy jest wiecej niz jeden bieg
i_P cos z przelozeniem?
i_param macierz przełożeń dla kolejnych biegów
n_shift obroty silnika przy ktorych nastepuje zmiana biegu na wyzszy
n_downshift obroty silnika przy ktorych nastepuje zmiana biegu na nizszy
t_shift czas zmiany biegu
c_w wspolczynnik oporu powietrza
c_l wspolczynnik oporu powietrza
A powierzchnia przekroju bolidu???
downforce_data nieuzywane?
downforce_multiplier mnożnik sily dociskowej?
aero_pv uzyte: dFWZrl_aero = Faero/2*aero_ph; % [N] Aerodynamic force on rear left wheel
DRS czy DRS jest dostepny/wlaczony
c_d_DRS wspolczynnik oporu powietrza z wlaczonym drs
c_l_DRS wspolczynnik oporu powietrza z wlaczonym drs
ConstantDownforce stala sily docisku
DRS_Radius promien DRS?
V_i napiecie baterii
Energy_i nieuzywane?
nZellen_Parallel liczba celi baterii polaczonych rownolegle?
nZellen_Reihe liczba celi baterii polaczonych szeregowo?
capacity_cell pojemnosc celi baterii
t_L temperatura powietrza
p_L cisnienie atmosferyczne
R_L stala gazowa dla powietrza
g przyspieszenie ziemskie

Porównanie wartości w poszczególnych plikach

W przygotowaniu

Ładowanie setupów do symulacji

Plik loadSetup.m w katalogu głównym odpowiada za załadowanie wszystkich tych parametrów do symulacji.

Prototyp funkcji

function loadSetup(app, file)

Parametry

  • app: Obiekt aplikacji, do którego ładowane są parametry.
  • file: Ścieżka do pliku konfiguracyjnego .mat.

Działanie

Funkcja ładowania próbuje wczytać dane z pliku .mat i przypisuje je do właściwości obiektu app. Parametry są podzielone na kategorie takie jak szkielet, zawieszenie, napęd, aerodynamika, akumulator i warunki środowiskowe. Dodatkowo aplikacja sprawdza stan skrzyni biegów i zeruje jej przełożenia.

if app.gearbox
            setup.i_param = app.i_param;
            setup.n_shift = app.n_shift;
            setup.n_downshift = app.n_downshift;
            setup.t_shift = app.t_shift;
        else
            setup.i_param = [0 0];
            setup.n_shift = 0;
            setup.n_downshift = 0;
            setup.t_shift = 0;
        end

Obsługa błędów

W razie wystąpienia błędu podczas ładowania, funkcja zapisuje komunikat o błędzie do pliku dziennika.

Zastosowanie

Funkcja jest wywoływana z obiektem aplikacji i ścieżką do pliku konfiguracyjnego, inicjując aplikację z załadowanymi ustawieniami pojazdu.

16 - Wykresy sił na oponach

Opis skryptów badających siły przenoszone przez opony w zależności od poślizgu korzystając z paretrów opon Continental FormulaStudent 205 407 R13 65kPa

Wstęp

Realizacja wykresów opisujących zachowanie opon odbywa się za pomocą plików Conti_Tire_Plots_Lateral.m i Conti_Tire_Plots_Longitudinal.m opisujących siły w kierunku poprzedznym i wzdłużnym. Obydwa skrypty są bardzo podobne, jednakże znajdują się tam różnice w danych charakterystyczne dla opisywanego kierunku sił.

Analiza w kierunku poprzecznym

Zmienne:

Rys.1 Zmienne dla pliku  &hellip;Lateral.m

Rys.1 Zmienne dla pliku …Lateral.m

  • ALPHA: Jest to kąt poślizgu bocznego w stopniach. Kąt poślizgu bocznego jest to kąt między kierunkiem jazdy a kierunkiem, w którym opona jest skierowana.
  • GAMMA: Jest to kąt pochylenia w stopniach. Kąt pochylenia jest to kąt, pod którym opona jest pochylona względem pionu.
  • KAPPA: Jest to poślizg opony. Poślizg opony jest to różnica między prędkością obrotową opony a prędkością pojazdu.
  • FileNameLocation: Jest to ścieżka do pliku Tir. Plik Tir zawiera wszystkie parametry opony, które są potrzebne do modelowania jej zachowania.
  • TIRparam: Jest to struktura zawierająca parametry opony. Parametry te są wczytywane z pliku Tir.
  • Fz_r: Jest to obciążenie koła z tyłu w pozycji statycznej. Obciążenie to jest mierzone w niutonach.
  • Fy: Jest to przenoszona siła koła. Siła ta jest obliczana na podstawie parametrów opony i warunków jazdy.

Funkcje:

Rys.2 Funkcje dla pliku  &hellip;Lateral.m

Rys.2 Funkcje dla pliku …Lateral.m

  • loadTIR: Jest to funkcja, która wczytuje plik Tir do struktury. Plik Tir zawiera wszystkie parametry opony, które są potrzebne do modelowania jej zachowania.
  • MF52_Fy_cs: Jest to funkcja, która oblicza przenoszoną siłę koła. Funkcja ta oblicza siłę na podstawie parametrów opony i warunków jazdy.

Analiza w kierunku wzdłużnym

Funkcje i zmienne niewymienione poniżej są analogiczne jak opisane powyżej.

Zmienne:

Rys.3 Zmienne dla pliku  &hellip;Longitudinal.m

Rys.3 Zmienne dla pliku …Longitudinal.m

  • ALPHA: Kąt poślizgu bocznego w stopniach.
  • GAMMA: Kąt pochylenia w stopniach.
  • KAPPA: Poślizg opony.
  • FileNameLocation: Ścieżka do pliku Tir.
  • TIRparam: Struktura zawierająca parametry opony.
  • Fz_r: Obciążenie koła z tyłu w pozycji statycznej.
  • Fy / Fx: Przenoszona siła koła (boczna / podłużna).

Funkcje:

Rys.4 Funkcje dla pliku  &hellip;Longitudinal.m

Rys.4 Funkcje dla pliku …Longitudinal.m

  • loadTIR: Wczytuje plik Tir do struktury.
  • MF52_Fy_cs / MF52_Fx_cs: Oblicza przenoszoną siłę koła (boczną / podłużną).

Wykresy:

  • Pierwszy skrypt generuje wykres siły bocznej w zależności od kąta poślizgu bocznego i poślizgu podłużnego.
    Rys.5 Wykres rysowany przez plik &hellip;Longitudinal.m

    Rys.5 Wykres rysowany przez plik …Longitudinal.m

  • Drugi skrypt generuje wykres siły podłużnej w zależności od poślizgu opony i kąta poślizgu bocznego.
    Rys.6 Wykres rysowany przez plik   &hellip;Longitudinal.m

    Rys.6 Wykres rysowany przez plik …Longitudinal.m

Problemy:

Ze względu na brak kompletnych informacji na temat wielu zmiennych z pliku .tir opisującego parametry badanej opony na ten moment nie wiemy, jak zmieniane w obydwu skryptach parametry wpływają na wynik symulacji.

17 - catstruct.m

catstruct.m - łączenie struktur w jedną

Wstęp

Ta funkcja z pliku catstruct.m służy w skrócie do łączenia wielu struktur w jedną.

Działanie funkcji

narginchk() jest wykorzystwane do sprawdzenia czy ilość argumentów przesłanych do aktualnie wykonującej się funkcji mieści się w zadanym zakresie. Jeśli tak jest to nargin nic nie robi, natomiast jeśli liczba tych argumentów wyjdzie poza któryś z limitów to nargin wyrzuci błąd. W naszym przypadku ilość argumentów przesłanych do funkcji musi wynosić co najmniej 1. Zaraz potem do N jest przypisane nargin, które to zwraca ich ilość.

rys. 1

rys. 1

  1. isstruct(A) zwraca prawdę jeśli A jest strukturą lub fałsz jeśli A strukturą nie jest. varargin zwraca ciąg 1xN, gdzie N to ilość inputów przesłanych do wykonywanej funkcji, lub zwraca pusty ciąg jeśli nie przesłano żadnego. Więc wraz z negacją ~ sprawdzamy tak naprawdę czy przesłano jakieś argumenty (o ile dobrze rozumiem, bo nigdzie znalazłem czegoś o varargin{end}, który przechowuje wartość ostaniej komórki ciągu). Jeśli nie to a, natomiast jeśli tak to b:
    a - przejście do warunku 2.
    b - sorted = 0

  2. isequal porównuje dwa lub więcej wartości/ciągi i jeśli są sobie równe to zwraca true lub fałsz jeżeli równe nie są. Tak więc sprawdzamy czy varargin{end} ma wartość ‘sorted’. Jeśli tak to a, jeśli nie to b:
    a - narginchk() opisany jest wyżej. Podany zakres jest od 2 do infinity, a więc muszą być conajmniej dwa inputy przesłane do funkcji, aby narginchk nie wyrzucił błędu. Reszta jak na załączonym obrazku rys. 1., gdzie N to ilość tych inputów
    b - wyrzucony zostaje błąd o podanej treści

sz0 = [] będzie później wykorzystywany do sprawdzenia czy wszystkie inputy mają taki sam rozmiar

NonEmptyInputs = false(N,1) oraz NonEmptyInputsN = 0 użyte będzie później do oceny stanu inputów

FN = cell(N,1) oraz VAL = cell(N,1) wykorzystywane do zbierania nazw oraz inputów

18 - Logi

writeToLogfile(text, Debug, textAreaHandle) - Opisane tu jest w jaki sposób zapisywane i wypisywane są logi

Wstęp

Opisane tu jest w jaki sposób zapisywane i wypisywane są logi.
Poniższy obrazek prezentuje cały kod pliku writeToLogfile.m

Działanie funkcji writeToLogfile(text, Debug, textAreaHandle)

Najpierw za pomocą funkcji fopen(filename,permission) otwierany jest plik o nazwie ErrorLog.txt podanej w pierwszym parametrze, a jako drugi parametr podawany jest rodzaj dostępu do pliku - a - oznaczający otworzenie lub utworzenie pliku do zapisu oraz dodanie tekstu na koniec pliku.

  1. Pierwsza funkcja warunkowa sprawdza czy plik został poprawnie otworzony. Jeśli fid jest równy -1, co oznacza, że funkcja fopen nie mogła otworzyć pliku, to fukncja error(msg) wyrzuca i wyświetla błąd o treści zdefiniowanej w parametrze msg

Funkcja fprintf(fileID,formatSpec,A1,...,An) i jej parametry:

parametr zmienna co przechowuje
fileID fid identyfikator wcześniej otworzonego pliku
formatSpec ‘%s: %s\n’ format tekstu - “A1: A2 nowa linia
A1 datestr(now, 0) aktualny czas w formacie ‘dd-mmm-yyyy HH:MM:SS’
A2 text tekst, który chcemy zapisać w pliku; parametr text funkcji writeToLogfile

Funkcja fclose zamyka plik.

  1. Druga funkcja warunkowa sprawdza czy nargin (ilość parametrów podanych przy wywołaniu funkcji) jest równe 3 oraz Debug (parametr funkcji writeToLogfile) jest true. Jeśli oba te warunki zostaną spełnione to w elemencie GUI textArea (ten w zakładce How-to) zostanie dopisana linia “loaded Track!" na jego końcu.

19 - Renderowanie Trasy

renderSelectedTrack.m - renderowanie wybranej trasy

Wstęp

renderSelectedTrack.m - renderowanie wybranej trasy

Tracks.Data

Tracks.Data to, jak widać na załączonym obrazku, matryca wypełniona pewnymi wartościami. Na niej opiera się cały plik renderSelectedTrack.m

Kolumna 1 - nazwa trasy
Kolumna 2 - długość trasy
Kolumna 3 - ???
Kolumna 4 - wartość określająca czy na trasie jest podział dyscyplin
Kolumna 5 - liczba okrążeń
Kolumna 6 - prędkość startowa
Kolumna 7 - nazwa pliku trasy

Deklaracja zmiennych

Pobierana jest nazwa pliku z nazwą toru z listy rozwijanej DropDown (tej z zakładki Simulation Setup, z sekcji Scenario, podpisanej jako Track).

Za pomocą funkcji load(filename,variables) ładowana jest wybrana trasa z podaną nazwą trasy.

Do x_Track_preview i y_Track_preview przypisywane są odpowiednio koordynaty x i y trasy przyjmując za jednostkę metry.

s_preview to przebieg długości trasy.

TrackName to nazwa trasy pobrana z wcześniej wspomnianej listy TrackDropDown (zakładka Simulation Setup => sekcja Scenario => Track).

Zmienna Co przechowuje
x_Track_preview koordynaty x trasy w [m]
y_Track_preview koordynaty y trasy w [m]
s_preview przebieg długości trasy
TrackName nazwa trasy pobrana z wcześniej wspomnianej listy TrackDropDown (zakładka Simulation Setup => sekcja Scenario => Track)
app.StartingSpeed prędkość startowa dla danej trasy, konwertując ją ze stringa na zmienną typu double
app.numOfLaps ilość okrążeń dla danej trasy, konwertując ją ze stringa na zmienną typu double

Funkcje warunkowe

  1. W pierwszym warunku po przekonwertowaniu zmiennej typu string na double sprawdzane jest czy na wybranej trasie są w ogóle dyscypliny. Jeśli tak to app.DisciplineDropDown zostaje włączony. W przeciwnym wypadku zostaje wyłączony.

  2. Następnie ustawiany jest motyw kolorystyczny w zależności czy zaznaczony został odpowiedni checkbox - app.DarkModeCheckBox.

  3. dopisać

  4. Czwarta funkcja warunkowa zawsze się wykona bo tak zostało zapisane w kodzie (DrawApexes ustawione na 1 czyli na true - ergo - warunek zawsze prawdziwy).
    Funkcja hold z drugim parametrem “on” ustawia podany w pierszym parametrze wykres na niepoddający się wymazywaniu istniejących linii przy rysowaniu nowych.
    Zmienna ApexIndizes to kurwa co to nwm pózniej dopisze bo psycha siada Funkcja scatter , gdzie:

    Parametr Czym jest
    app.UIAxes2 docelowy element
    x_Track_preview(ApexIndizes) objaśniona wcześniej zmienna
    y_Track_preview(ApexIndizes) objaśniona wcześniej zmienna
    20 pole powierzchni znaczników (w jednostce points)
    ‘r’ kolor - red (czerwony)
    ‘filled’ opcja do wypełnienia środka markerów

Przez app.UIAxes2.reset resetowany jest graficzny elementu app.UIAxes2.
Funkcja title(target,titletext,Name,Value) zatytułowuje wykres, gdzie:

Parametr Czym jest
target element docelowy (tutaj app.UIAzes2)
titletext nazwa toru podawana przez zmienną TrackName
Name nazwa atrybutu (tutaj rozmiar czcionki)
Value wartość atrybutu

Oraz ustawiana jest grubość jego linii i kolory zależne od wybranego motywu.

app.LengthLabel.Text = "Track Length: " + max(s_preview) + " m" ustawia tekst labela w kącie wykresu na pokazany tutaj tekst, gdzie max(s_preview) to maksymalna wartość z ciągu s_preview. W praktyce przedstawia on długość trasy.

20 - TirFiles

updateTirFiles.m - Wypełnienie wybranej listy rozwijanej dropDown plikami .tir

Wstęp

Funkcja zapełnia podany w parametrze dropDown element GUI typu dropDown listą plików o rozszerzeniu .tir z podanej lokalizacji i jej podfolderów.

Nazwa zmiennej Co przechowuje
folderPath ścieżka do plików .tir
fileList lista wszystkich plików o .tir w lokalizacji folderPath i jej podfolderach
fileNames lista nazw wszystkich plików z fileList
dropDown.Items itemy elementu dropDown podanego przy wywołaniu funkcji updateTirFiles wypełnione listą fileNames

W praktyce funkcja ta jest wykorzystywana jeden raz w pliku Suspension.mlapp i dotyczy tylko elementu app.TIRFileDropDown, w zakładce General, podpisanego jako TIR File.