Tutorial · Intermedio · 40 min de lectura

Perfiles de movimiento: aceleración trapezoidal y curva en S

Por qué una orden de posición en escalón hace perder pasos, cómo lo arregla un perfil trapezoidal y qué cuesta en tiempo limitar el tirón con una curva en S.

Introducción

Le ordenas a un motor que vaya a una posición y remotamente intentará llegar de inmediato. No rápido — de inmediato. La orden no contiene información sobre a qué velocidad, así que la única interpretación posible es «tan rápido como sea posible», y lo que pase después lo decide lo que se agote primero: el par, el límite de corriente, la tracción, o la capacidad del stepper para seguir el ritmo.

Un perfil de movimiento es esa información que falta. Convierte «ve a 100 mm» en un calendario —dónde debería estar el eje en cada instante entre ahora y la llegada— y le entrega al controlador un objetivo que se mueve a una velocidad que la máquina puede dar de verdad.

Esta es la diferencia entre un brazo robótico que llega y uno que llega y además deja de temblar.

Lo que realmente pide una orden de posición desnuda

Considera un escalón: en t = 0 el objetivo salta de 0 mm a 100 mm.

Para seguir eso exactamente, el eje necesitaría velocidad infinita, que requiere aceleración infinita, que requiere fuerza infinita. No puede, así que algo cede:

  • Un stepper al que se le ordena una frecuencia de pasos que su par no puede producir a esa velocidad pierde pasos y —al ir en lazo abierto— no tiene ni idea de que lo ha hecho. La posición ahora está mal de forma permanente. Por qué pasa, y por qué son siempre cuatro pasos a la vez.
  • Un motor DC con un lazo PID ve un error instantáneo enorme, satura su salida, acumula su término integral y se pasa de rosca.
  • Un servo se lanza a su velocidad máxima y llega con todo el mecanismo todavía en movimiento.

Ninguno de estos es un problema de ajuste. Todos son el mismo problema: la orden era físicamente imposible.

El perfil trapezoidal

La solución es ordenar velocidad, y cambiar la velocidad a un ritmo que el motor pueda sostener. Acelera a una tasa constante hasta una velocidad de crucero, la mantiene, y luego decelera a la misma tasa. Si representas la velocidad frente al tiempo obtienes un trapecio, y de ahí viene el nombre.

Tres números lo definen: la distancia d, una velocidad máxima v_max y una aceleración 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

Para un movimiento de 100 mm a 100 mm/s con a = 500 mm/s²: cada rampa dura 0,2 s y cubre 10 mm, dejando 80 mm de crucero, para un total de 1,2 s.

Aquí está todo el asunto como función del tiempo — la posición que tu lazo de control debería perseguir en el instante 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;
}

Fíjate en lo que esta función no es: no es un controlador. Genera un punto de consigna. Lo que tuvieras —un planificador de pasos de stepper, un lazo PID, una escritura a un servo— sigue haciendo lo de siempre. El perfil solo cambia lo que sigue.

El movimiento que pediste no siempre es el movimiento que obtienes

Esa rama de 2 * dAcc > d es el caso que la gente se encuentra primero y diagnostica mal.

Si el movimiento es más corto que la distancia necesaria para acelerar y volver a frenar, el eje nunca alcanza la velocidad que configuraste. Sube, llega al punto medio y baja inmediatamente — un triángulo, no un trapecio.

El umbral es d < v_max² / a. Para los números de arriba son 20 mm, así que todo movimiento más corto de 20 mm topa por debajo de 100 mm/s importa lo que pongas.

Gráfico de la velocidad frente al tiempo para tres movimientos con los mismos ajustes de perfil de 500 mm/s al cuadrado y una velocidad máxima de 100 mm/s. Un movimiento de 8 mm forma un triángulo que culmina a 63 mm/s tras 0.25 segundos, sin tocar nunca la velocidad máxima configurada, mostrada como línea discontinua. Un movimiento de 20 mm justo alcanza 100 mm/s en su ápice. Un movimiento de 60 mm forma un trapecio con una fase de crucero clara, que tarda 0.80 segundos.
Por debajo de 20 mm este eje se queda sin distancia antes que sin rampa. Subir el límite de velocidad no hace nada a esos movimientos — solo subir la aceleración. Descargar SVG

