visualiseur G-code
LinuxCNC · rs274 PySide6 / OpenGL LGPL-2.1

Un tracé qui ne ment pas

Les visualiseurs G-code ordinaires n'implémentent pas le RS274NGC de LinuxCNC. Sur un fichier paramétré, ils n'échouent pas : ils inventent.

un .ngc paramétré écrire son propre parseur mêmes angles morts appeler rs274 l'interprète de LinuxCNC lui-même un dessin faux, présenté comme juste ce que la machine fera vraiment le programme ne fait que dessiner ce que l'interprète répond
Ce qu'on voit

Le parcours, le bois, et les erreurs

Un demi-million de segments à la fréquence de l'écran, le brut qui se creuse au fil du rejeu, et des erreurs qui s'expliquent au lieu de se taire.

Le tracé, coloré par profondeur

Le visualiseur affichant une gravure de pâquerettes vue de dessus, colorée par profondeur Z, avec le G-code à droite
561 931 segments, 3,8 s à charger, fluide ensuite. La coloration suit ici la profondeur Z, avec sa légende en bas à gauche ; six modes existent — rapide/travail, profondeur, puissance laser, avance, outil, et programme, qui montre d'un coup d'œil quelle part du travail revient à quelle fraise. La barre d'état donne l'étendue, la longueur travail/rapides et la durée estimée : ici 3 h 56 min 57 s, suivie de sa ventilation travail / rapides — c'est la répartition, et non le total, qui départage deux stratégies d'usinage.

Le code et le tracé, liés dans les deux sens

Cliquer un segment ouvre sa ligne ; poser le curseur sur une ligne éclaire ses segments. Y compris dans les sous-programmes : un mouvement engendré par toolchange.ngc ouvre toolchange.ngc à la bonne ligne, pas la ligne de même numéro du programme principal.

Le rejeu suit le temps, pas les segments

La tête avance selon la durée estimée. Sur une gravure, dix mille micro-traits pèsent un dixième du parcours mais la moitié du temps — un rejeu au numéro de segment donnerait une idée fausse du travail.

Le bloc de bois se creuse

Le même travail avec la matière activée : le brut en bois s'est creusé là où la fraise est passée, à mi-parcours du rejeu
Touche M : le brut apparaît et se laisse usiner au fil du rejeu, éclairé pour que le relief se lise. Ici à mi-parcours — 2 h 10 min sur 3 h 57 —, avec le volume enlevé affiché en continu : 33,7 cm³. Plusieurs programmes peuvent s'empiler sur le même brut, chacun avec sa fraise : ébauche à la Ø6, finition à la Ø3,175, détourage à la fraise en vé.

Une erreur, et la raison de l'erreur

Bandeau rouge « tracé incomplet » expliquant qu'un mot K est interdit dans un arc du plan XY, avec la ligne fautive marquée dans la marge
La moindre erreur d'interprétation donne un bandeau rouge, la ligne fautive marquée dans la marge, et la mention « tracé incomplet ». Le tracé partiel reste affiché : voir jusqu'où la machine serait allée est ce qui aide à comprendre.
Ajouter au message, jamais le remplacer

Les messages de rs274 sont exacts mais courts. « K word given for arc in xy plane » n'apprend rien à qui veut juste tailler une pièce — alors le visualiseur y ajoute le pourquoi et le remède : le mot K est interdit en G17, certains post-processeurs FreeCAD en écrivent un à zéro que GRBL ignore mais que LinuxCNC refuse, et il suffit de réexporter avec le bon post-processeur. Ce que dit l'interprète n'est jamais effacé.

L'origine

Quelques cercles au mauvais endroit, sans un mot

percage_lit_atc.ngc perce le lit de la machine. Il emploie des paramètres #<nom>, des expressions [..] et des O… IF — c'est ce qui permet de le lancer d'abord en essai à blanc, dix millimètres au-dessus du lit, avant de couper pour de bon.

