Tutorial · Intermedio · 25 min

Controllo orientato al campo: avanti resta avanti

Una matrice di rotazione e un'IMU rendono intuitivo il controllo di un robot olonomico. Esplora la matematica, la deriva e il bisogno di un pulsante di reset.

Il problema che incontrerai entro dieci secondi

Costruisci un robot mecanum, prendi il comando e spingi lo stick in avanti. Il robot si allontana da te. Bene.

Ora ruotalo di 180° e spingi di nuovo lo stick in avanti. Il robot avanza verso di te, perché avanti significa avanti per il robot e il robot ora è rivolto verso di te. Per uno o due secondi, il cervello di ogni pilota esegue la traduzione speculare, sbaglia e il robot colpisce qualcosa.

È già abbastanza grave su un robot a trazione differenziale, dove almeno il robot si muove sempre lungo il proprio muso. Su una base olonomica è molto peggio, perché ora il robot può essere rivolto in una direzione e muoversi in un’altra, senza alcun indizio visivo che mostri dove sia finito “di lato”. Dieci secondi di rotazione e nessuno nella stanza riesce a controllarlo.

La soluzione è una matrice di rotazione.

Due sistemi di riferimento, una trasformazione

Ci sono due modi per interpretare lo stick:

  • Orientato al robot (robot-centrico, relativo al robot). Lo stick è un comando nel sistema di riferimento del robot stesso — base_link, se usi ROS. Spingi in avanti e il robot si muove lungo il proprio muso.
  • Orientato al campo (field-centrico, relativo al campo). Lo stick è un comando nel sistema di riferimento del pavimento. Spingi in avanti e il robot si sposta verso nord, ovunque sia rivolto il suo muso.

La trazione comprende soltanto il sistema di riferimento del robot: la cinematica mecanum è scritta in quel sistema. Il controllo orientato al campo significa quindi ruotare il comando del pilota nel sistema di riferimento del robot prima che la cinematica lo veda.

Se l’orientamento del robot è θ (misurato in senso antiorario rispetto all’asse x del campo), ruota il comando di −θ:

vx_robot = vx_field · cos(θ) + vy_field · sin(θ)
vy_robot = −vx_field · sin(θ) + vy_field · cos(θ)

Meno theta, non theta. Se sbagli il segno, ottieni un robot che sembra corretto mentre punta in avanti e si muove nella direzione esattamente opposta dopo aver ruotato di 90°, un problema che può far impazzire per dieci minuti.

La rotazione non viene toccata. ω significa la stessa cosa in entrambi i sistemi di riferimento — una rotazione è una rotazione — quindi passa senza modifiche.

Tutto, in codice

#include <math.h>

// stickX: forward on the stick, positive = away from the driver (field +x)
// stickY: left on the stick,    positive = to the driver's left (field +y)
// stickW: twist, positive = counter-clockwise
void driveFieldOriented(float stickX, float stickY, float stickW) {
  float theta = imuYawRadians() - headingOffset;   // see "the reset" below

  float c = cosf(theta);
  float s = sinf(theta);
  float vx =  stickX * c + stickY * s;
  float vy = -stickX * s + stickY * c;

  driveMecanum(vx, vy, stickW);   // the inverse kinematics, unchanged
}

Sei righe, e sono la differenza tra un robot che le persone possono controllare e uno che non possono. Nota che driveMecanum() non saprà mai nulla di tutto questo: l’orientamento al campo è un cappello che metti sul comando, non una modifica alla trazione.

Come ottenere θ

Ti serve un angolo di orientamento. Ci sono tre modi per ottenerlo, in ordine crescente di quanto tempo rimangono affidabili.

Fonte Deriva Costo Verdetto
Solo odometria delle ruote Rapida — ogni slittamento è un errore di orientamento e i rulli mecanum scivolano per progetto Gratuita Accettabile solo per un breve percorso
Giroscopio MPU6050, integrato In genere 1–3° al minuto dopo la calibrazione ~£2 Adatto a un incontro di due minuti, non a un’ora
IMU a 9 DoF con fusione del magnetometro (BNO055, ICM-20948) Limitata, ma sensibile ai campi magnetici al chiuso ~£20 La scelta giusta se il percorso è lungo

L’orientamento derivato da un giroscopio è un integrale, quindi il bias diventa deriva in modo lineare:

// Integrate yaw rate, with the bias you measured while it sat still.
float rate = gyroZ() - gyroBiasZ;             // rad/s
if (fabsf(rate) < 0.004f) rate = 0.0f;        // deadband: kill the last of the creep
yaw += rate * dt;

