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.
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.
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()ysetAcceleration()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.xen 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.
- ProyectoConstruye un plóter de dibujo: dos ejes paso a paso
- ProyectoConstruye un robot pick and place con agarre verificado
- Ruta de aprendizajeAgarre y efectores finales: cómo sujetar piezas
- Ruta de aprendizajeControl de motores en robótica: ruta de aprendizaje
- Ruta de aprendizajeMovimiento de precisión con motores paso a paso
- Ruta de aprendizajeSeguimiento de trayectorias en robótica: ruta guiada
- Ruta de aprendizajeTracción holonómica: desplazamiento omnidireccional
Lecturas adicionales