Un programma scritto per un robot ABB non gira su un KUKA, un Fanuc o un Universal Robots: va riscritto da capo. Ogni produttore tiene il suo linguaggio: ABB usa RAPID, KUKA il KRL (KUKA Robot Language), Fanuc il TP per i programmi da teach pendant e KAREL per la logica più articolata, Universal Robots l’URScript. Per i bracci robotici non esiste niente di simile alla IEC 61131-3, lo standard che ha unificato la programmazione dei PLC. Chi deve far girare la stessa cella su marche diverse paga questa frammentazione in ore di lavoro specialistico e in competenze che non si spostano da un controller all’altro.
Contesto
La frammentazione non è casuale. I linguaggi dei robot sono cresciuti attorno ai controller, e ogni controller ha il suo modello di esecuzione: gestione delle eccezioni, sistemi di coordinate, I/O digitali, primitive di movimento. RAPID e KRL sono linguaggi imperativi completi, con tipi e moduli; l’URScript è uno scripting in stile Python documentato nel manuale delle e-Series; il TP di Fanuc è un formato a istruzioni numerate pensato per il teach pendant, con KAREL come strato procedurale sotto. Le primitive di movimento si somigliano nei concetti — movimento giunto, movimento lineare, raccordo fra punti — ma cambiano nella sintassi, nelle unità, nella semantica delle zone di approssimazione e nel modo di esprimere un target (giunti, posa cartesiana, frame utente).
Da anni esistono strumenti di programmazione offline che scavalcano queste differenze. RoboDK e Visual Components tengono librerie di post-processor: si costruiscono traiettorie e logica in un ambiente neutro, e un post-processor dedicato al singolo controller emette il codice nativo — .mod/.prg per ABB, .src per KUKA, .ls/.tp per Fanuc, .script/.urp per Universal Robots. Visual Components elenca post-processor per più di venti marche. Sul fronte open source, ROS-Industrial porta ROS nell’automazione industriale con driver, modelli URDF e pacchetti MoveIt per i manipolatori dei produttori principali.
Architettura
I due mondi astraggono a livelli diversi, e qui sta la parte interessante.
Il modello a post-processor astrae a valle, sul codice sorgente. L’ambiente di authoring tiene una rappresentazione interna della traiettoria; il post-processor la traduce, serializzandola nel dialetto del controller di destinazione. Il programma generato finisce poi sul controller come qualsiasi altro programma scritto a mano: a runtime il robot è autonomo, l’ambiente esterno è servito solo a produrre il file. È il modello giusto quando la cella deve restare indipendente dopo il deploy.
Il modello ROS-Industrial astrae a monte, sull’interfaccia di comando. Qui non si genera codice nativo: un nodo joint_trajectory manda al controller comandi di posizione articolare, e un nodo robot_state pubblica posizione e stato letti dal controller. Lo scambio passa per il protocollo simple_message, descritto nella REP-I0006. Il vincolo di progetto del protocollo è dichiarato per esteso: deve essere decodificabile «con le capacità limitate del tipico linguaggio di programmazione robotico, senza saturare le risorse limitate del controller». Per questo sul controller gira un piccolo server scritto nel linguaggio nativo — RAPID, KRL, KAREL — che parla simple_message e trasforma i comandi in movimento. La pianificazione resta fuori, in MoveIt; il controller esegue.
Il punto critico
Il livello a cui si astrae decide cosa è portabile e cosa no.
Con i post-processor è portabile il programma: lo stesso progetto di traiettoria genera sorgenti per controller diversi, ma a runtime il comportamento dipende per intero da come ciascun controller interpreta quel sorgente — raccordo, accelerazioni, gestione delle singolarità. Due robot di marca diversa, partendo dalla stessa traiettoria di authoring, possono muoversi in modo nettamente diverso, perché la semantica del movimento sta nel firmware, non nel file. La traduzione è statica: quel che il post-processor non riesce a esprimere nel dialetto di arrivo non passa.
Con ROS-Industrial è portabile l’applicazione che pilota il robot, non il programma residente. La logica di alto livello — pianificazione, anticollisione, integrazione con la visione — la si scrive una volta sopra l’astrazione, e resta portabile finché c’è un driver per quel controller. Il prezzo è che il robot non è più autonomo: dipende da un calcolatore esterno e da un canale di comunicazione, e in una cella di produzione latenza e affidabilità pesano. Il driver nativo, poi, va scritto e mantenuto per ogni controller, ed è lì che le idiosincrasie di ciascun produttore tornano a galla.
In entrambi i casi resta un punto fisso da cui non si scappa: la semantica di movimento di basso livello — come un controller raccorda due segmenti, come gestisce una singolarità di polso, come tratta i limiti di giunto vicino al bordo dello spazio di lavoro — non si lascia catturare per intero in un modello comune, perché non è documentata in modo uniforme e in parte vive nel firmware proprietario. Qualsiasi astrazione multi-marca è esatta sulla cinematica e approssimata sulla dinamica.
Implicazioni
Chi progetta un livello di astrazione multi-marca non si chiede prima di tutto quali marche includere, ma a quale livello legare il modello comune. Astraendo sul sorgente si ottengono robot autonomi e traduzione statica, con il comportamento a runtime delegato al firmware. Astraendo sul comando si ottengono applicazioni portabili e controllo a runtime, al costo di un calcolatore esterno e di un driver da mantenere per ogni controller. Un livello intermedio — un modello neutro di traiettoria e I/O, con backend intercambiabili che a seconda del deploy emettono sorgente oppure pilotano via driver — si può costruire, ma moltiplica le superfici da testare: ogni primitiva va validata su firmware reale per ogni controller, perché la documentazione da sola non garantisce l’equivalenza. Un caso concreto di questo livello intermedio, applicato a un software di programmazione robotica multi-brand via web per ABB, KUKA, Fanuc e Universal Robots, è raccontato nell’insight di noze sulla startup YK-Robotics: https://www.noze.it/insights/yk-robotics/.
Limiti
Tutto questo riguarda la cinematica e il flusso di comando, non i tempi di ciclo né la sicurezza funzionale. La conformità alla ISO 10218 per i robot industriali e le funzioni di sicurezza certificate (arresti protettivi, limiti di velocità e di spazio) restano legate al controller e alla sua catena di sicurezza: nessun livello di astrazione le rende portabili, e nessuno dovrebbe tentare di farlo. Tradurre una traiettoria fra marche è un problema di geometria e di emissione di codice; la garanzia che il robot si fermi quando deve resta dove l’ha messa il produttore.
- https://github.com/ros-industrial/rep/blob/master/rep-I0006.rst
- http://wiki.ros.org/industrial_robot_client/design
- https://mirror.umd.edu/roswiki/Industrial.html
- https://s3-eu-west-1.amazonaws.com/ur-support-site/115824/scriptManual_SW5.11.pdf
- https://www.universal-robots.com/developer/urscript/
- https://robodk.com/blog/off-line-programming/
- https://www.visualcomponents.com/products/robot-offline-programming/
Immagine di copertina: Bracci robotici industriali gialli FANUC al lavoro in una linea di assemblaggio di una fabbrica — foto di Steve Jurvetson, CC BY 2.0 — https://commons.wikimedia.org/wiki/File:FANUC_Robot_Assembly_Demo.jpg