TP 6 : Mesure de la fréquence d'un pendule¶

Le but de ce TP est d’apprendre à manipuler un film issu d'une expérience afin d’extraire des données en fonction du temps.

Pendule TP

Ici on étudie l'oscillation d’un pendule, on comparera les données expérimentales avec une théorie simple.

Stockage d'un film¶

Vous avez vu durant les TP 4 et 5 que les images sont stockées sous la forme de matrices contenant la couleur (ou nuance de gris).

Un film étant une succession d’images dans le temps, il peut être stocké au moyen d’une matrice M(k,j,i) à 3 indices.

Les 2 derniers indices $(j,i)$ font référence à la position du pixel, comme dans une image classique. La dimension ($k$) correspond à l’indice de temps (et non à sa valeur).

La 3e image du film peut ainsi être appelée par la commande : M[2,:,:]

Pour le tableau M(k,j,i) on a donc :

  • $k$ l'indice du temps du pixel
  • $j$ l'indice de la ligne du pixel
  • $i$ l'indice de la colonne du pixel

La figure suivante illustre ce stockage sous forme de matrice : stockage.png

Oscillation d'un pendule¶

Objectif¶

À partir des deux films (pendule court et pendule long), nous allons retrouver la relation existant entre la fréquence d’oscillation $T$ d’un pendule et sa longueur $L$, et la comparer avec la prédiction théorique pour de faibles oscillations : $$T=2\pi\sqrt{L/g}$$ où $g$ est l’accélération de la pesanteur. Les questions suivantes devront donc être réalisées sur les deux films de pendule (court et long) pour faire les comparaisons.Pour mettre au point commencez par faire tout le TP avec pendule court, il sera ensuite assez facile de généraliser.

La théorie veut que l’oscillation obtenue soit proche d’une oscillation sinusoïdale : $$ x(t)= \beta+\alpha \sin\left( \frac{2\pi t}{T} +\phi\right),$$ avec :

  • $\beta$ : la valeur moyenne autour de laquelle le sinus oscille
  • $\alpha$ : l'amplitude de l’oscillation,
  • $T$ : la période d’oscillation,
  • $\phi$ : un déphasage.

À partir du film, on souhaite obtenir l'évolution $x(t)$ puis mesurer la période $T$.

In [ ]:
# On importe les modules nécessaires au TP
import imageio
import numpy as np
import matplotlib.pyplot as plt
import os

# Uniquement pour jupyter notebook
%matplotlib auto 

I. Visualisation du film¶

Vous disposez de deux films (que vous pourrez prévisualiser en dehors de Python ...) avec une fréquence d'échantillonage de 100 images par seconde.

Pour vous faciliter la tâche, les films ont été convertis en tableaux et sauvegardés dans des fichiers .npy. Le script pour faire l'opération du passage d'un film .avi au fichier .npy est donné en annexe mais ce n'est pas au programme.

Les fichiers .npy sont des fichiers binaires. L'avantage des fichiers binaires est qu'ils sont très compacts (plus petits en espace de stockage). L'inconvénient est qu'ils ne peuvent pas être lus dans un éditeur et modifiés simplement. Pour les fichiers texte on a utilisé les commandes np.loadtxt et np.savetxt. Pour les fichiers binaires, on se sert des commandes np.load et np.save. L'esprit est le même.

L'instruction tab_court = np.load('pendule_court.npy') permet de charger le tableau tab_court correspondant aux "frames" de pendule_court.avi .

  1. Charger les fichiers pendule_court.npy et pendule_long.npy dans les tableaux tab_court et tab_long
  2. Faire afficher le nombre d'images et les dimensions d'une image pour chaque film.
  3. La boucle pour réaliser l’animation du film en niveau de gris vous est donnée dans le cadre réponse. Elle permet de relire les images de la matrice stockée dans tab. On ne prend qu'une image sur 10 et un pixel sur 4 pour fluidifier la visualisation, vous pouvez modifier ces valeurs. (L'animation se sert de matplotlib en version "orienté objet" ce n'est pas au programme.)
  4. A l'aide de la question 3 et en modifiant éventuellement kstart, kstop, kstep, repérez une image sur laquelle le fil est bien vertical. Noter le numéro de cette image dans les variables indVerti_court et indVerti_long.
In [ ]:
# Réponse 


# Question 3 
"""
On peut mettre les 2 tableaux dans une liste pour faire les 2 films dans une boucle sur la liste.
Pour la mise au point, mettre uniquement tab_court
"""
for tab in [tab_court, tab_long] : 
    nbrFrame = tab.shape[0] # Nombre de frames du film
    kstart = 0
    kstop = nbrFrame
    kstep = 10
    fig = plt.figure(figsize=(6,6))
    ax = fig.gca()
    h = ax.imshow(tab[0,::4, ::4], cmap='gray') # On ne représente qu'un pixel sur 4 avec la section de tableau ::4
    for k in range(kstart, kstop, kstep) : # On parcourt le film de kstart à kstop par pas de kstep frames 
        h.set_data(tab[k, ::4, ::4])
        plt.title('Image #'+str(k))
        plt.draw()
        plt.pause(1e-1)

# Réponse 

II. Mesure de la longueur L du fil¶

  1. Sur une nouvelle figure, afficher uniquement une image (avec tous les pixels) pour laquelle le fil est bien vertical.
  2. Déterminer avec plt.ginput la longueur du pendule en pixels puis convertir en mètres. Il faut bien prendre une longueur de pendule allant de l'axe de rotation au centre de masse et se servir de l'échelle de longueur sur le côté. (N.B. à faire pour les 2 films et garder les valeurs dans lg_court et lg_long par exemple, conservez également la conversion pixel en mètre dans px2m_court et px2m_long)
