graw01
Aplikacja GRAWITACJA służy do przeprowadzania eksperymentów fizycznych na komputerze. Pozwala symulować ruch obiektów w polu grawitacyjnym oraz loty kosmiczne. Projekt powstał jako praca dyplomowa z fizyki, którą studiowałem na Wydziale Fizyki i Informatyki Stosowanej  na krakowskiej AGH. 1500 wierszy kodu to niewiele ale stopień skomplikowania bardzo duży. Program kosztował dwa miesiące wakacji, po 10 godzin dziennie!

Inne uwagi:

  • Program napisany przy użyciu VB i pracuje w środowisku MS Excela. Ułatwia to obliczenia i pozwala na szybkie modyfikowanie kodu lecz stwarza problemy w obszarze animacji.
  • Program z założenia miał być swoistym rodzajem laboratorium elektronicznym do przeprowadzania eksperymentów i dlatego większą uwagę poświęcono liczbom.
  • Możliwość symulowania czterech obiektów kosmicznych i rakiety – to raczej niewiele, ale celem miało być zasymulowanie lotu na Marsa.
  • Tory ruchu planet wyliczane są z równań ruchu, które wywodzą się wprost z prawa powszechnego ciążenia Newtona.
  • Do wyliczania współrzędnych na płaszczyźnie wykorzystano algorytmy: Eulera, Verleta i Runge-Kutta.
  • Siła ciągu rakiety uwzględnia zmianę jej masy, co jest zgodne z wzorami wyprowadzonymi przez Konstantina Ciołkowskiego.
  • W trakcie lotu możemy obracać rakietą wokół osi oraz sterować siłą ciągu.
  • Wszelkie zmiany mogą być dokonywane w trakcie symulacji.
  • 1500 wierszy kodu źródłowego, nie jest może liczbą imponującą lecz otwarta konstrukcja umożliwia różnorodne zastosowania.

Wszelkie szczegółowe informacje zostały opisane dokładnie w pracy dyplomowej, której fragmenty znajdują się w poniższych załącznikach:

mgr inż. Wacław Libront


Fragment kodu źródłowego:

'RAKIETA *********************************************************************
'wyliczanie chwilowego przyspieszenia pochodzącego od siły ciągu rakiety
'siła ciągu zawsze działa zgodnie z kierunkiem pochylenia rakiety
'który może być inny niż kierunek lotu wyliczony z grawitacji
Sub AA_rakieta()
Dim ax, ay, vx, vy, a, v, vx1, vy1, ac, acx, acy As Double
On Error GoTo błąd
 
  'wartości chwilowe przyspieszeń i prędkości rakiety
  ax = AA(0, 1)
  ay = AA(0, 2)
  vx = VV(0, 1)
  vy = VV(0, 2)
  'wypadkowe
  a = (ax ^ 2 + ay ^ 2) ^ (1 / 2)
  v = (vx ^ 2 + vy ^ 2) ^ (1 / 2)
  
  'przyspieszenia po osiach rakiety wyliczamy z Talesa
  'proporcjonalne do wektorów prędkości rakiety
  'przyspieszenie zgodne ze zwrotem przepustnicy rakiety
  'i uwzględniamy obrót automatyczny
  'kąt = KĄT_GRANICA(KĄT_RAKIETY + KĄT_SKOKU_OBROTU)
  'kąt = KĄT_GRANICA(KĄT_RAKIETY + KIERUNEK_OBROTU)
  kąt = KĄT_RAKIETY
  'wyliczone kierunki prędkości
  vx1 = WERSOR_X(kąt)
  vy1 = WERSOR_Y(kąt)
  'nowe prędkości składowe po zmianie kąta
  'po co to było liczone?
  'vx = v * Abs(Cos(kąt * PI / 180)) * vx1
  'vy = v * Abs(Sin(kąt * PI / 180)) * vy1
  
  'przyspieszenie uwzględnia masę chwilową rakiety - Ciołkowski
  'nie przeliczamy na inne jednostki, bo za szybko
  'jest w N a my chcemy na kilogramy?
  ac = SIŁA_CIĄGU / MASA_RAKIETY
  'przyspieszenie ciągu działa w tą stronę, w którą jest zwrócona rakieta
  acx = ac * Abs(Cos(kąt * PI / 180)) * vx1
  acy = ac * Abs(Sin(kąt * PI / 180)) * vy1
  'nowe składowe przyspieszeń rakiety
  'po uwzględnieniu siły ciągu i kąta odchylenia
  AA(0, 1) = AA(0, 1) + acx
  AA(0, 2) = AA(0, 2) + acy
