Różnice między wybraną wersją a wersją aktualną.
Poprzednia rewizja po obu stronachPoprzednia wersjaNowa wersja | Poprzednia wersja | ||
narzedzia:apple_sim_py [2025/05/07 11:56] – administrator | narzedzia:apple_sim_py [2025/05/16 18:48] (aktualna) – administrator | ||
---|---|---|---|
Linia 1: | Linia 1: | ||
- | = Symulacja Masy Sprężystej = | + | Skrypt do pobrania: |
+ | {{ : | ||
- | Ten artykuł opisuje działanie skryptu w Pythonie wykonującego symulację ruchu kulki pod wpływem siły grawitacji, wiatru oraz oddziaływania sprężysto‐tarciowego. Skrypt wykorzystuje biblioteki NumPy, Matplotlib oraz Tkinter do wizualizacji i interakcji. | + | {{ : |
- | == Spis treści | + | ====== PY: Symulacja Masy Sprężystej ====== |
- | # Opis ogólny | + | |
- | # Stałe i parametry | + | |
- | # Model fizyczny | + | |
- | # Inicjalizacja i reset symulacji | + | |
- | # Interfejs użytkownika (Tkinter) | + | |
- | # Rysowanie i animacja (Matplotlib) | + | |
- | # Funkcja animate() | + | |
- | # Zakończenie i pętla główna | + | |
- | == 1. Opis ogólny == | + | Ten artykuł wyjaśnia, jak działa skrypt symulujący ruch masy sprężystej pod wpływem grawitacji, |
- | Skrypt emuluje ruch kulki („jabłuszka”) o masie $m$ poruszającej się w układzie dwuwymiarowym. Użytkownik może regulować siłę wiatru oraz współczynnik sprężystości odbicia (restitution), a także obserwować: | + | |
- | * Tor ruchu | + | |
- | * Wektory sił (grawitacja, wiatr, prędkość, | + | |
- | * Wykres prędkości | + | |
- | * Reprezentację wektorów w układzie polarnym | + | |
- | == 2. Stałe i parametry == | ||
- | < | ||
- | # Stałe fizyczne | ||
- | g = 9.81 # przyspieszenie grawitacyjne [m/s²] | ||
- | m = 0.15 # masa kulki [kg] | ||
- | e = 0.7 # współczynnik sprężystości (restitution) | ||
- | μ = 0.5 # współczynnik tarcia | ||
- | dt = 0.05 # krok czasowy [s] | ||
- | </ | ||
- | Parametry wykresów: | + | ---- |
- | < | + | |
- | x_min, x_max = -20, 20 # granice osi X [m] | + | |
- | y_min, y_max = 0, 40 # granice osi Y [m] | + | |
- | velocity_scale = 0.2 # skala strzałki prędkości | + | |
- | </ | + | |
- | == 3. Model fizyczny | + | ===== ⚙️ Stałe fizyczne i warunki początkowe |
- | === 3.1 Przyspieszenie | + | |
- | Przyspieszenie kulki w kierunku poziomym i pionowym wyznaczamy z II zasady dynamiki Newtona: | + | |
- | < | + | |
- | a_x = \frac{F_\text{wiatr}}{m}, | + | |
- | a_y = -g | + | |
- | </ | + | |
- | === 3.2 Równania kinetyczne === | + | <code python> |
- | Pozycję i prędkość w kolejnych krokach obliczamy ze wzorów: | + | g = 9.81 # Przyspieszenie ziemskie |
- | <math> | + | m = 0.15 # Masa piłki |
- | v(t+\Delta t) = v(t) + a \,\Delta t | + | restitution = 0.7 # Współczynnik sprężystości |
- | </ | + | friction_coefficient |
- | < | + | </code> |
- | x(t+\Delta t) = x(t) + v(t)\, | + | |
- | </math> | + | |
- | === 3.3 Odbicie od podłoża === | + | Używamy podstawowych stałych z fizyki: |
- | Gdy kulka dotyka podłoża ($y \le y_\min$), następuje odbicie: | + | |
- | < | + | |
- | v_y' = -\,e\, v_y | + | |
- | </ | + | |
- | gdzie $e$ to współczynnik sprężystości. Jeżeli prędkość pionowa jest mała ($|v_y|< | + | |
- | < | + | * Siła grawitacji: ( F_g = m g ) |
- | F_\text{tarcie} | + | * Odbicie piłki od ziemi następuje z redukcją |
- | </ | + | |
- | które zmniejsza | + | |
- | < | + | |
- | v_x \;\to\; v_x \;-\;\mathrm{sign}(v_x)\, | + | |
- | </ | + | |
- | == 4. Inicjalizacja i reset symulacji == | ||
- | Funkcja `reset_simulation()` przywraca początki symulacji: | ||
- | < | ||
- | def reset_simulation(): | ||
- | global x, y, vx, vy, trace, sim_time, time_list, speed_list, acc_list | ||
- | x, y = 0, 30 # początkowa pozycja | ||
- | vx, vy = 0, 0 # początkowe prędkości | ||
- | trace = [] # czyszczenie śladu toru | ||
- | sim_time = 0.0 | ||
- | time_list = [] | ||
- | speed_list = [] | ||
- | acc_list = [] | ||
- | </ | ||
- | == 5. Interfejs użytkownika (Tkinter) == | + | ---- |
- | Symulacja działa w oknie Tkinter, w którym mamy: | + | |
- | * Suwak do zmiany siły wiatru (`wind_slider`) | + | |
- | * Suwak do zmiany współczynnika sprężystości (`spring_slider`) | + | |
- | * Przycisk „Restart” – ponowne wywołanie `reset_simulation()` | + | |
- | * Pole tekstowe (`info_text`) wyświetlające bieżące wartości czasu, pozycji, prędkości, | + | |
- | == 6. Rysowanie i animacja (Matplotlib) | + | ===== 🧮 Obliczenia |
- | Tworzymy trzy wykresy: | + | |
- | # Główny wykres 2D: pozycja kulki i wektory | + | |
- | # Wykres czasowy prędkości | + | |
- | # Wykres polarny wektorów | + | |
- | Przykład inicjalizacji głównego wykresu: | + | ==== Kod: ==== |
- | < | + | |
- | fig, ax = plt.subplots(figsize=(8, 6)) | + | |
- | ax.set_xlim(x_min, | + | |
- | ax.set_xlabel(" | + | |
- | apple = patches.Circle((0, | + | |
- | ax.add_patch(apple) | + | |
- | trace_line, | + | |
- | </ | + | |
- | == 7. Funkcja animate() == | + | <code python> |
- | To serce animacji wywoływane przez `FuncAnimation`. W kolejnych krokach: | + | Fw = wind_force |
- | <syntaxhighlight lang=" | + | ax_acc |
- | def animate(i): | + | ay_acc |
- | global x, y, vx, vy, sim_time | + | </code> |
- | # 1) Obliczanie przyspieszeń | + | Zgodnie z II zasadą dynamiki Newtona: |
- | ax_acc = wind_force / m | + | |
- | ay_acc = -g | + | |
- | # 2) Aktualizacja prędkości | + | * Siła wiatru generuje przyspieszenie poziome: $$ a_x = \frac{F_{\text{wiatr}}}{m} $$ |
- | vx += ax_acc | + | * Przyspieszenie pionowe jest równe przyspieszeniu ziemskiemu: $$ a_y = -g $$ |
- | vy += ay_acc * dt | + | |
- | # 3) Aktualizacja pozycji | ||
- | x += vx * dt + 0.5 * ax_acc * dt**2 | ||
- | y += vy * dt + 0.5 * ay_acc * dt**2 | ||
- | # 4) Odbicie i tarcie | + | ---- |
- | if y <= y_min: | + | |
- | y = y_min | + | |
- | vy = -vy * restitution | + | |
- | # ... kod tarcia ... | + | |
- | # 5) Aktualizacja obiektu graficznego | + | ===== 🧠 Kinematyka ruchu ===== |
- | apple.set_center((x, | + | |
- | trace.append((x, | + | |
- | trace_line.set_data(*zip(*trace)) | + | |
- | # 6) Rysowanie wektorów na wykresie: | + | <code python> |
- | | + | vx += ax_acc * time_step |
- | wind_vector.remove() | + | vy += ay_acc * time_step |
- | resultant_vector.remove() | + | x += vx * time_step + 0.5 * ax_acc * time_step**2 |
- | g_vector | + | y += vy * time_step + 0.5 * ay_acc * time_step**2 |
- | | + | </ |
- | | + | |
- | # 7) Aktualizacja wykresów prędkości i przyspieszenia | + | Używamy podstawowych równań kinematyki: |
- | sim_time += dt | + | |
- | current_speed = np.hypot(vx, | + | |
- | time_list.append(sim_time); | + | |
- | line_speed.set_data(time_list, | + | |
- | line_acc.set_data(time_list, | + | |
- | ax2.set_xlim(0, | + | |
- | ax2.set_ylim(0, | + | |
- | data_canvas.draw() | + | |
- | # 8) Aktualizacja pola tekstowego | + | $$ |
- | | + | v = v_0 + a \cdot \Delta t \\ |
- | | + | s = s_0 + v \cdot \Delta t + \frac{1}{2} a \cdot \Delta t^2 |
+ | $$ | ||
- | # 9) Wykres polarny | ||
- | polar_ax.clear() | ||
- | draw_polar_arrow(polar_ax, | ||
- | # … pozostałe wektory … | ||
- | polar_canvas.draw() | ||
- | return apple, g_vector, wind_vector, resultant_vector, trace_line, line_speed, line_acc | + | ---- |
- | </syntaxhighlight> | + | |
+ | ===== 🪨 Odbicie od ziemi i tarcie ===== | ||
+ | |||
+ | <code python> | ||
+ | if y <= y_min: | ||
+ | vy = -vy * restitution | ||
+ | if abs(vy) < 0.5: | ||
+ | vx -= \dots \text{(siła tarcia)} | ||
+ | </ | ||
+ | |||
+ | Siła tarcia kinetycznego: | ||
+ | |||
+ | $$ | ||
+ | F_{\text{tarcia}} = \mu \cdot m \cdot g \\ | ||
+ | a_{\text{tarcia}} = \frac{F_{\text{tarcia}}}{m} = \mu \cdot g | ||
+ | $$ | ||
+ | |||
+ | |||
+ | ---- | ||
+ | |||
+ | ===== 📈 Wektory sił i wykresy ===== | ||
+ | |||
+ | Kod rysuje wektory: | ||
+ | |||
+ | * Grawitacji – zawsze w dół | ||
+ | * Wiatru – poziomo | ||
+ | * Prędkości – dynamicznie | ||
+ | |||
+ | <code python> | ||
+ | draw_arrow(x, y, vx * scale, vy * scale, ' | ||
+ | </ | ||
+ | |||
+ | |||
+ | ---- | ||
+ | |||
+ | ===== 🧭 Wektory na wykresie biegunowym ===== | ||
+ | |||
+ | <code python> | ||
+ | draw_polar_arrow(polar_ax, angle, magnitude, color) | ||
+ | </code> | ||
+ | |||
+ | Ten fragment przelicza wartości sił i prędkości do współrzędnych biegunowych. Dzięki temu użytkownik może obserwować ich kierunki i względne wartości. | ||
+ | |||
+ | |||
+ | ---- | ||
+ | |||
+ | ===== 📊 Wykresy prędkości i przyspieszenia ===== | ||
+ | |||
+ | <code python> | ||
+ | current_speed = np.sqrt(vx**2 + vy**2) | ||
+ | net_acc = np.sqrt(ax_acc**2 + ay_acc**2) | ||
+ | </ | ||
+ | |||
+ | Wartości te są dodawane do list i rysowane w czasie rzeczywistym. | ||
+ | |||
+ | |||
+ | ---- | ||
+ | |||
+ | ===== 🧵 Podsumowanie ===== | ||
+ | |||
+ | Ten skrypt to przykład dynamicznej symulacji ruchu w dwuwymiarowym polu sił, uwzględniającej: | ||
+ | |||
+ | * Grawitację | ||
+ | * Wiatr jako siłę zewnętrzną | ||
+ | * Sprężystość przy zderzeniu z podłożem | ||
+ | * Tarcie dynamiczne przy niskiej prędkości | ||
+ | |||
+ | Dzięki interfejsowi graficznemu użytkownik może manipulować parametrami i obserwować efekty fizyczne w czasie rzeczywistym. | ||
- | === 7.1 Uwaga nt. funkcji draw_polar_arrow === | ||
- | Funkcja rysuje wektor w układzie polarnym z określonym kątem $\theta$ i długością $r$, dodając znacznik strzałki oraz tekstową etykietę. | ||
- | == 8. Zakończenie i pętla główna == | ||
- | Na końcu tworzymy animację: | ||
- | < | ||
- | ani = animation.FuncAnimation(fig, | ||
- | root.protocol(" | ||
- | root.mainloop() | ||
- | </ | ||
- | Funkcja `on_closing()` zapewnia poprawne zakończenie pętli Tkinter i zamknięcie okna. | ||
- | --- | ||
- | Ten artykuł pokrywa wszystkie główne elementy skryptu: od definicji parametrów fizycznych, przez mechanikę ruchu, aż po elementy GUI i animacji. Dzięki zastosowaniu LaTeX‐owych wzorów równania są czytelne i wiernie odzwierciedlają użyte w kodzie prawa dynamiki. | ||