Por eso subir v_max en una máquina que hace muchos movimientos cortos no cambia nada medible. Los movimientos nunca estuvieron limitados por velocidad; estaban limitados por aceleración. Una impresora 3D haciendo relleno denso es el ejemplo cotidiano.

Las esquinas siguen siendo discontinuas

El perfil trapezoidal arregló la velocidad. Mira la aceleración y el problema simplemente se ha mudado.

En t = 0 la aceleración salta de 0 a 500 mm/s² al instante. En la cima de la rampa vuelve a 0 al instante. Cada una de esas es un escalón en la aceleración — y la derivada de la aceleración es el jerk, así que un escalón en la aceleración es un impulso de jerk infinito.

Infinito tampoco es un número que una máquina pueda producir. Lo que produce es:

  • Un golpe audible al inicio y al final de cada rampa.
  • Rebabado — las correas se estiran, los acoplamientos se cargan y la estructura tiene compliancia, así que un cambio brusco de fuerza la excita y luego oscila. En una impresora esto es el fantasma que ves junto a los rasgos nítidos.
  • Picos de par que disparan límites de corriente que la cifra de par medio decía que estaban bien.
Cuatro gráficos apilados frente al tiempo comparando un perfil trapezoidal y una curva en S para el mismo movimiento de 100 mm. Posición: ambas son formas de S suaves que llegan a 100 mm, la curva en S ligeramente por detrás. Velocidad: el trapecio tiene rampas rectas y esquinas afiladas, la curva en S tiene esquinas redondeadas y termina 0.1 segundos más tarde. Aceleración: el trapecio es una onda cuadrada que salta instantáneamente entre más y menos 500, la curva en S es un trapecio que sube y baja entre ellas. Jerk: la curva en S es una onda cuadrada acotada, mientras que el perfil trapezoidal se dibuja como cuatro flechas de impulso no acotadas en las esquinas.
El mismo movimiento bajo los dos perfiles. Cada fila es la derivada de la de arriba, y la discontinuidad no desaparece según derivas — solo baja por la pila hasta convertirse en un impulso. Descargar SVG

La curva en S

Un perfil en curva en S limita el jerk además de la aceleración. En vez de saltar a la aceleración completa, sube hasta ella a lo largo de un tiempo de jerk t_j = a_max / j_max, la mantiene, y luego baja. La curva de velocidad gana esquinas redondeadas — de ahí el nombre— y la aceleración se convierte en un trapecio propio.

Un movimiento completo en curva en S tiene siete fases: subir el jerk, mantener la aceleración, bajar el jerk, crucero, y la imagen especular para parar.

Lo que cuesta: exactamente un t_j

Esta es la parte que merece aprenderse de memoria, porque hace el intercambio concreto.

Cuando ambos perfiles alcanzan el mismo v_max y el mismo a_max, el movimiento en curva en S tarda más exactamente t_j — un tiempo de jerk, no dos, e independientemente de lo lejos que sea el movimiento:

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

Para el movimiento trabajado: 1,2 s pasa a ser 1,3 s. Una penalización del 8 % en este movimiento, y un porcentaje menor en los más largos, a cambio de un jerk acotado.

La razón de que sea uno y no dos: el segmento de aceleración de la curva en S es más largo, así que cubre más distancia antes de crucero, así que la fase de crucero se encoge y devuelve casi todo el tiempo. Solo el tiempo de jerk en sí es irrecuperable.

Ahí se esconde una restricción. La aceleración solo alcanza a_max si v_max ≥ a_max² / j_max. Por debajo de eso el movimiento tampoco llega a la aceleración completa, y obtienes un perfil de aceleración triangular — la misma historia de «se quedó sin distancia», una derivada más arriba.

«Jerk» en el firmware de impresoras no es jerk

Merece la pena saberlo antes de que te pongas a ajustar nada, porque el vocabulario engaña activamente.

El DEFAULT_XJERK clásico de Marlin no es la derivada de la aceleración. Es el cambio de velocidad instantáneo máximo permitido en una unión entre dos movimientos, en mm/s — una tolerancia de curva que deja al planificador tomar una esquina sin frenar hasta cero. Útil, pero otra magnitud, con el nombre equivocado y las unidades equivocadas.