błąd:
End Sub

'obliczenie ilości paliwa i masy rakiety, gdy pracuje silnik
'i zaznaczono, że ma pobierać paliwo
Sub PALIWO_oblicz()
  If PALIWO_POBIERAJ And SILNIK_PRACUJE Then
    If MASA_PALIWA_AKT <= 0 Then
      PALIWO_POBIERAJ = False
      SILNIK_onoff 'wyłączenie silnika
    Else
      'powinniśmy uwzględniać skok czasu, ale bardzo szybko by spalało
      'nie uwzględniamy czasu spalania dlatego bez * CZAS_SKOKU
      MASA_PALIWA_AKT = MASA_PALIWA_AKT - SZYBKOŚĆ_SPALANIA * SKOK_CZASU
      MASA_RAKIETY = MASA_RAKIETY - SZYBKOŚĆ_SPALANIA * SKOK_CZASU
      MA(0) = MASA_RAKIETY 'zmniejszyć masę rakiety do obliczeń
    End If
    PALIWO_ustaw
  End If
End Sub

'obliczanie kątów, położenia i kierunku rakiety
'gdy pracuje silnik
'i próby automatycznego wychodzenia z korkociągu,
'gdy prędkość spada do zera a przeciwny zwrot
Sub KĄTY_oblicz()
  Dim vx, vy, vx1, vy1 As Variant
  
  'położenie rakiety
  vx = Sheets("GRAWITACJA").Range("E10")
  vy = Sheets("GRAWITACJA").Range("F10")
  'położenie planety środkowej
  vx1 = Sheets("GRAWITACJA").Cells(10 + WYKRES_ŚRODEK_NR, 5)
  vy1 = Sheets("GRAWITACJA").Cells(10 + WYKRES_ŚRODEK_NR, 6)
  'nowe położenie rakiety
  vx = vx - vx1
  vy = vy - vy1
  'v = (vx ^ 2 + vy ^ 2) ^ (1 / 2)
  'wyliczenie kąta lotu
  KĄT_LOTU = KĄT_oblicz(vx, vy)
  'jeśli niema kompensacji to nie ma problemów z korkociągami
  'bo sobie sam oblicza i reguluje
  'tu wstawić czy kompensacja obrotów rakiety
  If KOMPENSACJA Then
    'prawidłowa reakcja na korkociąg gdy silnik pracuje
    If Not (SILNIK_PRACUJE) Then
      KĄT_RAKIETY = KĄT_GRANICA(KĄT_LOTU + ODCHYLENIE)
    Else
      ODCHYLENIE = KĄT_GRANICA(KĄT_RAKIETY - KĄT_LOTU)
    End If
  End If
  'obraca się zgodnie z szybkością zmian kąta lotu
  If OBRACAĆ = True Then
    KĄT_RAKIETY = KĄT_GRANICA(KĄT_RAKIETY + KĄT_SKOKU_OBROTU * KIERUNEK_OBROTU)
    ODCHYLENIE = KĄT_GRANICA(KĄT_RAKIETY - KĄT_LOTU)
  Else
  End If
End Sub

'ALGORYTMY *******************************************************************

'obliczanie odległości pomiędzy obiektami
Function R_oblicz(i, j As Variant) As Double
  r2 = (XY(i, 1) - XY(j, 1)) ^ 2 + (XY(i, 2) - XY(j, 2)) ^ 2
  R_oblicz = r2 ^ (1 / 2)
