Calculer un tracer pour une CNC
wisky
Membre
Bonjour a tous,
J'ai une question de mathématique et géométrie. Je sais réaliser un dessin avec BezierPath. J'arrive à charger, sauvegarder, dessiner les trais, cercle, etc...
Maintenant ce logiciel est prévu pour commander une CNC (fraiseuse à commande numérique).
Les commandes envoyées à la CNC sont du genre Y+;X+;Z+ pour une valeur constant le plus est remplacer par le = et par un - pour la diminution !
Comment faire pour calculer chaque point d'un tracer ?
Pour des lignes droite sur les axes X ou Y c'est simple mais comment faire pour les autres type de lignes, un cercle, du texte ?
Si vous avez des liens pour que je trouve les méthode de calcul je prend !
J'ai une question de mathématique et géométrie. Je sais réaliser un dessin avec BezierPath. J'arrive à charger, sauvegarder, dessiner les trais, cercle, etc...
Maintenant ce logiciel est prévu pour commander une CNC (fraiseuse à commande numérique).
Les commandes envoyées à la CNC sont du genre Y+;X+;Z+ pour une valeur constant le plus est remplacer par le = et par un - pour la diminution !
Comment faire pour calculer chaque point d'un tracer ?
Pour des lignes droite sur les axes X ou Y c'est simple mais comment faire pour les autres type de lignes, un cercle, du texte ?
Si vous avez des liens pour que je trouve les méthode de calcul je prend !
Connectez-vous ou Inscrivez-vous pour répondre.
Réponses
x(t) = xO+R*cos(t)
y(t) = yO+R*sin(t)
t = [ 0 ; 2*PI ]
Et plus spécialement pour un ovale :
x(t) = xO+R1*cos(t)
y(t) = yO+R2*sin(t)
t = [ 0 ; 2*PI ]
* L'équation paramétrique d'une courbe de Bézier, c'est :
x(t) = x0*(1-t)^3+3*x1*t*(1-t)^2+3*x2*t^2*(1-t)+x3*t^3
y(t) = y0*(1-t)^3+3*y1*t*(1-t)^2+3*y2*t^2*(1-t)+y3*t^3
Pour les lettres, tu ne trouveras jamais, ça ne peut pas être défini par une courbe le TrueType... c'est un fonctionnement interne à base de courbes de Bézier quadratiques définissant le contour des lettres.
Le problème va être de trouver le pas idéal pour faire évoluer t, vu qu'apparemment ta CNC ne prend comme commande que des offsets unitaires sur chacun des axes (on peut pas dire X=X+3 par exemple, juste X+ pour augmenter X d'une unité, c'est ça ?).
Du coup le plus simple est de faire évoluer t avec un pas assez petit, et de voir si une des valeurs de X ou Y (tronqué à l'unité de ta CNC, j'imagine des entiers) a changé.
- Si X et/ou Y, une fois arrondi à l'entier, a changé depuis la dernière valeur, et seulement d'une unité, tu émets la commande X+/-/= et Y+/-/= correspondante et tu passes à l'offset
- Si X et/ou Y, une fois arrondi, a changé mais de plus d'une unité, par exemple X a augmenté de 2... comme tu ne peux pas émettre de "X+2", soit tu émets 2 commandes X+ à suivre, ce qui peut suffire si tu n'as pas besoin de grosse précision, soit tu insères un pas intermédiaire pour t (tu refais le calcul pour un t à mi chemin entre la dernière valeur et la valeur courante), jusqu'à ce que ton offset en X (et en Y) soit au maximum unitaire (ce qui est plus précis, en particulier si tu as par exemple un deltaX de 100 d'un coup pour un deltaY de 1, parce que tu dessines une forme dont la tangente est quasi confondue avec l'axe des abscisses
- Si X et Y sont tous les deux inchangés, bah tu n'émets rien (ce serait inutile d'émettre la commande X=,Y= !) et tu passes au t suivant.
Voilà pour le principe qui te permettrait de te ramener à des déplacements unitaires, du moins c'est ce qui me parait le mieux
* Si aucun changement, on double t
* Si changement unitaire, on laisse t à sa valeur
* Si changement trop grand, on divise t par 2 et on refait le calcul
Les commandes de base sont celles données dans mon premier poste. Cependant, il est possible d'ordonner un déplacement plus grand. Dans ce cas, la commande est du genre : +2;+3;0 avec dans l'ordre le nombre à ajouter/retrancher à X;Y;Z.
@schlum
Je pensait pas que les formules étaient si complexes. Il va falloir que je ressorte mes bouquins de math
Où puis-je trouver rapidement des explications sur ses formules ? Mes cours de math sont trop loin.
Il y a une variable (t) qui varie dans un intervalle donné et qui à chaque pas donne l'abscisse et l'ordonnée.
"^2" veut dire au carré -> t^2 = t*t
"^3" veut dire au cube -> t^3 = t*t*t
"sin" et "cos" sont dans math.h, ainsi que des macros donnant PI
Après, s'il y a des transformations appliquées, c'est plus complexe (surtout pour les rotations), il faut multiplier chaque couple abscisse / ordonnée par les matrices des transformations.
Par contre oui faut pas se laisser impressionner par les formules, elles sont simples et en plus tu n'as pas spécialement à les retravailler, tu peux les utiliser telles qu'elles : si par exemple on se contente de faire évoluer t régulièrement par pas de kStep, ça donne un truc comme ça tout bêtement :
Pour le moment, je ne compte pas ajouter de transformation. Le dessin de base me suffit
Après je demanderai peut être à un prof de math de m'aider :P
(heu je suis pas sûr du nom des méthodes, je cite ça de tête c'est juste pour montrer l'idée)
C'est bien transformPoint, mais comme ça c'est mieux :
Ou pour une taille :
Au final cela va me permettre de réalisez beaucoup de chose
Sur la CNC un pas d'un moteur représente 1/10eme de millimètre il en faut 10 pour faire un millimètre.
La CNC n'est pas encore monté mais j'aimerai arrivé à ce niveau de précision. Tout cela pour réaliser des perçage de circuit imprimer.
Il me faudra donc arriver à avoir le même définition sur mon dessin. Il me faut donc monté à 254ppp. Quelqu'un à une idée ?
Du coup comme on a [tt]x = x0.(1-t)³ + 3*x1.t.(1-t)² + 3.x2.t².(1-t) + x3.t³[/tt], ça nous donne si je ne me trompe :
[tt]dx = [-3.x0.(1-t)² + 3.x1.(1-t).(1-3t) + 3.x2.t.(2-3t) + 3.x3.t²] * dt[/tt]
Et pareil pour dy. Du coup avec ces formules on a directement le delta en X et en Y en fonction de t et dt (le pas d'avancement en t, kStep dans mon exemple)... Bon ça doit revenir au même que calculer x(t) et faire la différence avec le précédent x(t-dt) de l'itération d'avant (le lastPos de mon dernier post), qu'on le fasse chaque étape (pos, lastPos, et la différence) par code ou tout en une seule ligne...
J'ai pas essayé mais on devrait retomber sur le même résultat, que ce soit en faisant le calcul de la différencielle comme j'ai fait, le calcul de (x(t)-x(t-dt)) ou qu'on fasse par code le calcul de x(t) et la différence ensuite...
Sauf que j'ai un petit problème avec la fonction bezier :
A gauche : le cercle, au centre : l'oval, à droite la coube de bezier.
Les traits rouge bleu et gris représentent les lignes droite entre les points. Pourquoi cela continue après le passage au point final ?
Autre question, comment calculer point par point la ligne rouge (pas taper) ?
pour une ligne bezier c'est : t varie entre 0 et 1
pour les lignes c'est ça :
donc :
x(t) = xO +t (x1 - xO)
y(t) = yO +t (y1 - yO)
En plus ça se devine un peu à cause des (1-t) qui trainent, permettant de tomber sur les points (x0,y0) en t=0... et (x3,y3) en t=1, puisqu'à ce moment là (1-t) vaut zéro et annule plein de termes... :P
Sinon oui pour la ligne c'est ça (et de même on retrouve P0 en t=0 et P1 en t=1 )
Euh... Méfie toi avec la dérivée...
t^3 a pour dérivée 3*t^2
0 -> 0
1 -> 1 (d = 1 ; f' = 3)
2 -> 8 (d = 7 ; f' = 12)
3 -> 27 (d = 19 ; f' = 27)
4 -> 64 (d = 37 ; f' = 48)
C'est loin d'être corrélé
La dérivée donne le vecteur vitesse instantané, c'est tout...
Comment ça " on " ! N'essaie pas de partager la faute
Vu la tronche de l'équation, ça me paraissait tellement évident que c'était entre 0 et 1 que je ne l'ai même pas précisé
C'est quoi la " ligne rouge " ?
Celle sur l'image écran. J'ai trouvé l'équation pour une ligne droite
ça Marche bien !!
Et puis c'est pas justement la vitesse instantannée qu'on veut ?
Je veux dire en plus si on reprend la formule de la dérivée, c'est la limite quand dx tend vers 0 de [tt]f'(t) = (f(t+dt)-f(t))/dt[/tt] non ? Et du coup la formule de la différencielle de f c'est pas [tt]df = f'(t)*dt = f(t+dt)-f(t)[/tt] ?
Or f(t+dt)-f(t) c'est précisément ce que l'on veut dans notre cas, la différence (offset) entre le point à l'instant t (point courant) et celui à l'instant t+dt (prochaine position à atteindre), non ?
Oui j'ai pas compris de suite non plus... mais c'est juste bah son tracé de courbe de bézier. Au lieu de tracer une seule courbe tout de la même couleur, il a tracé 3 NSBezierPath (qui se révèlent être 3 segments en fait), un en rouge, un en bleu, un en gris. Enfin c'est ce que j'ai fini par en comprendre ^^
La vitesse instantanée est... une vitesse instantanée :P
Si tu veux pouvoir l'utiliser sur ∆t pour calculer un ∆x, ∆y, il faut justement que tu l'intègres sur ce ∆t... Intégrer une dérivée alors qu'on a la courbe originelle c'est pas forcément le must
Et heu sinon j'ai toujours du mal à voir ce que j'ai de faux dans mon raisonnement (∆f = f(t+∆t)-f(t) = f'(t)*∆t... pour ∆t suffisamment petit, c'est à dire tendant vers zéro, supposition acceptable vu le contexte puisqu'on cherche justement à faire avancer t d'un pas le plus petit possible)
En plus je capte pas dans ce que tu m'expliques pourquoi ce que je dis cloche : on cherche (pour chaque t) le ∆x et ∆y instantané (= au point t considéré)... ce qui est justement précisément donné par le vecteur vitesse instantané ! Donc qu'est ce qui te gène ?
L'idée est de trouver la formule de ∆x et ∆y pour tout t, donc de calculer pour chaque point à l'instant t le vecteur vitesse instantané. Si tu préfères, ça revient à trouver pour chaque point P de la courbe la tangente à la courbe en ce point P, ce qui va nous donner la direction globale et locale (instantané) uniquement de la courbe en ce point... donc la direction globale vers laquelle aller pour aller au "prochain point" de la courbe.
Après une fois arrivé à ce "prochain point", il faudra évidemment recalculer la nouvelle vitesse instantanée à ce nouveau point et ne pas réutiliser la précédente, ça va de soi, pour recalculer la nouvelle tendance de direction à prendre.
Alors évidemment, ça ne marche que si ∆t est assez petit... Finalement c'est une sorte de développement limité de ta courbe au voisinage du point {x(t),y(t)}... donc faut rester dans le voisinage du point... mais c'est le cas puisqu'on veut justement les déplacements de ∆t les plus petits possibles pour un maximum de précision.
Comme là on cherche le déplacement de la tête de la CNC à effectuer quand on est au point P, calculer la dérivée de la courbe en ce point P pour directement avoir la vitesse instantanée et donc les ∆x et ∆y que l'on recherche me parait donc pourtant tout adapté, moi... Qu'est ce que j'ai loupé dans mon raisonnement ?
d c'est f(x+1)-f(x), et f' c'est f'(x)
Parce que tu raisonnes en delta alors que ce n'est pas un delta, la dérivée est la limite pour le delta tendant vers 0 justement.
Non, ça ne marche justement que si ∆t est infiniment petit. Tu peux toujours essayer de le programmer pour un ∆t quelconque, tu ne t'en sortiras jamais
f'(t) = limit((f(t+∆t)-f(t))/∆t,∆t->0)
Que veux-tu faire avec ça ?
Pour un quelconque ∆t, pour calculer un ∆x, ∆y il faudra passer par l'intégrale de la dérivée, qui par définition est le ∆x et le ∆y. Au lieu de faire une dérivée, puis une intégrale, autant passer directement par la fonction
la valeur 1 est un vachement trop grande à l'échelle de l'évolution de ta fonction, tu m'étonnes que tu aies des écarts si grands
Bah non moi je prenais des ∆t suffisemment petits pour que l'approximation par DL soit correcte, rester au voisinage quoi.
Même avec un ∆t de l'ordre de 10^-6 ou dans ces eaux-là ?
Evidemment je te l'accorde, le résultat ne sera pas parfait (au sens que ce ne sera pas une égalité mathématique, mais une approximation au voisinage), mais largement suffisante je pense...
C'est précisément le même principe que quand tu fais un DL de ta courbe en un point t=t0, si tu restes assez proche du voisinage de t0, l'approximation est en général vraiment suffisante.
Bien sûr si tu commences à t'éloigner de t0 ça devient vite catastrophique comme approx, mais là c'est loin d'être notre cas... Enfin si c'est ton cas quand tu prends ∆t = 1 comme dans ton exemple si j'ai tout suivi (f(x+1)-f(x)), et c'est pas étonnant... mais avec un ∆t=10^6 ou dans ces eaux-là pourquoi ça ne serait pas suffisant ?
Alors entendons-nous bien : je ne soutiens plus que ma méthode est une solution viable pour le problème de wisky, car en effet (1) c'est pas dit que ça optimise tant que ça et (2) le code serait beaucoup moins lisible en passant par là ... et surtout (3) oui en effet ok il n'y a pas exact égalité mathématique entre les calculs obtenus par les 2 méthodes, la mienne restant une approximation puisque j'utilise un ∆t petit... au lieu du résultat de la limite quand dt tend vers 0.
Mais j'aimerais juste comprendre pourquoi ça te semble si inadapté, je veux dire même si ça reste une approximation, utilisant sur le principe notre bon vieux Taylor/McLaurin, tant qu'on reste au voisinage de la courbe au point considéré (ce que j'estime être le cas avec un ∆t de l'ordre de 10^-6), je trouve que l'approximation serait amplement suffisante, non ?
Alors ok pour le cas de wisky c'est pas la peine de se prendre la tête à calculer la différentielle au final... mais pour le principe mathématique ?
f'(t) = lim((f(t+∆t)-f(t))/∆t,∆t->0+)
C'est la définition la plus adaptée à ce que tu essaies de faire je suppose...
Donc ce que tu essaies de me dire, c'est que f'(t)*10^-6 ~ f(t+10^-6)-f(t)
Donc f(t+10^-6) ~ f(t) + f'(t)*10^-6
Certes, mais tu veux tirer quoi de cette quasi égalité ? (qui doit être en gros un développement limité d'ordre 0 donc très mauvais dès qu'on s'éloigne d'un tantinet)
Sans compter que pour faire le développement limité (approximation polynomiale) d'un polynôme, faut vraiment avoir envie de se prendre la tête (tu fais un développement limité de niveau 3, je te garantis que tu vas retomber sur ta courbe exacte :P)
Puisqu'à chaque étape, ce que cherche wisky c'est [tt]d = f(t+∆t)-f(t)[/tt] pour savoir de quel delta il doit se déplacer justement, puisque ce qu'il veut c'est déplacer sa tête de fraiseuse à CN d'un certain delta en X,Y. Et ce f(t+∆t)-f(t)... ça équivaut à [tt]d ~ f'(t)*∆t[/tt] justement...
Nan mais bon je vois que t'accroche pas, on va laisser tomber et arrêter là
Tu déplaces ta tête, de ce ∆x,∆y (de l'ordre de 10^-6, ne l'oublions pas ), et... paf, t'es déjà plus exactement sur la courbe
Tu répètes ça 1M de fois pour avoir un truc de l'ordre d'1 pixel... -> Dieu sait où t'es par rapport à la courbe déjà
En 0 on est à 0
On prend un ∆x de 10^-6
Dérivée 2*x
On va donc se déplacer f'(x)*∆x = 2*0*10^-6
Ensuite, de 2*(10^-6)*10^-6
Ensuite, de 2*(2*10^-6)*10^-6
À chaque pas, de 2*(i*10^-6)*10^-6 = 2*10^-12*i
sum(2*10^-12*i,i,0,n-1) = 2*10^-12*n*(n-1)/2 = 10^-12*n*(n-1)
On est donc à une erreur de 10^-12 par pas.
pour x^3, ça donne à peu près le même calcul
10^-18*(n-1)*n*(2*n-1)/2
En fait, ça fonctionne à peu près parce que l'erreur est en O(∆t^2)
Après, avec 1M, ça revient presque à faire une intégrale puisque l'intégrale c'est ce calcul quand ∆t tends vers 0
Faire un DLn simple (degré 1 suffisant) pour que ça soit suffisamment proche
Après justement l'idée c'est que comme on cherche les ∆x et ∆y en fonction de t, là on les a direct (je vois pas pourquoi tu disais qu'on devait faire l'intégrale pour retomber sur nos pieds... si tu fais la limite de la somme à ∆t = 0, ce qui revient à faire l'intégrale, ça te permet de vérifier que tu retombes sur tes pieds... Mais en l'occurrence c'est les ∆x et ∆y qu'on cherche pas les x et y de toute façon.
Par contre c'est vrai qu'en partat de (x0,y0) et n'utilisant que les ∆x,∆y pour évoluer (ce que fait la CNC finalement), avec le cumul d'erreurs on risque en effet de dériver trop loin sur le long terme, ça je suis tout à fait d'accord. Donc certes au final pour le pb de wisky il faut mieux calculer d'abord (x,y) pour tomber sur la courbe, en déduire le ∆x,∆y pour connaà®tre la commande à envoyer à la CNC... et recalculer x et y pour le coup d'après, justement juste pour éviter qu'il y ait ce cumul d'erreur à long terme.
Après bon c'était juste pour lancer le débat côté mathématique parce que c'est toujours intéressant
En bougeant de la diagonale d'1 pixel, on sait qu'on aura forcément un changement unitaire (en ∆x, en ∆y ou les 2).
Avec la dérivée seconde, on a en plus l'accélération, ce qui permet d'affiner le calcul... Accélération, on prend un ∆s de calcul plus petit sachant que ça va aller plus loin que prévu (entre 1 et √2), décélération, on en prend un plus grand sachant que ça va aller moins loin que prévu (entre √2 et 2).