Chargé dans un visualiseur en ligne, il a produit quelques cercles au mauvais endroit. Pas une alerte, pas un avertissement : un dessin faux, présenté comme juste. Ces outils lisent un G-code de base et ignorent le reste. Sur un fichier ordinaire ça passe ; sur un fichier paramétré, ça invente.

Le fichier de perçage du lit affiché en vue isométrique : vingt perçages alignés, avec le G-code paramétré lisible à droite
Le fichier en question, tracé juste : vingt perçages, 8 999 segments, 4 min 38 s estimées. À droite, le G-code avec ses #<essai>, #<ep_lit> et #<debouche> — ce sont eux que les visualiseurs ordinaires ne savent pas lire.
Le parti pris qui en découle

Ne pas écrire de parseur G-code. Écrire le sien, c'est refaire le même bug avec les mêmes angles morts. LinuxCNC livre l'interpréteur qui fait autorité ; ce programme l'appelle et se contente de dessiner ce qu'il répond.

Le contrôle qui le prouve, à chaque exécution des tests

Le fichier paramétré et son jumeau développé à la main — écrit à l'époque justement pour contourner les visualiseurs ordinaires — sont comparés segment par segment.

8 999segments identiques
entre les deux fichiers
< 1 µmd'écart en XY
sur l'ensemble du parcours

Le jumeau développé à la main n'a plus de raison d'être : c'est peut-être le meilleur résultat du projet.

Dans l'atelier CAM

Un bouton dans FreeCAD, et pourquoi ce n'est pas un doublon

Un greffon ajoute une icône à la barre de l'atelier CAM de FreeCAD. Il poste le Job courant et ouvre le résultat dans le visualiseur, en processus séparé. Le G-code n'est pas écrit sur le disque et le document n'est pas modifié.

FreeCAD a pourtant déjà son simulateur. Mais il lit operations[i].Path.Commands — les objets Path internes. Il montre donc ce que FreeCAD a l'intention de faire, jamais ce que le post-processeur a écrit. Il est structurellement aveugle à un défaut de post-traitement, et ces défauts existent : sur 167 fichiers de l'atelier, 49 portaient un mot K sur des arcs G17, émis par le post-processeur. Le simulateur les montre parfaits ; l'interpréteur de LinuxCNC les refuse.

Le même défaut, sur une vraie pièce

Un ancien fichier de guitare, dont le Job visait encore GRBL. Le post-processeur écrit K0.000 sur les 275 arcs du programme — pas un seul non nul, donc pas un seul qui porte la moindre information. GRBL les ignore, LinuxCNC s'arrête au premier. Résultat à l'écran : 5 segments au lieu de 2 173, et un bandeau rouge qui nomme la ligne et la raison. Le simulateur intégré, lui, l'aurait dessiné entier.

Choisir ce qu'on veut voir

Le Job entier est rarement ce qu'on cherche : on cherche l'opération dont on doute. Le greffon demande donc lesquelles tracer, les cases suivant l'état du Job. Sur une rosace de 18 opérations, tout donne 2 103 lignes de G-code et la seule opération de contour en donne 111.

Le Job n'est pas modifié pour autant. La voie évidente — désactiver les opérations puis les réactiver — laisserait un Job amputé si quoi que ce soit s'interrompait entre les deux, et ce Job-là finirait un jour posté pour de vrai. Le greffon restreint plutôt ce que le post-processeur considère : cocher les 18 redonne le fichier entier à deux lignes près, l'horodatage.

Une opération en échec ne passe plus

Une opération que FreeCAD n'a pas su recalculer garde le parcours de son dernier calcul réussi. Le post-processeur le poste sans broncher, et le tracé sort complet, crédible, périmé. C'est le défaut d'origine de ce projet, refait à l'intérieur même de l'outil censé le débusquer. Le greffon nomme désormais l'opération fautive et laisse choisir.

1 064lignes postées avec
l'opération cassée
964une fois réparée
— sans un mot d'écart
1 / 366opérations de l'atelier
déclenchent l'alarme