El Marlin más reciente usa en su lugar Junction Deviation, que modela la esquina como un arco de círculo con una desviación dada en mm. Klipper usa square_corner_velocity — la velocidad a la que se toma una esquina de 90°. Los tres son respuestas a «¿cómo no paro en cada esquina?», y ninguno es un límite de jerk en sentido físico.

Así que si un post de foro te dice que bajes el jerk para que pare el rebabado, comprueba a qué magnitud se refiere. Bajar la velocidad de unión reduce el choque al girar; no acota da/dt dentro de un mismo movimiento.

Tu PID probablemente está bien

Si tienes un eje en lazo cerrado que se pasa de rosca y oscila en cada movimiento, el instinto es desajustarlo — bajar Kp, añadir derivativo, luchar contra el sobreimpulso.

Prueba antes a perfilar el punto de consigna.

Una entrada escalón le pide una salida infinita a un controlador PID. Su término de error empieza en la distancia completa del movimiento, el término derivativo ve un salto instantáneo, y el término integral acumula mientras la salida está saturada y el eje no puede responder. Desajustar hace que el controlador sea perezoso en todas partes para sobrevivir a un instante imposible.

Con un perfil, el error se mantiene pequeño durante todo el movimiento, porque el objetivo está en algún sitio donde el eje puede estar de verdad. Las mismas ganancias que eran inservibles contra un escalón suelen comportarse bien contra una rampa — y ahora el controlador solo está corrigiendo por carga y rozamiento, que es justo para lo que sirve. Puedes ver la diferencia en el simulador de PID comparando un punto de consigna escalonado con uno gradual.

Dónde te encuentras esto en un robot real

  • Steppers. setMaxSpeed() y setAcceleration() de AccelStepper te dan un perfil trapezoidal y nada más. No hay opción de curva en S; para eso generas el punto de consigna tú mismo.
  • Servos de hobby. Un SG90 tiene un controlador interno que no puedes ver ni ajustar, así que perfilar significa mover el ángulo ordenado gradualmente en vez de escribir el objetivo de una vez — la misma idea aplicada desde fuera.
  • Motores DC con encoders. Perfila el punto de consigna de posición y deja que el PID del encoder lo siga. Esta es la disposición donde perfilar más compensa.
  • Robots móviles. El mismo límite se aplica a linear.x en un puente de cmd_vel: ordenar un escalón de velocidad hace patinar las ruedas, lo que corrompe la odometría. Limita la tasa de la torsión.
  • Impresoras y CNC. Marlin, Klipper y GRBL planifican los tres movimientos trapezoidales con una regla de curvatura entre ellos.

Cuando va mal

Síntoma Normalmente
El stepper pierde posición bajo carga, en silencio Sin perfil — la tasa ordenada supera el par de arranque
La máquina golpea al inicio y al final de los movimientos Impulso de jerk trapezoidal; necesita curva en S o menos aceleración
Rebabado junto a rasgos nítidos Resonancia estructural excitada por escalones de aceleración
Los movimientos cortos ignoran el ajuste de velocidad Perfil triangular — limitado por aceleración, no por velocidad
Sobreimpulso y oscilación en cada movimiento Punto de consigna escalón dentro de un lazo cerrado; perfílalo antes de desajustar
Subir la aceleración ayuda y luego de golpe no Ahora limitado por par en vez de por perfil
La odometría deriva mucho durante las arrancadas Patinaje de ruedas por un escalón de velocidad; limita la tasa de la orden

Perfilar es la mejora grande más barata disponible para la mayoría de los sistemas de movimiento de hobby, porque cuesta una función y ningún hardware. El simulador de brazo robótico es un buen sitio para ver por qué importa al final de un eslabón largo, donde un pequeño escalón de aceleración en la base se convierte en un bamboleo visible en la pinza. En un robot móvil, el mismo perfil es lo que permite que un seguidor de trayectoria frene para una curva más cerrada que su radio de giro, en vez de no conseguir seguirla.

Explora el grafo

Forma parte de estos montajes

Proyectos y rutas de aprendizaje que incluyen este tutorial.

Lecturas adicionales

Referencias