Projet

Général

Profil

Étude mathématique

Explication sur la solution optimale

Voir sur la page Wikipédia de la courbe

Choix des courbes de Bézier

On utilise pour cela le logiciel Jupyter, afin de réaliser de courts algorithmes en Python permettant d'élaborer les courbes de Bézier.

Pour rappel, une courbe de Bézier est définie ici pour quatre points : un point A de départ, un point B d'arrivée, et deux points de contrôle A' et B', tels que le début de la courbe de Bézier est sur la tangente [AA'], et la fin de la courbe sur la tangente [BB'].
Ne pouvant utiliser de caractère ', on notera ces deux derniers points Ap et Bp.


Image de MarianSigler

Comme annoncé dans le synopsis, on souhaite décrire quatre courbes :
  • la droite allant du point A au point B ;
  • la courbe solution du problème ;
  • une courbe médiane entre ces deux-ci, donc avec peu de courbure ;
  • une courbe hyperbolique, avec une très grande courbure.

⚠️ Attention : sur Jupyter par défaut, l'axe des ordonnées va vers le haut. Le point d'origine est donc le coin inférieur gauche de la courbe.

Pour tracer la droite allant du point A au point B, il suffit de prendre la courbe de Bézier avec comme points de contrôle le point milieu du segment [AB].
Pour tracer la courbe hyperbolique, avec une très grande courbure, on ajuste à la volée les points de contrôle de la courbe de Bézier. Ici, nous avons pris comme points de contrôle le point (0, 0).
Idem pour tracer la courbe médiane entre la cycloïde et la droite, ci-dessous tracée en rouge, avec comme points de contrôles choisis les points (0,1 ; 0,2) et (0,4 ; 0,05).

Approximation de la cycloïde par des courbes de Bézier

Mathématiquement, une cycloïde est d'équation paramétrique . Dans Jupyter, on utilise alors une fonction qui renvoie un point appartenant à la cycloïde à partir d'une valeur comprise entre 0 et 1 :

def cycloid(t):
    theta = 314/100*t
    D = 37/100
    return vector((D/2*(theta - sin(theta)), D - D/2*(1 - cos(theta))))

Ici, D, qui vaut 0.37, est la hauteur du point de départ de notre cycloïde (choisie ainsi suite à la taille des planches à notre disposition).

On pourra alors afficher la cycloïde, en faisant appel à la fonction parametric_plot de Jupyter, qui affiche une courbe en fonction d'un paramètre, ici t, que l'on fait varier entre 0 et 1.
Pour approximer la cycloïde avec des courbes de Bézier, on peut prendre une dizaine de points de contrôle qui sont autant de points de la cycloïde.
Malheureusement, cette solution n'a pas marché pour nous. On s'est ici résolu à approximer la cycloïde avec des segments entre 200 points de la courbe de la cycloïde. Pour les calculer, nous avons utilisé l'algorithme suivant :

N = 200
for t in range(N+1):
    M = cycloid(t/N).n()
    print("L %.2f %.2f " % (40+M[0]*1000, 360-M[1]*1000), end="")

L'algorithme affiche ici toutes les coordonnées des points, ajustés afin de correspondre aux coordonnées des premiers dessins sur la planche, et précédés de L afin de tracer des lignes en format vectoriel (ceci nous permet de copier le résultat de l'algorithme sans avoir à entrer manuellement les points).

Nous avons ainsi approximé la cycloïde avec des segments. On pourra à loisir augmenter ou diminuer le nombre de segments pour augmenter ou diminuer la précision, mais avec 200 points, la cycloïde une fois découpée ne laisse transparaitre aucune coupure.


Image des quatre courbes découpées, de haut en bas : le segment entre les deux points, une courbe de faible courbure, la cycloïde et l'hyperbole.

Calcul du temps de parcours

Pour rappel, un point M d'une courbe de Bézier est d'équation : avec A, A', B', B les points caractéristiques de la courbe de Bézier.

Physiquement, si l'on omet les forces de frottement (plus ou moins importants selon que l'on ait choisi de faire une rigole ou deux planches alignées), on retrouve l'équation de conservation de l'énergie . On simplifie par , puis après quelques opérations, on trouve .

On intègre alors pour déterminer le temps.

Là aussi, un algorithme permet de calculer cela pour nous, en lui injectant une courbe (c'est-à-dire un ensemble de points définis par un point) :

def timing(curve):
    g = 981/100
    var('t')
    length = curve(t).derivative(t).norm()
    velocity = sqrt(2*g*(curve(0)[1] - curve(t)[1]))
    time = length/velocity
    return integral(time, t, 0, 1).n()

On obtient alors ces prévisions de durée de roulement :

Droite 0,511 s
Courbe rouge 0,440 s
Cycloïde 0,419 s
Hyperbole 0,459 s