Ce dernier chiffre est la raison d'être du contrôle. Une alarme qui se trompe s'apprend à ignorer, et cesse alors de servir le jour utile : le seuil a donc été choisi sur un relevé des 366 opérations des 87 Jobs de l'atelier. L'état « à recalculer » touche 57 fichiers sur 87 — inutilisable. L'état « en échec » sort à une opération sur 366, et c'était la bonne.

Sous le capot

Comment c'est fait

La partie technique, repliée : à dérouler seulement si le sujet intéresse.

La chaîne, du fichier à l'écran deux couches

Un noyau qui ne connaît ni Qt ni OpenGL et se teste sans écran, et une interface qui ne fait aucune géométrie.

noyau — ni Qt ni OpenGL, se teste sans écran interface .ngc + ses sous-progr. rs274 sous-processus flux canonique arcs découpés numpy sommets, genre, avance, ligne OpenGL tracé, caméra Aucun G-code n'est analysé par le programme lui-même. 561 931 segments · 3,8 s à charger · fluide ensuite
Le noyau se teste sans écran ; l'interface ne fait aucune géométrie. C'est ce qui rend le parcours vérifiable en dehors de toute fenêtre.

Trois choses vérifiées avant d'être codées

⚖️

Sous-processus, pas import

LinuxCNC est en GPL-2.0. Importer son module Python serait une édition de liens et rendrait le dépôt dérivé. Un processus séparé qui échange du texte garde les deux indépendants — et le format canonique est stable et facile à lire.

🚫

Jamais -n 0

En mode « continuer », rs274 signale l'erreur, poursuit, et sort avec le code 0. Le parcours est tronqué sans que rien ne le dise. Le mode par défaut sort avec 1 : c'est la garantie contre l'échec silencieux, et elle ne se brade pas.

🗑️

Toujours un .var jetable

Sans -v, rs274 écrit ses paramètres persistants dans le fichier d'exemple de la configuration. Un G10 L2 dans un fichier regardé en passant polluerait toutes les lectures suivantes.

Chaque segment sait d'où il vient le mot N, et les tranches d'un million

Le lien entre le tracé et le code n'a rien coûté. print_nc_line_number() de LinuxCNC relit le mot N du texte source et le recopie dans la sortie canonique. En préfixant chaque ligne d'une copie par son propre numéro, chaque segment porte son origine — aucune analyse du G-code n'est nécessaire, et rien ne peut diverger.

Restait un manque : le mot N dit « ligne 42 », pas « ligne 42 de quel fichier ». Chaque fichier reçoit donc sa tranche d'un million.

programme principal 1 → 999 999 toolchange.ngc 1 000 000 → 1 999 999 atc_config.ngc 2 000 000 → 2 999 999 le 2 147ᵉ fichier 2 146 000 000 → … plafond du mot N 2 147 483 647 soit 2 147 fichiers (vérifié) Les dossiers sont recopiés numérotés dans un cache, et l'.ini repointé dessus le temps de l'interprétation : la configuration de la machine n'est jamais modifiée.
Le programme principal prend la première tranche, chaque sous-programme la suivante. Le plafond du mot N a été vérifié, pas supposé.
L'enlèvement de matière, et son oracle érosion, puis OpenCascade

La matière restante est décrite par une carte de hauteurs — une grille en X/Y, une altitude par case. C'est ce qu'il faut pour trois axes, où la matière se décrit entièrement par sa surface supérieure. Des voxels sauraient faire les contre-dépouilles, qu'une PrintNC ne fait pas, et coûteraient cent fois plus.

Le calcul ne parcourt pas les segments un par un — ce serait un appel numpy par segment, des dizaines de secondes sur un gros fichier. Il se ramène à une érosion en niveaux de gris :

l'axe de l'outil, tracé dans la grille r le profil de l'outil : droit, hémisphérique, en vé la surface = l'érosion de l'axe par le profil le coût ne dépend plus du nombre de segments, mais de la longueur parcourue
0,2 s pour les 562 000 segments de paquerette2.ngc, et 3 ms par image pendant le rejeu.