End Function
'obliczanie przyspieszeń z wzoru na grawitację
'a=-G*M/R^2
Sub A_oblicz()
On Error GoTo błąd
Dim R, R3 As Double

  For i = 0 To WYM
    AA(i, 1) = 0
    AA(i, 2) = 0
    For j = 0 To WYM
    'sam ze sobą nie oddziaływuje i sprawdzamy tylko obiekty z masą >0
    If i <> j And MA(i) > 0 And MA(j) > 0 Then
      'odległości pomiędzy planetami
      R = R_oblicz(i, j)
      R3 = R ^ 3
      'suma wszystkich składowych przyspieszeń daje przyspieszenie wypadkowe
      For k = 1 To 2
        'sumujemy przyspieszenie chwilowe
        AA(i, k) = AA(i, k) + -GRAW * MA(j) * (XY(i, k) - XY(j, k)) / R3
      Next k
    End If
    Next j
  Next i
  Exit Sub
błąd:
  'gdy błąd, bo np promień równy 0 to omijamy i realizujemy dalej
  Resume Next
End Sub

'RUNGE-KUTTY 4
'zapamiętaj początkowe
Sub XV0_oblicz()
  For i = 0 To WYM
    For k = 1 To 2
      XY0(i, k) = XY(i, k)
      VV0(i, k) = VV(i, k)
    Next k
  Next i
End Sub
'nowe prędkości z początkowym V i obliczonym K
Sub KXV1_oblicz()
  For i = 0 To WYM
    For k = 1 To 2
      VV1(i, k) = AA(i, k) * SKOK_CZASU
      XY(i, k) = XY0(i, k) + VV1(i, k) * SKOK_CZASU / 2
    Next k
  Next i
End Sub
Sub KXV2_oblicz()
  For i = 0 To WYM
    For k = 1 To 2
      VV2(i, k) = AA(i, k) * SKOK_CZASU
      XY(i, k) = XY0(i, k) + VV2(i, k) * SKOK_CZASU / 2
    Next k
  Next i
End Sub
Sub KXV3_oblicz()
  For i = 0 To WYM
    For k = 1 To 2
      VV3(i, k) = AA(i, k) * SKOK_CZASU
      XY(i, k) = XY0(i, k) + VV3(i, k) * SKOK_CZASU
    Next k
  Next i
End Sub
Sub K4_oblicz()
  For i = 0 To WYM
    For k = 1 To 2
      VV4(i, k) = AA(i, k) * SKOK_CZASU
    Next k
  Next i
End Sub
'prędkość w metodzie RK
Sub VXRK_oblicz()
  For i = 0 To WYM
    For k = 1 To 2
      VV(i, k) = VV0(i, k) + _
                (VV1(i, k) + 2 * VV2(i, k) + 2 * VV3(i, k) + VV4(i, k)) / 6
      XY(i, k) = XY0(i, k) + VV(i, k) * SKOK_CZASU
    Next k
  Next i
End Sub
'METODA Runge-Kutty4
Sub RK4()
    'zapamiętaj poprzednie V i X
    XV0_oblicz
    '1 krok RK
    A_oblicz
    If (SILNIK_PRACUJE) And (SKOK_CZASU > 0) Then AA_rakieta
    KXV1_oblicz
    '2 krok RK
    A_oblicz
    If (SILNIK_PRACUJE) And (SKOK_CZASU > 0) Then AA_rakieta
    KXV2_oblicz
    '3 krok RK
    A_oblicz
    If (SILNIK_PRACUJE) And (SKOK_CZASU > 0) Then AA_rakieta
    KXV3_oblicz
    '4 krok RK
    A_oblicz
    'uwzględniamy silnik
    If (SILNIK_PRACUJE) And (SKOK_CZASU > 0) Then AA_rakieta
    K4_oblicz 'K4
    'a teraz obliczenie V i X jako 1/6
    VXRK_oblicz 'do tablic VV ze startowego V i 1/6(K1+2K2+2K3+k4)
                 'do tablic XY z przyrostem czasu dt
End Sub