Tutorial · Intermedio · 40 min

Profili di movimento: accelerazione trapezoidale e a curva S

Scopri perché un comando di posizione secco fa saltare i motori, come il profilo trapezoidale lo evita e quanto costa una curva S con jerk limitato.

Introduzione

Ordina a un motore di raggiungere una posizione e cercherà di arrivarci immediatamente. Non rapidamente: immediatamente. Il comando non contiene informazioni sulla velocità, quindi l’unica interpretazione possibile è «il più rapidamente possibile», e ciò che accade dopo dipende da ciò che finisce prima: coppia, limite di corrente, trazione o capacità del motore passo-passo di tenere il passo.

Un profilo di movimento è l’informazione mancante. Trasforma «vai a 100 mm» in una pianificazione — dove deve trovarsi l’asse in ogni istante tra adesso e l’arrivo — e fornisce al controllore un bersaglio che si muove alla velocità che la macchina è davvero in grado di fornire.

Questa è la differenza fra un braccio robotico che arriva e uno che arriva e continua a vibrare.

Che cosa chiede davvero un comando di posizione secco

Considera un passo: a t = 0 il bersaglio salta da 0 mm a 100 mm.

Per seguirlo esattamente, l’asse dovrebbe avere velocità infinita, che richiede accelerazione infinita, che richiede forza infinita. Non può, quindi qualcosa cede:

  • Un motore passo-passo riceve una frequenza di passi che la sua coppia non può produrre a quella velocità, perde passi e — funzionando in anello aperto — non ha idea di averlo fatto. La posizione ora è sbagliata in modo permanente. Perché succede e perché avviene sempre quattro passi alla volta.
  • Un motore CC con un ciclo PID vede un errore istantaneo enorme, satura l’uscita, carica il termine integrale e supera il bersaglio.
  • Un servomotore scatta alla velocità massima e arriva mentre l’intero meccanismo è ancora in movimento.

Nessuno di questi è un problema di regolazione. Sono tutti lo stesso problema: il comando era fisicamente impossibile.

Il profilo trapezoidale

La correzione consiste nel comandare la velocità e cambiarla a una velocità di variazione che il motore può sostenere. Accelera con un’accelerazione costante fino alla velocità di regime, mantienila e poi decelera con la stessa accelerazione. Riportando la velocità rispetto al tempo ottieni un trapezio, da cui il nome.

Tre numeri lo definiscono: la distanza d, la velocità massima v_max e un’accelerazione a.

t_accel = v_max / a                     time spent ramping
d_accel = v_max² / (2a)                 distance used by one ramp
t_total = v_max / a  +  d / v_max       whole move, if it reaches v_max

Per uno spostamento di 100 mm a 100 mm/s con a = 500 mm/s²: ogni rampa dura 0.2 s e copre 10 mm, lasciando 80 mm di regime, per un totale di 1.2 s.

Ecco tutto in funzione del tempo: la posizione che il ciclo di controllo deve inseguire all’istante t.

// Target position t seconds into a trapezoidal move of `d` mm.
float profilePosition(float t, float d, float vMax, float a) {
  float tAcc = vMax / a;
  float dAcc = vMax * vMax / (2 * a);

  if (2 * dAcc > d) {                      // too short to reach vMax
    float tPeak = sqrtf(d / a);            // triangular profile
    if (t >= 2 * tPeak) return d;
    if (t < tPeak) return 0.5f * a * t * t;
    float left = 2 * tPeak - t;
    return d - 0.5f * a * left * left;
  }

  float tCruise = (d - 2 * dAcc) / vMax;
  float tTotal  = 2 * tAcc + tCruise;
  if (t >= tTotal) return d;
  if (t < tAcc)           return 0.5f * a * t * t;
  if (t < tAcc + tCruise) return dAcc + vMax * (t - tAcc);

  float left = tTotal - t;
  return d - 0.5f * a * left * left;
}

Nota che cosa non è questa funzione: non è un controllore. Genera un riferimento. Qualunque cosa avessi prima — un pianificatore di passi per motore passo-passo, un ciclo PID, la scrittura su un servomotore — continua a fare il lavoro. Il profilo cambia soltanto ciò che viene seguito.

Il movimento richiesto non è sempre quello che ottieni

Il ramo 2 * dAcc > d è il caso incontrato per primo e mal diagnosticato.

Se il movimento è più corto della distanza necessaria per accelerare e decelerare di nuovo, l’asse non raggiunge mai la velocità configurata. Sale, raggiunge il punto medio e ridiscende immediatamente: è un triangolo, non un trapezio.

La soglia è d < v_max² / a. Per i numeri precedenti è 20 mm, quindi ogni movimento più corto di 20 mm raggiunge un massimo inferiore a 100 mm/s, qualunque cosa tu configuri.

