Marc Buffat, dpt mécanique, UCB Lyon 1
Attention il faut exécuter toutes les cellules suivantes pour afficher son nom !!
%matplotlib inline
import numpy as np
from matplotlib import pyplot as plt
import matplotlib.pyplot as plt
plt.rc('font', family='serif', size='14')
from validation.valide_markdown import test_markdown, test_code
from validation.validation import info_etudiant, bib_validation
from IPython.display import display, Markdown, clear_output# nom etudiant
def printmd(string):
display(Markdown(string))
# test si numero étudiant spécifier
try: NUMERO_ETUDIANT
except NameError: NUMERO_ETUDIANT = None
if NUMERO_ETUDIANT is None:
NOM,PRENOM,NUMERO_ETUDIANT = info_etudiant()
printmd("**Etudiant** {} {} id={}".format(NOM,PRENOM,NUMERO_ETUDIANT))
# generation des parametres
notebook_name = "TP_trajectoire.ipynb"
bib_validation('cours','MGC2028L')
from Circuit import Circuit,test_vitesse,test_trajectoire,test_acceleration
np.random.seed(NUMERO_ETUDIANT)
Circuit("circuit.txt");
np.random.seed(NUMERO_ETUDIANT)
_H_ = 200.0 + np.random.randint(50)
Etudiant NBGrader Course id=2592889824
L'objectif du TP est d'apprendre à manipuler des tableaux numpy représentant des fonctions, pour pouvoir numériquement analyser ces fonctions, calculer numériquement la dérivée de ces fonctions ou pouvoir numériquement les intégrer.
Les 2 cas traités sont:
Dans un fichier "vchute.dat" sont stockées les mesures de vitesse d'un objet en chute libre en fonction du temps, sous la forme de 2 colonnes: le temps en seconde et la vitesse en km/h séparée par un espace.
Le contenu du fichier est de la forme suivante
# temps et vitesse pour une chute libre
0.000 0.000
0.100 -3.529
0.200 -7.045
0.300 -10.533
Utiliser la fonction numpy loadtxt pour lire les données et les mettre dans les 2 variables T et U.
Vérifier que les 2 variables T et U sont bien des tableaux numpy de même dimension et tracer la courbe de vitesse en fonction du temps avec un titre et des labels sur les axes pour vérifier.
Dans la suite, on utilisera comme unité : s. pour le temps, km/h pour la vitesse, et m pour la distance.
# lecture des données
T = None
U = None
## BEGIN SOLUTION
T,U = np.loadtxt("vchute.dat",delimiter=' ',unpack=True)
print("Vérification ", T.size==U.size)
plt.plot(T,U,label="U")
plt.title("vitesse de Chute libre")
plt.xlabel('t en sec.')
plt.ylabel('vitesse en km/h')
plt.legend()
## END SOLUTION
Vérification True
<matplotlib.legend.Legend at 0x7f4050ee6be0>
# ne rien ecrire
## BEGIN HIDDEN TESTS
assert(T.size == U.size)
assert(test_code(notebook_name,"cell-verif01",
["plt.plot","plt.title","plt.xlabel","plt.ylabel"]))
## END HIDDEN TESTS
Sur le graphe précédent, on constate que la vitesse tend vers une valeur limite $u_{lim}$ que l'on va calculer.
On obtient une estimation du temps limite $t_{lim}$ en déterminant où dans le tableau DU, la valeur devient, en valeur absolue, inférieure à une précision $\epsilon$ fixée: i.e. l'indice k tq. $|DU_k| < \epsilon$ avec une précision $\epsilon=10^{-2}$.
Pour calculer cet indice k, on utilise la fonction numpy where:
la fonction np.where(condition) (où condition est une condition sur un tableau X (p.e. np.where(X>0)) renvoie les indices du tableau où cette condition est réalisée
Mettre dans la variable k le numéro de cet intervalle. Calculer les valeurs moyennes de t et U sur cet intervalle k pour en déduire $t_{lim}$ et $u_{lim}$ que l'on mettra dans Tlim et Ulim.
Affichez la valeur de Tlim et Ulim.
dU = None
k = None
Tlim = None
Ulim = None
### BEGIN SOLUTION
dU = U[1:]-U[:-1]
k = np.where(np.abs(dU)<0.01)[0][0]
Tlim = (T[k]+T[k+1])/2.
Ulim = (U[k+1]+U[k])/2.
print(Tlim,Ulim,max(T),max(np.abs(U)))
### END SOLUTION
8.25 -79.6235 10.0 79.707
# ne rien écrire dans cette cellule
### BEGIN HIDDEN TESTS
assert(np.allclose(dU,U[1:]-U[:-1]))
assert(k == np.where(np.abs(dU)<0.01)[0][0])
assert(np.isclose(Tlim,(T[k]+T[k+1])/2.))
assert(np.isclose(Ulim,(U[k]+U[k+1])/2.))
### END HIDDEN TESTS
D'après l'étude précédente sur chaque intervalle de temps $[t_i,t_{i+1}]$, on connaît la vitesse $u_i$ en $t_i$ et la vitesse $u_{i+1}$ en $t_{i+1}$. On peut donc en déduire la distance parcourue $d_i$ par l'objet entre $t_i$ et $t_{i+1}$ en utilisant la vitesse moyenne avec la relation :
$$ d_i = \frac{u_{i}+u_{i+1}}{2} (t_{i+1} - t_{i}) $$
A partir de la position $x_i$ à $t_i$, on peut alors en déduire la position $x_{i+1}$ à $t_{i+1}$
$$ x_{i+1} = x_i + d_i $$
Connaissant la position $x_0$ à l'instant initiale, on a donc une méthode itérative pour calculer la position du solide au cours du temps.
Trajectoire1D(t,u) , qui à partir du tableau des temps t (en sec.) et des vitesses u (en km/h), calcule la distance parcourue en m dans un tableau x et renvoie ce tableau. Faire attention aux unités
# definition de la fonction Trajectoire
## BEGIN SOLUTION
def Trajectoire1D(t,u):
""" calcule et retourne la trajectoire 1D dans x en m
les arguments sont le tableau des temps t en s. et des vitesses u en km/h"""
n = t.size
x = np.zeros(n)
for i in range(1,n):
um = (u[i]+u[i-1])/2./3.6
x[i] = x[i-1] + (t[i]-t[i-1])*um
return x
# calcul
X = Trajectoire1D(T,U)
print(min(X),max(X))
plt.plot(T,X)
plt.title("Trajectoire")
plt.xlabel("t sen sec.")
plt.ylabel("x en m")
## END SOLUTION
-186.81406944444447 0.0
Text(0, 0.5, 'x en m')
# ne rien écrire dans cette cellule
### BEGIN HIDDEN TESTS
assert (X.size == T.size)
assert (np.allclose(X , Trajectoire1D(T,U)))
### END HIDDEN TESTS
On suppose que l'objet est lâché sans vitesse initiale à partir d'une hauteur H donnée ci-dessous.
On veut calculer le temps $t_{fin}$ où l'objet atteint la surface de la terre. On connaît la position à la fin des mesures, et on sait que l'objet en fin de trajectoire atteint une vitesse limite.
En déduire alors la valeur du temps d'impact $t_{fin}$ que l'on stockera dans la variable tfin
Pour vérifier, tracer la position de l'objet par rapport à la surface de la terre en fonction du temps. Tracer aussi la position du point d'impact dans la cellule suivante avec des titres, labels et légendes.
Vous devriez obtenir une figure similaire à la figure ci-dessous:
print("hauteur H = ",_H_)
hauteur H = 239.0
H = 0
tfin = 0
## BEGIN SOLUTION
H = _H_
# distance restante à parcourir
dr = H + X[-1]
tr = dr/np.abs(Ulim/3.6)
tfin = T[-1]+tr
print("Temps impacte: ", tfin,T[-1],dr,tr)
## END SOLUTION
Temps impacte: 12.359471136033958 10.0 52.18593055555553 2.3594711360339584
# tracer résultat et pt d'impact
## BEGIN SOLUTION
plt.plot(T,H+X,label='h(t)')
plt.plot([tfin],[0],'o',label='impact')
plt.title('Altitude h(t)')
plt.xlabel('temps [s]')
plt.ylabel('hauteur [en m]')
plt.legend()
plt.grid();
#plt.savefig('Hauteur_Temps.png')
## END SOLUTION
Commentaires sur la figure
%%% BEGIN SOLUTION
%%% END SOLUTION
# ne rien écrire dans cette cellule
### BEGIN HIDDEN TESTS
assert (tfin > T[-1])
### END HIDDEN TESTS
# ne rien écrire dans cette cellule
### BEGIN HIDDEN TESTS
assert(test_code(notebook_name,"cell-verif02",
["plt.plot","plt.title","plt.xlabel","plt.ylabel"]))
### END HIDDEN TESTS
On veut étudier la cinématique d'un cycliste sur piste à partir de mesures de sa vitesse en fonction du temps.
Les données du circuit sont dans le fichier circuit.txt qui contient 3 colonnes correspondants au temps (en s.), et aux 2 composantes de la vitesse suivant x et y (en km/h).
Dans la cellule suivante:
circuit.txt en utilisant la fonction loadtxt pour les mettre dans 3 tableaux T,U,V. .Umean la moyenne de Umorm , son minimum Umin et son maximum Umax. On pourra utiliser les fonctions (méthodes) numpy: mean(), max() et min()appliquées aux tableaux.T = None
U = None
V = None
Unorm = None
Umean = None
Umin = None
Umax = None
### BEGIN SOLUTION
T,U,V = np.loadtxt('circuit.txt',unpack=True)
Unorm = np.sqrt(U**2 + V**2)
Umean = Unorm.mean()
Umax = Unorm.max()
Umin = Unorm.min()
print("Vitesse moyenne={:.1f}km/h min={:.1f} km/h max={:.1f}km/h".format(Umean,Umin,Umax))
### END SOLUTION
Vitesse moyenne=42.0km/h min=31.1 km/h max=51.8km/h
# tracer des vitesses
### BEGIN SOLUTION
plt.figure(figsize=(10,7))
plt.plot(T,U,label="U")
plt.plot(T,V,label="V")
plt.plot(T,Unorm,label="amplitude")
plt.xlabel('t [sec]')
plt.ylabel('U [km/h]')
plt.title("Vitesse du cycliste en km/h")
plt.legend();
#plt.savefig("vitesse.png")
### END SOLUTION
# ne rien écrire dans cette cellule
### BEGIN HIDDEN TESTS
# test sur les résultats (a executer)
assert((U.size == T.size) and (V.size == T.size))
assert(test_vitesse("circuit.txt",Umean,Umin,Umax))
### END HIDDEN TESTS
# ne rien écrire dans cette cellule
### BEGIN HIDDEN TESTS
assert(test_code("TP_trajectoire.ipynb","cell-verif00",["plt.plot","plt.title","plt.legend"]))
### END HIDDEN TESTS
A partir des composantes de vitesse U et V , on va calculer la trajectoire en fonction du temps, i.e. la position $X_i$ et $Y_i$ du point $P_i$ de la trajectoire pour chacun des temps $T_i$.
On va généraliser l'approche précédente, en calculant la distance parcourue $\mathbf{D}_{i}$ entre $T_{i-1}$ et $T_{i}$, mais de façon vectorielle:
$$ \mathbf{D}_{i} = \frac{1}{2}(\vec{U}_{i-1}+\vec{U}_{i-1}) dt \mbox { avec } dt = T_i - T_{i-1} $$d'où la position $P_i$ du cycliste donnée dans le repère $(O,x,y)$ par le vecteur $\mathbf{OP}_{i}$
$$ \mathbf{OP}_{i} = \mathbf{OP}_{i-1} + \mathbf{D}_{i} \leadsto X_{i} = X_{i-1} + \frac{1}{2}(U_{i-1}+U_i) dt , Y_{i} = Y_{i-1} + \frac{1}{2}(V_{i-1}+V_i) dt $$On constate que pour calculer la trajectoire X et Y on peut utiliser la fonction Trajectoire1D précédente.
Dans la cellule suivante:
X et Y en utilisant la fonction Trajectoire1DL L avec la longueur moyenne Lmean que l'on calculera en utilisant la vitesse moyenne précédente UmeanOn utilisera la fonction plt.quiver(X,Y,U,V) qui permet de tracer des flèches de longueur U,V aux points X,Y.
Pour éviter de tracer trop de flèches, on pourra prendre par exemple un point sur 10 en remplaçant X par X[::10] et idem pour tous les autres arguments.
X,Y = None,None
L = None
Lmean = None
### BEGIN SOLUTION
X = Trajectoire1D(T,U)
Y = Trajectoire1D(T,V)
# calcul longueur
L = 0
for i in range(1,X.size):
L += np.sqrt((X[i]-X[i-1])**2 + (Y[i]-Y[i-1])**2)
Lmean = Umean*(T[-1]-T[0])/3.6
print("Longueur du circuit {:.2f} m".format(L))
print("Verification / longueur moyenne :",Lmean)
### END SOLUTION
Longueur du circuit 470.56 m Verification / longueur moyenne : 469.9997864019623
# tracer
### BEGIN SOLUTION
plt.figure(figsize=(12,8))
plt.plot(X,Y)
plt.quiver(X[::10],Y[::10],U[::10],V[::10])
plt.title("Trajectoire")
plt.axis('equal');
#plt.savefig("trajectoire.png")
### END SOLUTION
# ne rien écrire dans cette cellule
### BEGIN HIDDEN TESTS
# test sur les résultats (a executer)
assert((X.size == T.size) and (Y.size == T.size))
print("Longueur du circuit {:.2f}m".format(L))
assert(test_trajectoire("circuit.txt",X,Y,L))
assert(np.abs(L-Lmean)<L*0.01)
### END HIDDEN TESTS
Longueur du circuit 470.56m
# ne rien écrire dans cette cellule
### BEGIN HIDDEN TESTS
assert(test_code("TP_trajectoire.ipynb","cell-verif1",["plt.plot","plt.quiver","plt.title"]))
### END HIDDEN TESTS
Pour le calcul de l'accélération, on se place sur chaque intervalle k de temps $[T_{k},T_{k+1}]$. Sur cet intervalle, la vitesse varie de ${U_{k},V_{k}}$ de ${U_{k+1},V_{k+1}}$ et l'accélération mesure cette variation de vitesse suivant x dans $Gx_k$ et suivant y dans $Gy_k$
$$ Gx_k = \frac{\Delta U}{\Delta t} = \frac{U_{k+1} - U_{k}}{T_{k+1} - T_{k}}, Gy_k = \frac{\Delta V}{\Delta t} = \frac{V_{k+1} - V_{k}}{T_{k+1} - T_{k}}$$
Cette accélération est calculée pour un temps $Tm_k$ correspondant à la moyenne de $[T_{k}$ et $T_{k+1}]$
$$ Tm_k = \frac{T_{k+1}+T_{k}}{2} $$
Dans la cellule suivante:
Gx et Gy respectivement. Attention le calcul de l'accélération se fait en unité SI: $ms^{-2}$Tm A partir du calcul précédent, on se propose de calculer l'accélération tangentielle et normale, i.e. le vecteur accélération projeté dans le référentiel local direct formé par la tangente et la normale en chaque point de la trajectoire. En se plaçant sur chaque intervalle k, on peut calculer la tangente $\vec{t}$ à partir de la vitesse moyenne $\vec{u}_m$
$$ \vec{t} = \frac{\vec{u}_m}{ |{\vec{u}_m}|}$$puis en déduire la normale $\vec{n}$. Il suffit alors de projeter l'accélération calculée suivant x et y pour obtenir l'accélération tangentielle et normale.
Dans une boucle sur chacun des intervalles k, calculer les composantes suivant x et y de la tangente dans tx, ty et de la normale dans nx, ny. En déduire la
composante d'accélération tangentielle Gt_k et normale Gn_k. On mettra ces composantes dans les tableaux numpy Gn et Gt.
Tracer sur une figure l'accélération suivant x, suivant y, l'accélération normale et l'accélération tangentielle avec comme unité le g ($g=9.81 ms^{-2}$)
Commenter le résultat dans la cellule suivante, et en particulier la variation de l'accélération tangentielle.
Faire attention aux unités
g = 9.81
Gx = None
Gy = None
Gt = None
Gn = None
### BEGIN SOLUTION
N = X.size
# calcul acceleration
Gx = np.zeros(N-1)
Gy = np.zeros(N-1)
for i in range(0,N-1):
Gx[i] = (U[i+1]-U[i])/(T[i+1]-T[i])/3.6
Gy[i] = (V[i+1]-V[i])/(T[i+1]-T[i])/3.6
# temps
Tm = (T[:-1]+T[1:])/2.
# projection
Gt = np.zeros(N-1)
Gn = np.zeros(N-1)
for i in range(0,N-1):
um = (U[i]+U[i+1])/2.
vm = (V[i]+V[i+1])/2.
tx = um/np.sqrt(um**2+vm**2)
ty = vm/np.sqrt(um**2+vm**2)
Gt[i] = Gx[i]*tx + Gy[i]*ty
Gn[i] =-Gx[i]*ty + Gy[i]*tx
# tracer
plt.figure(figsize=(14,8))
plt.plot(Tm,Gx/g,label="Gx")
plt.plot(Tm,Gy/g,label='Gy')
plt.plot(Tm,Gn/g,label="Gn")
plt.plot(Tm,Gt/g,label='Gt')
plt.legend()
plt.xlabel("t en sec.")
plt.ylabel("$\gamma$ en g")
plt.title("Composantes de l'accélération");
#plt.savefig("acceleration.png")
### END SOLUTION
Commentaires sur la figure
%%% BEGIN SOLUTION
%%% END SOLUTION
# ne rien écrire dans cette cellule
### BEGIN HIDDEN TESTS
# test sur les résultats (a executer)
assert((Gx.size == T.size-1) and (Gy.size == T.size-1))
assert((Gn.size == T.size-1) and (Gt.size == T.size-1))
assert(test_acceleration("circuit.txt",Gt/g,Gn/g,None))
assert(test_code("TP_trajectoire.ipynb","cell-verif2",["plt.plot","plt.title"]))
### END HIDDEN TESTSS
L'objectif est de calculer l'angle $\theta$ d'inclinaison du cycliste, qui correspond à l'équilibre des forces dans le référentiel lié au cycliste dans le plan de la figure:
$$ \vec{F_c} + \vec{P} + \vec{R} = \vec{0}$$La force centrifuge $\vec{F_c} = - M \vec{\gamma_n}$ est une force fictive qui est opposée à l'accélération dans la direction normale, et qui traduit cet équilibre statique dans le référentiel lié au cycliste. Dans le référentiel fixe, on retrouve le PFD dans le plan de la figure:
$$ \vec{F_c} + \vec{P} = M \vec{\gamma_n}$$Remarque dans la direction tangentielle (i.e. la direction perpendiculaire au plan de la figure) on a un équilibre entre l'accélération tangentielle, la force de traction, et les forces de frottements.
Pour calculer $\theta$, il faut donc utiliser l'accélération tangentielle et normale, i.e. le vecteur accélération projeté dans le référentiel local directe formé par la tangente et la normale en chaque point de la trajectoire.
Calculer 'angle d'inclinaison $\theta$ en degré du cycliste pour composer la force centrifuge en prenant $g=9.81 \ m/s^{-2}$. On mettra le résultat dans le tableau numpy THETA. On pourra utiliser la fonction numpy arctan2(a,b) qui calcule l'angle en radian dont la tangente vaut $a/b$.
Tracer l'angle d'inclinaison du cycliste.
Commenter l'ordre de grandeur de l'angle d'inclinaison $\theta$, et discuter sa variation.
# calcul de l'angle
### BEGIN SOLUTION
THETA = np.rad2deg(np.arctan2(Gn,g))
# tracer
plt.figure(figsize=(14,8))
plt.plot(Tm,THETA)
plt.ylim(-20,20)
plt.xlabel("t en sec.")
plt.ylabel("$\\theta$ en degré")
plt.title("inclinaison en degré");
#plt.savefig("acceleration.png")
### END SOLUTION
Commentaires sur la figure
%%% BEGIN SOLUTION
%%% END SOLUTION
# ne rien écrire dans cette cellule
### BEGIN HIDDEN TESTS
# test sur les résultats (a executer)
assert(THETA.size == T.size-1)
assert(test_acceleration("circuit.txt",Gt/g,Gn/g,THETA))
assert(test_code("TP_trajectoire.ipynb","cell-verif3",["plt.plot","plt.title"]))
### END HIDDEN TESTSS