In [ ]:
# Réponse 

III. Mesure de la période T du pendule¶

    • Binariser les niveaux de gris dans tab_bin. Choisir un seuil pour ne voir que le fil en noir, le reste de l'image en blanc. Prendre par exemple seuil=80.
    • Réduire la taille des images, en selectionnant les pixels entre les colonnes 160 et 400 sur l'horizontal
    • Afficher la première image du film en superposant sur la ligne 150 une ligne en tirets rouges en utilisant plot pendule.png
  1. Copier la ligne 150 (i.e. tab_bin[:, 150, :]) dans un tableau que vous appellerez tab_ligne. Le premier indice de ce tableau tab_ligne correspond au numéro d'image (donc le temps) et le deuxième à l'espace.
  2. On souhaite à présent tracer l'évolution spatio-temporelle du déplacement de la corde, c'est-à-dire l'amplitude du déplacement en fonction du temps : diag_spat_temp Observez le résultat de la commande plt.imshow(np.transpose(tab_ligne), cmap='gray'), c'est un diagramme spatio temporel. On veut maintenant mettre des axes qui ne soient pas les indices du tableau.
    • Construire un vecteur temps en secondes et un vecteur dist en mètres à partir des dimensions du tableau tab_ligne et en connaisant le nombre d'images par seconde et la conversion de pixels en mètres puis utilisez la fonction plt.pcolormesh(temps, dist, np.transpose(tab_ligne), cmap='gray') pour obtenir l'évolution spatio-temporelle ($x(t)$). plt.pcolormesh fonctionne comme plt.imshow en affichant l'image, mais permet en plus d'afficher des coordonnées en abscisses et en ordonnées autres que les indices.
  3. Le diagramme spatio-temporel que nous avons obtenu est encore une image (une matrice avec les tons de gris) et non la valeur de la position de la corde du pendule rangée dans vecteur.
    • Créer un tableau osc1=tab_ligne[0,:], correspondant à la ligne 150 de la première image.
    • Tracer osc1 en fonction de x.
  4. Il peut y avoir plusieurs pixels noirs sur une ligne. À l'aide des logiques, du tableau dist et osc1, faire la moyenne des distances des pixels noirs de osc1. Cette moyenne correspond à la coordonnée $x$ du fil.
    • Avec une boucle répéter cette opération pour chaque image et construire un vecteur osc qui a autant d’éléments que d’images avec la coordonnée $x$ de la corde à chaque instant.
    • Représenter alors sur un graphique l'évolution de osc en fonction du temps.
    • A partir de osc calculer les valeurs de $\alpha$ et $\beta$
    • Mesurer sur la figure la période $T$ (utiliser ginput en moyennant sur plusieurs périodes) et garder les valeurs dans T_court et T_long .
    • Déterminer $\phi$ en minimisant l'erreur quadratique ($Err = \sum (x_{theorie}(t) - x_{exp}(t))^2$) de façon similaire à ce qui a été vu dans les TP précédents. On prendra des valeurs de phi entre 0 et 5 par pas de 0.05.
    • Tracer observation et courbe théorique thVSexp
In [ ]:
# Réponse 

IV. Comparaison avec la prédiction théorique¶

  1. Une fois $T$ et $L$ déterminés pour les deux pendules, tracer le graphique de la variation théorique de $T$ en fonction de $L$ (avec $g = 9,81\rm ~ m \cdot s^{-2}$). Superposer à ce graphique, les points $(L_1, T_1)$ et $(L_2, T_2)$ qui correspondent à nos deux mesures expérimentales.
  2. La théorie marche-t-elle ? Combien de pourcents d'écart trouvez-vous sur la période ?
In [ ]:
# Réponse 

Annexe :¶

Dans ce TP, les deux fichiers .npy avec les tableaux contenant les images des deux films sont directement fournis au bon format pour Numpy. Dans la pratique, on dispose de films avec des formats classiques avi, mpeg, mp4 .... Ce qui suit vous explique comment relire vous-même ces films. Ce n’est pas au programme de l'UE.

Il faut tout d'abord installer un package supplémentaire imageio-ffmpeg qui n'est pas installé par défaut dans Anaconda. Pour faire cette installation, dans une fenêtre de Terminal (Linux ou mac OS) ou dans le terminal que l'on ouvre depuis Anaconda Navigator sous Windows, tapez la commande suivante:

conda install imageio-ffmpeg -c conda-forge

Vous aurez ainsi le package qui permet de relire les films dans divers formats.

Le script suivant fait l'opération souhaitée de conversion du film ici au format avi en fichier .npy. import imageio import numpy as np fileAVI = ['pendule_long.avi', 'pendule_court.avi'] # fait la liste des films à relire nameFinal = ['pendule_long', 'pendule_court'] # fait une liste des noms des fichiers de sauvegarde npy for file, name in zip(fileAVI, nameFinal) : # On parcourt les deux listes grace à zip reader = imageio.get_reader(file) # on associe à reader le film avi frames = [] # crée la liste vide frames for cur_frame in reader: # on parcourt les images du film frames.append(cur_frame) frames = np.array(frames) # conversion en tableau numpy en sortie de boucle frames = frames[:,:,:,0] # On ne garde que le "rouge" indice 0 pour avoir un film N&B np.save(name, frames) # Ecriture sur le disque du tableau dans le fichier name.npy

Note: Il serait aussi possible de travailler directement sur les 'frames' extraits du film sans passer par une sauvegarde dans un fichier npy sur le disque dur. Il y a de nombreuses autres possibilités d'import avec imageio d'images ou de films. Pour en savoir plus et voir des exemples de scripts, vous pouvez lire la documentation en anglais de ce module