Grafico della velocità rispetto al tempo per tre movimenti con le stesse impostazioni di profilo: 500 mm/s quadrato e velocità massima di 100 mm/s. Un movimento di 8 mm forma un triangolo con picco a 63 mm/s dopo 0.25 secondi, senza mai toccare la velocità massima configurata, mostrata come linea tratteggiata. Un movimento di 20 mm raggiunge esattamente 100 mm/s nel vertice. Un movimento di 60 mm forma un trapezio con una chiara fase di regime e dura 0.80 secondi.
Sotto i 20 mm questo asse esaurisce la distanza prima della rampa. Aumentare il limite di velocità non serve a quei movimenti: serve solo aumentare l'accelerazione. Scarica SVG

Ecco perché aumentare v_max su una macchina che esegue molti movimenti brevi non cambia nulla di misurabile. I movimenti non erano mai limitati dalla velocità, ma dall’accelerazione. Una stampante 3D che esegue un riempimento fitto è l’esempio quotidiano.

Gli angoli sono ancora discontinui

Il profilo trapezoidale ha risolto la velocità. Osserva l’accelerazione e il problema si è semplicemente spostato.

A t = 0 l’accelerazione salta da 0 a 500 mm/s² istantaneamente. In cima alla rampa torna subito a 0. Ciascuno di questi è un gradino nell’accelerazione — e la velocità di variazione dell’accelerazione è il jerk, quindi un gradino nell’accelerazione è un impulso di jerk infinito.

Nemmeno l’infinito è un numero che una macchina può produrre. Produce invece:

  • Un colpo udibile all’inizio e alla fine di ogni rampa.
  • Vibrazioni — le cinghie si allungano, gli accoppiamenti si caricano e la struttura ha cedevolezza, quindi una variazione improvvisa della forza la eccita e la fa oscillare in seguito. Su una stampante è l’alone (ghosting) che vedi accanto a spigoli netti.
  • Picchi di coppia che attivano i limiti di corrente, mentre la coppia media indicava che erano ampiamente rispettati.
Quattro grafici impilati rispetto al tempo che confrontano un profilo trapezoidale e uno a curva S per lo stesso movimento di 100 mm. Posizione: entrambi sono forme S fluide che raggiungono 100 mm, con la curva S leggermente in ritardo. Velocità: il trapezio ha rampe rettilinee e angoli netti, la curva S ha angoli arrotondati e termina 0.1 secondi dopo. Accelerazione: il trapezio è un'onda quadra che varia istantaneamente tra più e meno 500, mentre la curva S è un trapezio che passa da una all'altra. Jerk: la curva S è un'onda quadra limitata, mentre il profilo trapezoidale è rappresentato da quattro frecce di impulso illimitate agli angoli.
Lo stesso movimento con entrambi i profili. Ogni riga è la derivata di quella sopra e la discontinuità non scompare man mano che si differenzia: scende semplicemente lungo la pila finché diventa un impulso. Scarica SVG

La curva S

Un profilo a curva S limita il jerk oltre all’accelerazione. Invece di passare direttamente all’accelerazione piena, la aumenta gradualmente per un tempo di jerk t_j = a_max / j_max, la mantiene e poi la riduce. La curva di velocità acquisisce angoli arrotondati — da cui il nome — e l’accelerazione diventa a sua volta un trapezio.

Un movimento completo con curva S ha sette fasi: aumento del jerk, accelerazione costante, diminuzione del jerk, regime e la sequenza speculare per l’arresto.

Cosa costa: esattamente un t_j

Questa è la parte da ricordare, perché rende concreto il compromesso.

Quando entrambi i profili raggiungono lo stesso v_max e lo stesso a_max, il movimento con curva S dura esattamente t_j in più: un tempo di jerk, non due, indipendentemente dalla lunghezza del movimento:

trapezoidal   T = v_max/a + d/v_max
S-curve       T = v_max/a + d/v_max + t_j          where t_j = a_max / j_max

Per il movimento calcolato: 1.2 s diventano 1.3 s. Una penalità dell’8% su questo movimento e una percentuale inferiore su quelli più lunghi, in cambio di un jerk limitato.

Il motivo è uno e non due: il segmento di accelerazione della curva S è più lungo, quindi percorre più distanza prima della fase di regime, che si accorcia e restituisce gran parte del tempo. Solo il tempo di jerk è irreversibile.

C’è un vincolo nascosto. L’accelerazione raggiunge a_max soltanto se v_max ≥ a_max² / j_max. Sotto questa soglia il movimento non raggiunge nemmeno la piena accelerazione e ottieni un profilo di accelerazione triangolare: la stessa storia dello spazio esaurito, una derivata più in alto.

«Jerk» nel firmware della stampante non è jerk