Due dettagli contano più della scelta del sensore:

  • Misura il bias a ogni avvio, con il robot fermo. Fai la media di 500 campioni in uno o due secondi prima di qualsiasi movimento. Un MPU6050 grezzo senza rimozione del bias deriva di decine di gradi al minuto; con la rimozione, di un numero di una sola cifra.
  • Applica una zona morta alla velocità angolare, non all’angolo. Applicarla all’angolo fa perdere le rotazioni reali lente. Applicarla alla velocità scarta soltanto il rumore di fondo, che è esattamente ciò che viene integrato e diventa deriva.

Un accelerometro non può aiutarti qui. Fornisce rollio e beccheggio osservando la gravità, motivo per cui un filtro complementare corregge egregiamente l’inclinazione, ma la gravità è parallela all’asse di orientamento, quindi non dice nulla sul verso in cui sei rivolto. L’orientamento richiede un magnetometro, oppure deve derivare.

Il reset, che non è opzionale

Due fattori impongono uno zero manuale:

  1. Deriva. Dopo pochi minuti l’idea di nord del robot e quella del pilota si separano e la correzione diventa il problema.
  2. Orientamento iniziale. Lo zero della IMU corrisponde alla direzione in cui il robot puntava all’accensione, che raramente è quella da cui si trova il pilota.

Mantieni quindi un offset e un pulsante:

float headingOffset = 0.0f;

void resetFieldHeading() {          // bind to a button the driver can hit blind
  headingOffset = imuYawRadians();  // "whatever you are pointing at is now forward"
}

La convenzione verso cui tutti convergono: punta il robot in direzione opposta al pilota, premi il pulsante e guida. Ci vuole mezzo secondo e risolve entrambi i problemi in una volta. Ogni robot olonomico teleoperato serio ha questo pulsante e ogni squadra che lo ha omesso lo ha aggiunto dopo la prima partita.

Controllo orientato al campo anche per l’autonomia

Non è solo un aiuto alla guida. Qualsiasi comportamento autonomo il cui comando sia espresso naturalmente rispetto al pavimento richiede la stessa trasformazione:

  • “Muoviti di 300 mm verso l’obiettivo” — l’obiettivo è nelle coordinate del campo, quindi lo è anche il comando.
  • “Sposta lateralmente per mantenere centrato il bersaglio della telecamera mentre lo si orbita” — l’orbita è nel riferimento del campo, la rotazione in quello del robot e il controllo orientato al campo ti permette di scrivere entrambe sulla stessa riga.
  • Qualsiasi elemento a valle di un pianificatore di percorsi, che pianifica su una mappa e quindi nel riferimento del campo.

In ROS è la trasformazione odom → base_link a svolgere lo stesso compito: per questo esiste TF2 e perché cmd_vel è definito esplicitamente in base_link. Il controllo orientato al campo è la versione implementata manualmente di una ricerca che altrimenti chiederesti a TF2.

Come si vede

Il simulatore della trazione mecanum ha una sola manovra che rende il punto senza bisogno di parole: tieni lo stick in avanti, continua a ruotare e cambia sistema di riferimento.

Sistema di riferimento Traccia del robot
Orientato al robot Un rosone. Il comando ruota con il corpo, quindi il robot si avvolge su stesso e non va da nessuna parte in particolare.
Orientato al campo Una linea retta, mentre il corpo ruota per tutta la sua lunghezza.

Stesso stick, stesse ruote, stessa cinematica. L’unica differenza sono sei righe di trigonometria.

Risoluzione dei problemi

Sintomo Causa Soluzione
Corretto a 0°, esattamente sbagliato a 180° Stai ruotando di +θ anziché di −θ Inverti il segno; i termini con il seno si scambiano
Si muove a 90° rispetto allo stick x e y sono scambiati oppure la IMU è montata ruotata Controlla la marcatura dell’asse della IMU rispetto al muso del robot
Funziona per un minuto, poi diventa lentamente sbagliato Deriva del giroscopio Calibrazione del bias all’avvio, zona morta sulla velocità e pulsante di reset
Salta in modo brusco vicino a una parte della stanza Magnetometro vicino a un motore, un altoparlante o acciaio Sposta la IMU oppure elimina il magnetometro e accetta la deriva del giroscopio
Il pulsante di reset non fa nulla Offset applicato alla variabile sbagliata oppure letto prima che la IMU sia pronta Stampa θ e l’offset insieme; subito dopo un reset devono essere uguali
Il robot scivola lateralmente quando lo stick è centrato Non è un problema di sistema di riferimento — è la velocità delle ruote Verifica che ogni ruota si stia davvero fermando

Prossimo passo

L’orientamento al campo fa sì che il comando significhi la cosa giusta. Il controllo ad anello chiuso della velocità delle ruote fa sì che le ruote lo eroghino davvero: su una base olonomica i due aspetti formano una coppia, perché un robot i cui motori cedono in modo diseguale ha un orientamento errato prima che la IMU possa dire la sua.

Esplora il grafo

Fa parte di queste costruzioni

Progetti e percorsi di apprendimento che includono questo tutorial.

Per approfondire

Fonti