La carte de hauteurs donne un volume. En face, FreeCAD construit le solide balayé par l'outil et le retire du brut en BRep exact. Aucun code commun : ni la représentation, ni l'algorithme, ni la bibliothèque.

0 % 1 % 2 % 3 % case 0,20 mm 0,10 mm 0,05 mm contour raster hémisphérique écart entre la carte de hauteurs et le calcul BRep exact
Pour le contour et le raster, l'écart se divise par deux quand la case se divise par deux : c'est la signature d'une quantification de bord, pas d'un modèle faux — un modèle faux garderait son écart.
L'oracle a servi tout de suite

Le chiffre attendu de tête pour le contour fermé était faux de 5 % : c'était la formule d'un chemin ouvert. Un test qui ne vérifie que ce qu'on avait déjà en tête n'aurait rien vu.

Où est le dessus de la planche ?

Aucun programme ne dit où est le bois : il dit où va l'outil. Le premier jet prenait le point le plus haut usiné — c'est-à-dire le début du plongeon, qui part de la hauteur de garde. Sur 37 fichiers de l'atelier, il posait le dessus à +2, +3 ou +10 mm quand la coupe commence à zéro : une peau de bois fantôme, un volume gonflé d'autant — 50,9 cm³ annoncés contre 33,5 réels — et dix-sept fausses alarmes du contrôle des rapides.

Les pièges, et ce que chacun a laissé un test par piège
même centre A B l'arc attendu l'arc obtenu si l'on inverse les axes même rayon mêmes extrémités chemin inverse
Dans le plan XZ, ARC_FEED reçoit (fin_z, fin_x) et non (fin_x, fin_z). Un contrôle de centre ne voit rien : le test mesure donc le balayage déroulé.

Des uniformes ignorés en silence

PySide6 accepte setUniformValue(emplacement, 0.5) et ne fait rien : ni exception, ni erreur OpenGL. Tous les modes de coloration affichaient le premier. Les scalaires tiennent maintenant dans un vec4, et un test surveille.

Un cercle n'est pas une suite d'angles

Sans la limite centripète, découper un cercle plus fin ferait « ralentir » la machine, et un G61 ferait durer un cercle une éternité. Le test exige que la durée d'un cercle ne dépende pas de la finesse du découpage.

Le tracé à deux mètres et quart de sa place

Une version de LinuxCNC packagée multiplie les décalages d'outil par 25,4, et aucun réglage d'unités n'y change rien. Le T100 de la PrintNC, décalage Y de 88,75 mm, ressortait à 2 254,25 mm — sans un mot. Le facteur est donc mesuré au lancement, sur un programme d'essai d'une ligne, puis compensé. La mesure rend 1 depuis, et la compensation reste : rien ne garantit la version du prochain poste.

Écrire un G-code sans l'abîmer

Le panneau G-code est un vrai éditeur, et l'enregistrement est atomique : un fichier tronqué par une écriture interrompue ne se signale pas — il s'ouvre, s'interprète, se lance, et s'arrête au milieu du travail. Fins de ligne et saut final sont relevés sur les octets d'origine et reproduits : sur 306 fichiers de l'atelier, 4 sont en CRLF et 68 n'ont pas de saut final. Les réécrire « proprement » transformerait un chiffre modifié en un diff de cinq cents lignes, et ces fichiers sont sous git.

Honnêteté

Ce qu'il ne fait pas

Le code est public

Sous LGPL-2.1, sur github.com/atelierduverdier/visualiseur-gcode — y compris la suite de douze modules, et le contrôle qui éprouve le contrat entre le greffon et les entrailles de FreeCAD.

Deux de ces modules lisent des fichiers qui ne sont pas dans le dépôt : le programme de perçage du lit de ma machine et son jumeau développé à la main, pièces à conviction du contrôle le plus important du projet. Sans eux, ils échouent en nommant le fichier manquant — jamais en silence.