Il moto di un corpo lungo un piano inclinato può essere studiato come esempio di moto in una dimensione. Obiettivo di questo esempio è quello di studiare la posizione, la velocità e l'accelerazione in funzione del tempo.
L'oggetto che si muove lungo il piano inclinato può essere descritto come un punto materiale che si muove lungo una retta. La posizione del punto materiale può essere individuata tramite la coordinata $ x $, il cui valore corrisponde in questo caso alla distanza tra l'oggetto ed un sensore situato all'inizio della pista.
In particolare, utilizziamo un sensore ad ultrasuoni HC-SR04 che viene alimentato e controllato tramite una scheda Raspberry Pi (Raspberry Pi 3 Model B).
Semplici codici Python permettono di:
Registrare i valori di distanza tra il sensore fisso ed il veicolo in movimento.
E contemporaneamente misurare il tempo trascorso da un certo istante iniziale.
I collegamenti del sensore alla scheda Raspberry Pi ed i codici Python per effettuare le misure sono descritti nel riferimento 1. Physics Education 2020 (v. anche Supplementary Information)
Tempo (s) | Distanza (m) |
---|---|
6.300999302766286e-06 | 0.04921078322613539 |
0.20044025799870724 | 0.04400026829147464 |
Ottenere una rappresentazione grafica dei dati.
Elaborare i dati per ottenere i valori della velocità in funzione del tempo.
Rappresentare graficamente l'andamento della velocità in funzione del tempo.
Calcolare i valori dell'accelerazione in funzione del tempo e mostrare l'andamento in un grafico.
Analizzare i dati della velocità:
Scegliendo un intervallo di tempo nel quale l'andamento della velocità in funzione del tempo è lineare.
Trovando i parametri della retta che si adatta meglio ai dati sperimentali.
Valutare i risultati ottenuti riportando in un'unica figura i grafici di: coordinata $ x $, velocità e accelerazione.
Confrontare il valore stimato dell'accelerazione con il valore calcolato utilizzando un modello fisico.
Altri dettagli sui codici Python e sull'analisi dati sono forniti nel notebook Viaggio in ascensore.
Predisponiamo un piano inclinato ed un oggetto che possa essere lasciato muovere lungo il piano inclinato.
Una grandezza che caratterizza le condizioni in cui viene svolto l'esperimento è la misura dell'angolo che il piano inclinato forma con la direzione orizzontale. Si può misurare facilmente questo angolo installando sullo smartphone l'applicazione phyphox. Tra i menù disponibili, sotto la voce Strumenti scegliere Inclinazione (misura l'angolo d'inclinazione del telefono). Premere il tasto play per iniziare la misura.
Si manda in esecuzione sulla Raspberry Pi il codice distance_recorder.py e si lascia che l'oggetto si muova lungo il piano inclinato, mentre i valori di distanza vengono misurati e memorizzati in un array. Lo script Python produce il file distance_table.csv in cui sono riportati i dati del tempo e della distanza.
Con il seguente codice leggiamo i dati contenuti nel file distance-table.csv e riportiamo in grafico la distanza sensore - oggetto in funzione del tempo trascorso da un certo istante iniziale.
# Utilizzato per importare la libreria adoperata per le strutture e le funzioni matematiche.
import numpy as np
# Utilizzato per importare la libreria adoperata per i grafici.
import matplotlib.pyplot as plt
# Utilizzato per importare un file di dati.
inputDataFile = "Dati/distance-table.csv"
# Utilizzato per leggere il file di dati.
t, x = np.loadtxt(inputDataFile, delimiter = ",", unpack = True)
# Utilizzato per il grafico.
plt.figure(1, figsize = (15, 15)) # Utilizzato per creare, numerare e dimensionare il grafico.
# Utilizzato per il titolo.
plt.title("Distanza sensore - oggetto in funzione del tempo", fontdict = {"fontsize": 17.5}, pad = 10)
# Utilizzato per la x.
plt.xlabel("Tempo $ (s) $", fontsize = 12.5)
# Utilizzato per la y.
plt.ylabel("Distanza $ (m) $", fontsize = 12.5)
# Utilizzato per rappresentare x e y.
plt.plot(t, x, "o", color = "#0075E2", markersize = 5)
# Utilizzato per la griglia.
plt.grid(True)
# Utilizzato per avere gli assi con la stessa scala.
plt.gca().set_aspect("equal", adjustable = "box")
# Utilizzato per mostrare il grafico.
plt.show()
Per calcolare la velocità consideriamo gli spostamenti $ \Delta x $ e la durata degli intervalli di tempo $ \Delta t $ tra due misure successive. La velocità media riferita ad ogni intervallo di tempo viene calcolata come:
Questo valore di velocità media viene riferito ad un tempo $ t' $ ottenuto come valore medio del tempo nell'intervallo $ \Delta t $ considerato. I dati calcolati vengono memorizzati in un file Incline-Speed.csv.
# Utilizzato per importare il file.
speedDataFile = "Dati/Incline-Speed.csv"
# Utilizzato per impostare il numero di cifre decimali nella stampa dei dati su file.
np.set_printoptions(precision = 20)
# Utilizzato per calcolare delta t.
delta_t = np.diff(t)
# Utilizzato per calcolare delta x.
delta_x = np.diff(x)
# Utilizzato per calcolare la velocità in m/s.
v = delta_x / delta_t
# Utilizzato per calcolare il valore medio del tempo in ogni intervallo di tempo.
t_prime = t[:-1] + (delta_t / 2)
# Utilizzato per salvare i dati in un file.
np.savetxt(speedDataFile, np.column_stack((t_prime, v)))
Abbiamo già importato in una delle celle di codice di questo notebook Jupyter la libreria Matplotlib, quindi con le seguenti righe di codice possiamo utilizzare la funzione plt.plot() e tutte le altre funzioni della libreria per costruire un grafico della velocità in funzione del tempo.
# Utilizzato per il grafico.
plt.figure(2, figsize = (15, 15)) # Utilizzato per creare, numerare e dimensionare il grafico.
# Utilizzato per il titolo.
plt.title("Velocità in funzione del tempo", fontdict = {"fontsize": 17.5}, pad = 10)
# Utilizzato per la x.
plt.xlabel("Tempo $ (s) $", fontsize = 12.5)
# Utilizzato per la y.
plt.ylabel("Velocità $ (m/s) $", fontsize = 12.5)
# Utilizzato per rappresentare x e y e.
plt.plot(t_prime, v, "o", color = "#0075E2", markersize = 5)
# Utilizzato per la griglia.
plt.grid(True)
# Utilizzato per avere gli assi con la stessa scala.
plt.gca().set_aspect("equal", adjustable = "box")
# Utilizzato per mostrare il grafico.
plt.show()
L'accelerazione dell'oggetto che si muove lungo il piano inclinato viene calcolata in questo esempio come accelerazione media riferita a ciascun intervallo di tempo $ \Delta t' $.
Ciascun valore di accelerazione viene associato ad un tempo uguale al valore medio del corrispondente intervallo $ \Delta t' $. I dati vengono memorizzati in un file Incline-Acceleration.csv.
# Utilizzato per importare il file.
accelerationDataFile = "Dati/Incline-Acceleration.csv"
# Utilizzato per impostare il numero di cifre decimali nella stampa dei dati su file.
np.set_printoptions(precision = 20)
# Utilizzato per calcolare delta t'.
delta_t_prime = np.diff(t_prime)
# Utilizzato per calcolare delta v.
delta_v = np.diff(v)
# Utilizzato per calcolare l'accelerazione in m/s^2.
a = delta_v / delta_t_prime
# Utilizzato per calcolare il valore medio del tempo' in ogni intervallo di tempo.
t_double_prime = t_prime[:-1] + (delta_t_prime / 2)
# Utilizzato per salvare i dati in un file.
np.savetxt(accelerationDataFile, np.column_stack((t_double_prime, a)))
I valori ottenuti vengono riportati in un grafico.
# Utilizzato per il grafico.
plt.figure(3, figsize = (15, 15)) # Utilizzato per creare, numerare e dimensionare il grafico.
# Utilizzato per il titolo.
plt.title("Accelerazione in funzione del tempo", fontdict = {"fontsize": 17.5}, pad = 10)
# Utilizzato per la x.
plt.xlabel("Tempo $ (s) $", fontsize = 12.5)
# Utilizzato per la y.
plt.ylabel("Accelerazione $ (m/s^{2} $)", fontsize = 12.5)
# Utilizzato per rappresentare x e y.
plt.plot(t_double_prime, a, "o", color = "#0075E2", markersize = 5, label = "Calculated")
# Utilizzato per la legenda.
plt.legend(loc = "lower left", shadow = True, fontsize = "large")
# Utilizzato per la griglia.
plt.grid(True)
# Utilizzato per avere gli assi con la stessa scala.
#plt.gca().set_aspect("equal", adjustable = "box")
# Utilizzato per mostrare il grafico.
plt.show()
Possiamo osservare che l'accelerazione assume anche valori negativi. Questi valori corrispondono all'intervallo di tempo in cui l'oggetto, dopo essersi mosso lungo tutto il piano inclinato, viene rallentato bruscamente di proposito contro un ostacolo morbido.
Il numero di coppie (tempo $ t' $, velocità $ v $) è dato dalla dimensione dell'array che può essere calcolata tramite la funzione np.size() della libreria NumPy.
# Utilizzato per calcolare la dimensione dell'array.
np.size(t_prime)
27
Per poter restringere l'analisi ad un determinato intervallo di tempo utilizzamo due marker, ciascuno dei quali corrisponde al numero progressivo del dato considerato.
# Utilizzato per importare la libreria adoperata per i widget.
import ipywidgets as widgets
# Utilizzato per creare un widget (IntSlider) adoperato per cambiare interattivamente il valore del primo marker.
sliderMarkerOne = widgets.IntSlider(min = 0, max = (np.size(t_prime) - 1), step = 1, value = 9, continuous_update = False)
# Utilizzato per creare un widget (IntSlider) adoperato per cambiare interattivamente il valore del secondo marker.
sliderMarkerTwo = widgets.IntSlider(min = 0, max = (np.size(t_prime) - 1), step = 1, value = 17, continuous_update = False)
# Funzione.
def funzione(MarkerOne, MarkerTwo):
print("Valori consigliati: 9, 17") # Utilizzato per stampare.
print("Primo marker =", MarkerOne, "-", "Secondo marker =", MarkerTwo) # Utilizzato per stampare.
MarkerOneTime = t_prime[MarkerOne] # Utilizzato per il primo marker.
MarkerTwoTime = t_prime[MarkerTwo] # Utilizzato per il secondo marker.
# Utilizzato per stampare.
print("Primo tempo =", MarkerOneTime, "s", "-", "Secondo tempo =", MarkerTwoTime, "s")
makeplots(MarkerOne, MarkerTwo) # Utilizzato per adoperare la funzione grafico.
# Utilizzato per avere il sottoinsieme dei valori del tempo compresi tra i due marker.
t_subset = t_prime[MarkerOne:MarkerTwo]
# Utilizzato per avere il sottoinsieme dei valori della velocità compresi tra i due marker.
v_subset = v[MarkerOne:MarkerTwo]
# Funzione grafico.
def makeplots(MarkerOne, MarkerTwo):
# Utilizzato per creare e dimensionare il grafico.
fig = plt.figure(figsize = (15, 15))
# Grafico 1.
plt.subplot(2, 1, 1)
# Utilizzato per il titolo.
plt.title("Velocità in funzione del tempo", fontdict = {"fontsize": 17.5}, pad = 10)
# Utilizzato per la x.
plt.xlabel("Tempo $ (s) $", fontsize = 12.5)
# Utilizzato per la y.
plt.ylabel("Velocità $ (m/s) $", fontsize = 12.5)
# Utilizzato per rappresentare x e y.
plt.plot(t_prime, v, "o", color = "#0075E2", markersize = 5)
# Utilizzato per rappresentare il primo marker.
plt.plot(t_prime[MarkerOne], v[MarkerOne], "o", color = "black", markersize = 7.5, zorder = -1)
# Utilizzato per rappresentare il secondo marker.
plt.plot(t_prime[MarkerTwo], v[MarkerTwo], "o", color = "black", markersize = 7.5, zorder = -1)
# Utilizzato per disegnare il primo marker.
plt.axvline(color = "black", x = t_prime[MarkerOne], linewidth = 1.5, linestyle = "--", zorder = -1)
# Utilizzato per disegnare il secondo marker.
plt.axvline(color = "black", x = t_prime[MarkerTwo], linewidth = 1.5, linestyle = "--", zorder = -1)
# Utilizzato per avere gli assi con la stessa scala.
#plt.gca().set_aspect("equal", adjustable = "box")
# Utilizzato per la griglia.
plt.grid(True)
# Grafico 2.
plt.subplot(2, 1, 2)
# Utilizzato per il titolo.
plt.title("Accelerazione in funzione del tempo", fontdict = {"fontsize": 17.5}, pad = 10)
# Utilizzato per rappresentare x e y.
plt.plot(t_double_prime, a, "o", color = "#0075E2", markersize = 5)
# Utilizzato per disegnare il primo marker.
plt.axvline(color = "black", x = t_prime[MarkerOne], linewidth = 1.5, linestyle = "--", zorder = -1)
# Utilizzato per disegnare il secondo marker.
plt.axvline(color = "black", x = t_prime[MarkerTwo], linewidth = 1.5, linestyle = "--", zorder = -1)
# Utilizzato per la x.
plt.xlabel("Tempo $ (s) $", fontsize = 12.5)
# Utilizzato per la y.
plt.ylabel("Accelerazione $ (m/s^{2} $)", fontsize = 12.5)
# Utilizzato per avere gli assi con la stessa scala.
#plt.gca().set_aspect("equal", adjustable = "box")
# Utilizzato per la griglia.
plt.grid(True)
# Utilizzato per collegare i widget alla funzione e per interagire con gli slider.
widgets.interact(funzione, MarkerOne = sliderMarkerOne, MarkerTwo = sliderMarkerTwo)
Valori consigliati: 9, 17 Primo marker = 9 - Secondo marker = 17 Primo tempo = 1.9042753854992043 s - Secondo tempo = 3.5076683864990628 s
<function __main__.funzione(MarkerOne, MarkerTwo)>
In una certa regione del grafico l'andamento della velocità in funzione del tempo è lineare. I valori della velocità soddisfano un'equazione del tipo:
Considerando che la velocità iniziale è nulla, si ha:
Ovvero:
Il grafico di $ v $ in funzione di $ t $ può essere quindi descritto con l'equazione di una retta che, in un piano cartesiano $ O xy $, è:
Nel codice Python che segue definiamo una funzione che permette di calcolare i parametri $ A $ e $ B $ che forniscono il miglior accordo tra un insieme di dati e una retta. Applichiamo l'algoritmo all'insieme dei dati della velocità nell'intervallo di tempo che abbiamo selezionato ed otteniamo:
Il valore del parametro A
Il valore del parametro B
# Utilizzato per avere il sottoinsieme dei valori del tempo' compresi tra i due marker.
t_prime_subset = t_prime[sliderMarkerOne.value:sliderMarkerTwo.value]
# Utilizzato per avere il sottoinsieme dei valori della velocità compresi tra i due marker.
v_subset = v[sliderMarkerOne.value:sliderMarkerTwo.value]
# Funzione fit lineare.
def LineFit(x, y):
x_avg = x.mean()
slope = (y * (x - x_avg)).sum() / (x * (x - x_avg)).sum()
y_intercept = y.mean() - slope * x_avg
return slope, y_intercept
# Utilizzato per calcolare i valori dell'accelerazione e della velocità con la funzione LineFit e per inserirli in due variabili.
a_est, v_intercept = LineFit(t_prime_subset, v_subset)
print("Valore stimato dell'accelerazione (dal fit lineare): \na = {0:0.4} m/s^2".format(a_est)) # Utilizzato per stampare.
t0 = - v_intercept / a_est # Tempo iniziale in s.
print("Tempo iniziale: \nt0 = {0:0.4} s".format(t0)) # Utilizzato per stampare.
Valore stimato dell'accelerazione (dal fit lineare): a = 1.295 m/s^2 Tempo iniziale: t0 = 1.829 s
Vogliamo riassumere i risultati ottenuti in un'unica figura. I grafici sono organizzati in una tabella costituita da tre righe ed una colonna.
v_fit = a_est * t_prime_subset + v_intercept # Velocità fit lineare in m/s.
a_fit = v_fit / v_fit * a_est # Accelerazione fit lineare in m/s^2.
x_fit = 0.5 * a_est * (t_prime_subset - t0) ** 2 + 0.029 # Distanza fit lineare in m.
# Utilizzato per il grafico.
fig = plt.figure(figsize = (15, 22.5)) # Utilizzato per creare e dimensionare il grafico.
# Grafico 1.
plt.subplot(3, 1, 1)
# Utilizzato per il titolo.
plt.title("Distanza in funzione del tempo", fontdict = {"fontsize": 17.5}, pad = 10)
# Utilizzato per la x.
plt.xlabel("Tempo $ (s) $", fontsize = 12.5)
# Utilizzato per la y.
plt.ylabel("Distanza $ (m) $", fontsize = 12.5)
# Utilizzato per rappresentare x e y.
plt.plot(t, x, "o", color = "#0075E2", markersize = 5, label = "Dati")
# Utilizzato per rappresentare x e y.
plt.plot(t_prime_subset, x_fit, "-", color = "black", linewidth = 1, zorder = -1, label = "Fit")
# Utilizzato per disegnare il primo marker.
plt.axvline(color = "black", x = t_prime_subset[0], linewidth = 1.5, linestyle = "--", zorder = -1)
# Utilizzato per disegnare il secondo marker.
plt.axvline(color = "black", x = t_prime_subset[-1], linewidth = 1.5, linestyle = "--", zorder = -1)
# Utilizzato per la legenda.
plt.legend(loc = "upper left", shadow = True, fontsize = "large")
# Utilizzato per avere gli assi con la stessa scala.
#plt.gca().set_aspect("equal", adjustable = "box")
# Utilizzato per la griglia.
plt.grid(True)
# Grafico 2.
plt.subplot(3, 1, 2)
# Utilizzato per il titolo.
plt.title("Velocità in funzione del tempo", fontdict = {"fontsize": 17.5}, pad = 10)
# Utilizzato per la x.
plt.xlabel("Tempo $ (s) $", fontsize = 12.5)
# Utilizzato per la y.
plt.ylabel("Velocità $ (m/s) $", fontsize = 12.5)
# Utilizzato per rappresentare x e y.
plt.plot(t_prime, v, "o", color = "#0075E2", markersize = 5)
# Utilizzato per rappresentare x e y.
plt.plot(t_prime_subset, v_fit, "-", color = "black", linewidth = 1)
# Utilizzato per disegnare il primo marker.
plt.axvline(color = "black", x = t_prime_subset[0], linewidth = 1.5, linestyle = "--", zorder = -1)
# Utilizzato per disegnare il secondo marker.
plt.axvline(color = "black", x = t_prime_subset[-1], linewidth = 1.5, linestyle = "--", zorder = -1)
# Utilizzato per avere gli assi con la stessa scala.
#plt.gca().set_aspect("equal", adjustable = "box")
# Utilizzato per la griglia.
plt.grid(True)
# Grafico 3.
plt.subplot(3, 1, 3)
# Utilizzato per il titolo.
plt.title("Accelerazione in funzione del tempo", fontdict = {"fontsize": 17.5}, pad = 10)
# Utilizzato per la x.
plt.xlabel("Tempo $ (s) $", fontsize = 12.5)
# Utilizzato per la y.
plt.ylabel("Accelerazione $ (m/s^{2} $)", fontsize = 12.5)
# Utilizzato per rappresentare x e y.
plt.plot(t_double_prime, a, "o", color = "#0075E2", markersize = 5, label = "Calculated")
# Utilizzato per rappresentare x e y.
plt.plot(t_prime_subset, a_fit, "-", color = "black", markersize = 1, label = "Fit")
# Utilizzato per la legenda.
plt.legend(loc = "lower left", shadow = True, fontsize = "large")
# Utilizzato per avere gli assi con la stessa scala.
#plt.gca().set_aspect("equal", adjustable = "box")
# Utilizzato per la griglia.
plt.grid(True)
# Utilizzato per salvare i dati in un file.
plt.savefig("Dati/Incline-Results.pdf")
# Utilizzato per mostrare il grafico.
plt.show()
I valori della velocità sono riportati insieme al grafico della retta che meglio approssima i dati sperimentali nell'intervallo considerato. (Grafico 2/3)
La pendenza di tale retta fornisce una stima dell'accelerazione. Questo valore costante di accelerazione è rappresentato come una linea orizzontale nel grafico che riporta i valori di accelerazione in funzione del tempo. (Grafico 3/3)
I valori sperimentali di $ x $ in funzione del tempo sono mostrati in grafico (Grafico 1/3) insieme ai dati calcolati utilizzando l'equazione:
Con i valori di $ a $ e $ t_0 $ ottenuti dal fit lineare dei dati di velocità e con il valore di $ x_0 $ che fornisce il miglior adattamento della curva (parabola) ai valori sperimentali di $ x $ vs. $ t $.
Se si considera come modello fisico il sistema costituito da un punto materiale che si muove senza attrito lungo il piano inclinato sotto l'azione della forza peso, conoscendo l'angolo di inclinazione $ \theta $, si può prevedere che il moto sarà un moto con accelerazione costante pari a:
Dove $ g $ è l'accelerazione di gravità.
Nel nostro esempio:
Consideriamo la misura dell'angolo $ \theta $ ottenuta usando l'App phyphox.
Convertiamo la misura in radianti.
Calcoliamo il valore atteso dell'accelerazione in base alla previsione del modello.
ang_grad = 11 # Inclinazione in gradi.
ang_rad = ang_grad / 180 * np.pi # Inclinazione in radianti.
print("Inclinazione theta = {0:0.6} rad".format(ang_rad))
Inclinazione theta = 0.191986 rad
# Utilizzato per calcolare il seno dell'angolo in radianti.
np.sin(ang_rad)
0.1908089953765448
a_model = 9.8 * np.sin(ang_rad) # Accelerazione in assenza di attrito in m/s^2.
# Utilizzato per stampare.
print("Valore stimato dell'accelerazione in assenza di attrito: \na = {0:0.3f} m/s^2".format(a_model))
# Utilizzato per stampare.
print("Valore dell'accelerazione stimato tramite fit lineare dei dati sperimentali: \na = {0:0.3f} m/s^2".format(a_est))
relative_error = (a_model - a_est) / a_model # Errore relativo in percentuale.
# Utilizzato per stampare.
print("Errore relativo = {0:0.1f} %".format(relative_error * 100))
Valore stimato dell'accelerazione in assenza di attrito: a = 1.870 m/s^2 Valore dell'accelerazione stimato tramite fit lineare dei dati sperimentali: a = 1.295 m/s^2 Errore relativo = 30.7 %
Per eseguire il codice Python contenuto in questo notebook Jupyter, anche se Python e Notebook Jupyter non sono installati sulla macchina che stai adoperando, puoi utilizzare l'ambiente binder online.
Possiamo osservare che l'accelerazione ottenuta dai dati sperimentali è minore di quella stimata sulla base del modello.
La presenza di una forza di attrito costante ha come conseguenza che la forza totale costante che agisce sul corpo in movimento è costante ed è minore rispetto al caso ideale. Si otterrebbe quindi un'accelerazione costante minore rispetto a quella attesa in assenza di attrito, in accordo con i risultati di questa indagine sperimentale.
Python
Acquisizione di dati con un apparato sperimentale controllato tramite software.
Elaborazione dei dati, analisi dei dati.
Rappresentazione grafica dei risultati.
Fisica
Misure di distanza in funzione del tempo.
Analisi dei dati.
Andamento grafico della velocità nell'esempio di moto con accelerazione costante.
Fit lineare dei dati della velocità e determinazione dell'accelerazione.
Equazioni del moto uniformemente accelerato.
# Utilizzato per importare la libreria adoperata per visualizzare l'HTML con il Python.
from IPython.core.display import HTML
css_file = "Notebook.css" # File CSS.
# Utilizzato per aprire e leggere il file CSS adoperato per modificare la visualizzazione del notebook.
HTML(open(css_file, "r").read())
(c) 2020 Andrea Mandanici, Marco Guarnera, Giuseppe Mandaglio, Giovanni Pirrotta. All content is under Creative Common Attribution CC BY 4.0 and all code is under BSD 3 - Clause License.