Impression 3D pseudo 5 axes

De Wiki LOGre
Révision datée du 3 septembre 2019 à 07:45 par Fma38 (discussion | contributions) (Juillet 2019)
(diff) ← Version précédente | Voir la version actuelle (diff) | Version suivante → (diff)
Aller à : navigation, rechercher
Langue : Français  • English

Projet réalisé par Fma38.

En cours.

Présentation

Le but de ce projet est de pouvoir imprimer les panneaux du robot BB-8 de manière optimale.

BB-8 orange-panel.png

Ces panneaux sont des portions de sphère. Si on les imprime de manière classique, il faudra beaucoup de support. De plus, il y aura un effet d'escalier de plus en plus marqué vers le sommet ; cet effet pourrait être atténué en utilisant une hauteur de couche variable, au détriment du temps d'impression. Dans tous les cas, les couches resteront très visibles.

Étude

Une solution est d'utiliser une imprimante 5 axes, et d'imprimer le long de la sphère : les couches ne seraient alors plus visibles, puisque la surface du haut correspondrait à celle d'une pièce plane classique.

Si l'imprimante n'est pas très difficile à réaliser (!), il en va tout autrement du trancheur. À ce jour, seules quelques sociétés ont une solution de ce type, propriétaire, bien sûr.

Mais, au contraire d'une pièce quelconque, ici, on connaît parfaitement la géométrie - simple - de la pièce : une sphère. Il suffirait donc que le trancheur parcoure la pièce selon cette sphère, plutôt que le plan XY. Mais même cette modification n'est pas triviale, et bien au delà de mes compétences. Et je doute d'arriver à motiver un développeur de trancheur d'implémenter ça.

Heureusement, il y a une autre solution, beaucoup plus accessible, qui est de mapper la pièce sphérique sur le plan ! Cela se fait très simplement avec un script Python (cf ci-dessous). Une fois la pièce plane, n'importe quel trancheur de base fait l'affaire : il pensera parcourir la pièce suivant un plan, alors qu'il suit en fait une sphère ;o)

Il reste ensuite à transformer les coordonnées X/Y/Z en coordonnées X/Y/Z/A/B (où A et B sont les 2 axes supplémentaires, les rotations de la tête ou du plateau), de telle sorte que la tête se déplace bien sur la sphère plutôt que le plan.

Transformations

Sphère -> plan

Cette partie consiste à mapper le STL de la portion de sphère dans le plan, comme si on écrasait la pièce - molle - sur la table : elle s'étire donc dans le plan X/Y.

Plan -> sphère

Une fois la pièce mappée sur un plan, puis tranchée de manière classique, il faut donc générer les coordonnées X/Y/Z/A/B de la machine 5 axes à partir des coordonnées X/Y/Z.

Cette partie est plus complexe, car il faut :

  • remapper les déplacements plans sur la sphère ;
  • décomposer les grands mouvements en petits segments pour d'une part gérer la non-linéarité des nouveaux axes (rotations du plateau), et d'autre part parcourir la sphère et éviter les collisions.

LogBook

Juillet 2019

  • premier jet du code Python pour la transformation du STL (sphère vers plan) et de la transformation inverse du G-Code (plan vers sphère), avec segmentation
  • première impression de test -> pas si pire ! Note : le support en étoile a été généré/imprimé indépendemment.
  • il y a visiblement un souci de mapping/de-mapping, car la longueur d'un segment sur la pièce mappée est plus long que le segment correspondant sur la pièce dé-mappée :o/

Sphere.png Sphere mapped.png Sphere unmapped printed 1.png

Lien vers une courte vidéo

Code

Le code Python est disponible sur framagit.

Il permet :

  • de transformer un fichier STL (ascii ou binaire)
    • la portion de sphère doit être posée sur le plan Z=0, orientée vers le bas, et centrée sur l'axe Z
  • de tranformer un fichier G-Code mappé pour générer la cinématique 5 axes de déplacement le long de la sphère.

Les routines de conversion se résument à :

def mapToPlane(vertex):
    """ Map to plane
    """

    # Compute distance from center of sphere (P) to vertex (A)
    vector = Vector(vertex) - Vector([0, 0, config.BED_SPHERE_ORIGIN_Z])
    L = vector.length

    # Compte horizontal distance from Z axis to vertex
    Lu = math.sqrt(vertex.x ** 2 + vertex.y ** 2)

    # Compute angle between Z axis and PA
    alpha = math.atan2(Lu, vertex.z - config.BED_SPHERE_ORIGIN_Z)

    # Compute angle between X axis and PA in XY plane
    beta = math.atan2(vertex.y, vertex.x)

    # The mapping to plane is done by using the arc distance of vertex (A) as radius of mapped vertex (A')
    u = L * alpha
    x = u * math.cos(beta)
    y = u * math.sin(beta)
    z = L - config.RADIUS_INT

    return Vertex([x, y, z])


def unmapToSphere(vector):
    """ Map back to sphere
    """

    # Compute distance from center of sphere (P) to unmapped vertex (A)
    L = vector.z + config.BED_RADIUS_INT

    # Compute angle between Z axis and PA
    alpha = math.sqrt(vector.x ** 2 + vector.y ** 2) / L

    # Compute angle between X axis and PA in XY plane
    beta = math.atan2(vector.y, vector.x)

    # Compute horizontal distance from Z axis to vertex (A), and vertical distance from center of sphere (P) to unmapped vertex (A)
    Lu = L * math.sin(alpha)
    Lz = L * math.cos(alpha)

    # Unmapped vertex A coords
    x = Lu * math.cos(beta)
    y = Lu * math.sin(beta)
    z = Lz + config.BED_SPHERE_ORIGIN_Z
    if z < config.LAYER_HIGHT:
        z = config.LAYER_HIGHT
    A = Vector([x, y, z])

    # Compute bed rotation
    axis = vector.cross(Vector([0, 0, 1]))  # normal to Z axis and current point vector
    R = rotationMatrix(axis, alpha)
    a, b = extractEulerAnglesXY(R)

    # Rotated vertex A2 coords
    import numpy
    A = numpy.matrix([[A.x],
                      [A.y],
                      [A.z]])
    A2 = R * A

    A = Vector([float(A[0]), float(A[1]), float(A[2])])
    A2 = Vector([float(A2[0]), float(A2[1]), float(A2[2])])

    return A2, a, b