È importante saperlo prima di regolare qualsiasi cosa, perché il vocabolario inganna attivamente.

Il DEFAULT_XJERK classico di Marlin non è la derivata dell’accelerazione. È la variazione massima istantanea di velocità consentita all’angolo tra due movimenti, espressa in mm/s: una tolleranza in curva che permette al pianificatore di percorrere un angolo senza decelerare fino a zero. Utile, ma è una grandezza diversa con il nome e le unità sbagliati.

Le versioni più recenti di Marlin usano invece Junction Deviation, che modella l’angolo come un arco di circonferenza con una deviazione data in mm. Klipper usa square_corner_velocity: la velocità con cui si percorre un angolo di 90°. Tutte e tre rispondono alla domanda «come faccio a non fermarmi a ogni angolo?» e nessuna è un limite di jerk nel senso fisico.

Se una discussione online ti dice di diminuire il jerk per fermare le vibrazioni, verifica quale grandezza intende. Diminuire la velocità agli angoli riduce gli scatti in curva; non limita da/dt all’interno di un singolo movimento.

Il tuo PID è probabilmente corretto

Se hai un asse in anello chiuso che supera il bersaglio e oscilla a ogni movimento, l’istinto è togliere regolazione: abbassa Kp, aggiungi derivata e combatti il superamento.

Prova prima a profilare il riferimento.

Un ingresso a gradino chiede a un controllore PID un’uscita infinita. Il termine di errore parte dalla distanza totale del movimento, il termine derivativo vede una variazione istantanea e quello integrale accumula mentre l’uscita è satura e l’asse non può rispondere. Togliere regolazione rende pigro il controllore ovunque, per sopravvivere a un unico istante impossibile.

Con un profilo, l’errore resta piccolo per tutto il movimento, perché il bersaglio si trova dove l’asse può davvero essere. Gli stessi guadagni inutilizzabili contro un gradino si comportano spesso bene contro una rampa e ora il controllore corregge soltanto carico e attrito, che è il suo compito. Puoi vedere la differenza nel simulatore PID confrontando un riferimento a gradino con uno graduale.

Dove incontri tutto questo su un robot reale

  • Motori passo-passo. setMaxSpeed() e setAcceleration() di AccelStepper forniscono un profilo trapezoidale e nient’altro. Non esiste un’opzione a curva S; per ottenerla devi generare tu il riferimento.
  • Servomotori hobbistici. Un SG90 ha un controllore interno che non puoi vedere né regolare, quindi profilare significa variare gradualmente l’angolo comandato invece di scrivere il bersaglio in una sola chiamata: la stessa idea applicata dall’esterno.
  • Motori CC con encoder. Profila il riferimento di posizione e lascia che il PID dell’encoder lo segua. È la configurazione in cui la profilazione rende di più.
  • Robot mobili. Lo stesso limite si applica a linear.x su un ponte cmd_vel: comandare un gradino di velocità fa slittare le ruote e corrompe l’odometria. Limita la velocità di variazione del twist.
  • Stampanti e macchine CNC. Marlin, Klipper e GRBL pianificano tutti movimenti trapezoidali con una regola per gli angoli.

Quando qualcosa va storto

Sintomo Causa più probabile
Il motore passo-passo perde la posizione sotto carico, in silenzio Nessun profilo: la frequenza comandata supera la coppia di richiamo
La macchina bussa all’inizio e alla fine dei movimenti Impulso di jerk trapezoidale; serve una curva S o un’accelerazione minore
Vibrazioni accanto a spigoli netti Risonanza strutturale eccitata da gradini di accelerazione
I movimenti brevi ignorano l’impostazione di velocità Profilo triangolare: limitato dall’accelerazione, non dalla velocità
Superamento e oscillazione a ogni movimento Riferimento a gradino in anello chiuso; profila prima di togliere regolazione
Aumentare l’accelerazione aiuta, poi improvvisamente non più Ora il limite è la coppia, non il profilo
L’odometria deriva in modo marcato durante le partenze Slittamento delle ruote causato da un gradino di velocità; limita la velocità di variazione del comando

Per la maggior parte dei sistemi di movimento hobbistici, la profilazione è il miglioramento ampio più economico disponibile, perché costa una funzione e nessun hardware. Il simulatore del braccio robotico è un buon posto per capire perché conta alla fine di un segmento lungo, dove un piccolo gradino di accelerazione alla base diventa un’oscillazione visibile al polso. Su un robot mobile è lo stesso profilo che permette a un inseguitore di percorso di rallentare per un angolo più acuto del proprio raggio di sterzata, invece di non riuscire a seguirlo.

Esplora il grafo

Fa parte di queste costruzioni

Progetti e percorsi di apprendimento che includono questo tutorial.

Per approfondire

Fonti