Simulador de tracción Mecanum: desplazamiento y deriva
Conduce un robot holonómico en lateral, reduce la adherencia y observa cómo sus encoders insisten en que todo va bien. Luego instala una rueda al revés.
- Categoría
- Robots autónomos
- Tiempo
- 20–40 min
- Plataforma
- Browser · Arduino · ESP32
01 / Empieza aquí
Introducción
Una rueda Mecanum solo transmite fuerza a 45 grados, lo que permite el movimiento lateral pero compromete la adherencia. Este laboratorio resuelve el balance dinámico de fuerzas con límites de fricción reales, integrando los encoders de forma independiente al suelo para ilustrar cómo la odometría a bordo diverge de la posición real sin que el robot pueda advertirlo.
Live lab / Holonomic motion
Mecanum drive simulator
Drive a square sideways without ever turning, then take the grip away and watch the encoders keep insisting it worked. Fit one wheel backwards and the same code drives a spiral.
Left: a top-down view of the floor. The dashed outline is the manoeuvre as commanded, the solid line is where the robot actually went, and the dotted line is where its own encoders believe it went. The robot is drawn at its final pose, with each wheel's roller hand hatched — on a correctly built base those hatches point at the centre and make an X. Right: the four wheel rim speeds against time, with the motor's free speed marked. A trace sitting flat on that line is a wheel that has run out of motor; slip shows up on the left instead, as the gap between the solid line and the dotted one.
- Commanded manoeuvre
- Where the robot went
- Where the encoders say
- Motor free speed
- Missed home by
- 0 mm
- Odometry drift
- 0 mm
- Heading change
- 0.0°
- Ground lost to slip
- 0 mm
- Command clipped
- 0%
- Encoder disagreement
- 0.000
Every action has a button above. If you prefer the keyboard, focus the plots and press P for the next preset, M for the next manoeuvre, O to switch between robot- and field-oriented, W to fit the front-left wheel backwards and back, R to reset and F for full screen; sliders respond to the arrow keys.
Controles
Cada control reproduce la maniobra completa al cambiar la entrada, así que las trayectorias acompañan a un deslizador mientras lo arrastras. No hay nada que arrancar.
| Control | Qué cambia |
|---|---|
| Preset | Cinco situaciones trabajadas: una que funciona y cuatro formas de dejar de funcionar |
| Manoeuvre | Lo que pide el conductor: un cuadrado desplazándose de lado, un cuadrado girando, una carrera diagonal, o conducir mientras gira |
| Stick speed / Stick spin | Con cuánta fuerza se empuja la orden |
| Stick frame | Orientado al robot, u orientado al campo con una IMU |
| Over the limit | Escala la orden entera por la peor rueda, o recorta cada rueda por su cuenta |
| Wheel top speed | La velocidad libre de los motores en la llanta: un techo duro, patine o no |
| Floor grip μ | El hormigón pulido ronda 0.8; un suelo de gimnasio polvoriento o lubricante derramado, 0.25 |
| Wheel fit | Las cuatro correctas, o la delantera izquierda montada al revés |
El panel de la izquierda es el suelo. La discontinua es la maniobra tal como se comandó, la continua es dónde fue realmente el robot, y la punteada es dónde creen sus propios encoders que fue. El panel de la derecha son las cuatro velocidades de llanta frente al tiempo, con el techo del motor marcado. Una traza plana sobre esa línea es una rueda que se ha quedado sin motor; el patinaje aparece en el panel de la izquierda, como el hueco entre la línea continua y la punteada.
Teoría
Una rueda mecanum solo puede meter fuerza en el suelo a lo largo de los ejes de sus rodillos. En cualquier otra dirección, el rodillo simplemente gira y no se transmite nada. Esos ejes están a 45° respecto a la rueda, así que la fuerza de una rueda sobre el suelo está fijada a una única línea en el suelo y ningún par de motor la mueve.
Cuatro de esas líneas, de mano alterna, suman cualquier cosa. Escribe la velocidad de llanta de la rueda frente al twist del chasis ξ = (vx, vy, ω) y obtienes una fila por rueda:
vᵢ = vx + sᵢ·vy + (sᵢ·xᵢ − yᵢ)·ω sᵢ = ±1, the roller hand
Apila las cuatro filas en una matriz A y toda la tracción es v = A·ξ. Tres consecuencias, y el
laboratorio existe para hacer visible cada una:
Cuatro ecuaciones, tres incógnitas. Un chasis rígido cuyas cuatro ruedas agarran no puede
producir velocidades de llanta arbitrarias: la ecuación de más dice FL + FR = RL + RR, siempre. El
residuo de esa comprobación es un detector de patinaje libre que puedes calcular solo con encoders.
Dispara con patinaje asimétrico —una rueda en el aire, una rueda sobre un charco, una rueda en la
esquina equivocada— y es completamente ciego cuando las cuatro patinan a la vez, que es la razón por
la que la odometría mecanum se degrada en silencio.
La tracción cuesta 1/√2. La fuerza útil del motor va a lo largo de la dirección de rodadura, pero la fuerza real sobre el suelo es √2 veces esa, apuntando a lo largo del eje del rodillo, y la fricción acota el vector entero. Así que el límite por rueda es μN/√2 y el techo de aceleración del robot es:
a_max = μ·g / √2
Con μ = 0.85 eso son 5.9 m/s² frente a 8.3 m/s² para el mismo robot con ruedas normales. La masa se cancela en ambos casos, así que el lastre no cambia nada: lo contrario que un robot que empuja, donde el peso es toda la estrategia.
Las diagonales también cuestan 1/√2. Una orden a 45° mete vx + vy en dos ruedas y cero en las
otras dos, así que el par ocupado satura mientras el robot solo se mueve a V_MAX / √2. Motores más
rápidos mueven ese techo; nada lo elimina.
El desarrollo completo, incluida la inversa de odometría, está en cinemática de ruedas mecanum.
Algoritmo
Cada paso de 5 ms, en este orden. Las dos integraciones de pose del final están deliberadamente separadas: esa separación es la lección de odometría.
- Lee el joystick para este punto de la maniobra.
- Rota al marco del robot si está orientado al campo:
vx' = vx·cos θ + vy·sin θ,vy' = −vx·sin θ + vy·cos θ. El modo orientado al robot se salta esto por completo. - Cinemática inversa —
v = A·ξ, usando la matriz en la que el firmware cree, que siempre es la correcta. Una rueda mal montada no es algo que el firmware pueda saber. - Limita — escala el vector entero por la peor rueda, o recorta cada rueda por su cuenta.
- Retardo de rueda — cada llanta persigue su objetivo con una respuesta de primer orden de 0.1 s, porque un lazo de velocidad es bueno, no instantáneo.
- Lo que piden las ruedas — cinemática directa por mínimos cuadrados sobre las velocidades de llanta, usando la matriz del robot que realmente se construyó.
- Resuelve las fuerzas que harían que el chasis coincidiera, y luego aplica dos techos en orden: el del motor (siempre hubo solo tanto par) y el del suelo (μN/√2 por rueda).
- Lo que el suelo se niegue a hacer hace girar la llanta. Ese excedente acelera la rueda fuera de su velocidad comandada, que es patinaje, y es el único síntoma de patinaje que un encoder puede informar alguna vez.
- Integra la verdad a partir de las fuerzas que se aplicaron realmente.
- Integra la odometría a partir de las velocidades de llanta, a través de la matriz del firmware, porque el encoder está atornillado a la rueda, no al suelo.
Ahí no hay nada que busque patinaje ni que lo inserte. El patinaje es el paso 7 negándose a una fuerza, y la deriva que ves es que el paso 10 nunca se entera.
Experimentos guiados
Cada uno aísla una única variable. Hazlos en orden; se construyen unos sobre otros.
1. La cosa por la que compraste ruedas mecanum
Carga A square that closes. El robot avanza un metro, gira a la derecha un metro, vuelve atrás y a la izquierda, y regresa a casa a 17 mm de donde empezó con la lectura de rumbo sin moverse nunca de 0.0°. Ahora cambia la maniobra a square, turning at the corners: el mismo cuadrado, conducido como tiene que conducirse un robot de tracción diferencial. También cierra, a 4 mm. Recuerda que las dos cosas funcionan aquí.
Qué observar: el cuadrado desplazándose de lado traslada en dos ejes y gasta cero rumbo en ello. Ninguna tracción diferencial puede intentar eso.
2. Quítale el suelo
Arrastra floor grip de 0.85 hasta 0.25, manteniendo el cuadrado con desplazamiento lateral. Haz lo mismo con el cuadrado girando.
| Maniobra | Rumbo con μ = 0.85 | Rumbo con μ = 0.25 |
|---|---|---|
| Cuadrado desplazándose de lado | 0.0° | 0.0° |
| Cuadrado girando | 0.2° | decenas de grados, y a veces una inversión completa |
Qué observar: vigila el rumbo, no la distancia. Los dos robots deslizan y los dos fallan la vuelta a casa; el que se desplaza de lado falla mientras sigue apuntando exactamente donde empezó, porque nunca ordenó una rotación. El que gira pierde el rumbo y luego conduce el siguiente tramo en dirección equivocada, que es como un patinaje pequeño se convierte en un error grande. Cada giro es una oportunidad nueva de perder el hilo, y la base holonómica sencillamente no las acepta.
Las distancias en este experimento se mueven entre ejecuciones con distintos ajustes, y esa es la respuesta honesta y no un fallo: un robot deslizando sobre las cuatro ruedas es un sistema de adherencia-deslizamiento y no cae dos veces en el mismo sitio. El rumbo no tiene ese problema.
3. Mira mentir a los encoders
Carga Same square, greasy floor y mira las dos líneas del panel izquierdo. La línea punteada de odometría dibuja un cuadrado pulcro; la continua no. El robot termina a 225 mm de casa mientras que sus propios encoders lo ponen a 133 mm en otro sitio, después de 1.27 m de suelo que pasó por debajo de las ruedas sin mover el robot en absoluto.
Ahora vigila la lectura de Encoder disagreement. Se queda en 0.000 todo el rato.
Qué observar: la comprobación de residuo libre —FL + FR debería ser igual a RL + RR en cualquier chasis rígido— caza una rueda que patina y es completamente ciega a las cuatro patinando a la vez. Esa ceguera es exactamente la razón por la que la odometría mecanum falla en silencio. Ponle una IMU, o ruedas pasivas, y deja de fiarte de los encoders de tracción para la posición.
4. El techo √2
Carga Diagonal dash. La velocidad del joystick es 0.60 m/s y la velocidad máxima de rueda también, así que la orden debería ser alcanzable. No lo es: la orden se recorta el 91 % de la maniobra y el robot se queda en 0.424 m/s, que es 0.60/√2 hasta tres decimales, alcanzado exactamente.
Qué observar: en el panel derecho, dos trazas están planas en cero mientras dos están pegadas al
techo. Una orden a 45° mete vx + vy en dos ruedas y nada en las otras dos, así que el par ocupado
satura en V_MAX / √2. Sube la velocidad máxima de rueda y el techo se mueve con ella: el 71 %
nunca cambia.
5. Escalar frente a recortar
Cambia la maniobra a drive while spinning, empuja stick spin a 240 °/s y alterna Over the limit entre los dos ajustes. La trayectoria cambia de forma.
Qué observar: escalar renuncia a velocidad en todos los ejes y mantiene la dirección. Recortar mantiene la velocidad hacia delante y pierde el 27 % de la rotación: el robot gira 127° a lo largo de la maniobra en vez de 92°, así que se enrosca de otra manera a la que se le pidió. Luego vuelve a la carrera diagonal e intenta el mismo cambio: no pasa nada, porque las ruedas ociosas ya estaban dentro del límite. Así es como este fallo sobrevive a las pruebas.
6. Monta una rueda al revés
Carga One wheel fitted backwards, o pulsa W en las gráficas. Nada del código ha cambiado.
| Las cuatro correctas | Delantera izquierda espejada | |
|---|---|---|
| Se queda lejos de casa por | 17 mm | más de un metro |
| Cambio de rumbo | 0.0° | decenas de grados |
| Suelo perdido en patinaje | 15 mm | varios metros |
| Discrepancia de encoders | 0.000 | ≈ 0.28 |
Qué observar: el robot ya no está haciendo nada parecido a lo que se le dijo, y esta vez la lectura de residuo sí dispara, grande y constante en lugar de a ráfagas. Fíjate en qué columna tiene números exactos y cuál no: con una rueda peleándose contra las otras tres el robot desliza de forma continua, así que su pose final es caótica. El residuo es el número que sobrevive, y por eso justamente es el que merece una línea de telemetría. Es el único síntoma que puedes leer en un robot real sin IMU y sin referencia externa. Mira también el robot dibujado: el rayado de la esquina espejada apunta al revés, y las cuatro líneas de rodillos ya no forman una X.
7. Orientado al campo, en una tecla
Carga Field-oriented while spinning, y luego pulsa O para volver a orientado al robot y O otra vez para regresar.
Qué observar: en modo orientado al robot, mantener el joystick hacia delante mientras se gira dibuja una roseta: el robot recorre 2.34 m de camino y acaba a 0.30 m de donde empezó, es decir, el 13 % de su esfuerzo fue a alguna parte. En modo orientado al campo, el mismo joystick recorre 2.03 m y acaba a 2.03 m de distancia: una recta muerta, 100 %, con el cuerpo girando en todo el recorrido. Seis líneas de trigonometría separan los dos, y es la diferencia entre un robot que una persona puede conducir y uno que no.
Qué deberías observar
Siete cosas, juntas:
- Hacia delante es gratis; de lado y en diagonal no. Cada rueda contribuye del todo al movimiento hacia delante. Una diagonal usa la mitad.
- Dos penalizaciones de raíz de dos, del mismo 45°. Velocidad en diagonal, y tracción en todas las direcciones. Ninguna se compra con motores más grandes.
- La masa se cancela. El techo de aceleración es μg/√2 pese lo que pese el robot, que es lo contrario que un robot que empuja.
- Lo holonómico gana a lo diferencial cuando el suelo está mal, porque los giros son de donde viene el error.
- La odometría es el precio. No es un problema de ajuste, ni de un encoder mejor: el patinaje de la rueda es cómo funciona la tracción.
Llevarlo a hardware
| En este laboratorio | En un robot real |
|---|---|
| Un deslizador de agarre | Un suelo, y un número que descubres empujando el robot con una báscula de equipaje |
| Las ruedas alcanzan su velocidad comandada con 0.1 s de retardo | Solo si construiste un lazo de velocidad. En lazo abierto, las razones derivan con la batería |
| Integración de odometría perfecta e instantánea | 50–100 Hz, con la cuantización del encoder y un desbordamiento de micros() esperándote |
| Motores idénticos | De 3 a 8 % distintos de fábrica, y más distintos en caliente |
| Un μ limpio para todo el suelo | Polvo, una junta en el vinilo, un cable: el agarre local varía más de lo que esperas |
| El ajuste de ruedas es un desplegable | El ajuste de ruedas son cuatro tornillos y la comprobación de la X, y te lo vas a equivocar una vez |
El laboratorio vale los veinte minutos sobre todo por el experimento 6. Montar una rueda al revés no cuesta nada aquí y medio día en el banco, y es el fallo que con más probabilidad vas a construir.
Código fuente
Toda la tracción son estas dos funciones. La geometría vive en exactamente un sitio.
const float LX = 0.075f; // half the wheelbase, m (wheel centre to wheel centre / 2)
const float LY = 0.085f; // half the track, m
const float K = LX + LY;
const float R = 0.0485f; // wheel radius, m
const float V_MAX = 0.60f; // rim speed the motors can actually hold, m/s
// Inverse kinematics + saturation. vx forward, vy LEFT, omega counter-clockwise.
void driveMecanum(float vx, float vy, float omega) {
float w[4] = {
vx - vy - K * omega, // front left
vx + vy + K * omega, // front right
vx + vy - K * omega, // rear left
vx - vy + K * omega, // rear right
};
float peak = 0;
for (int i = 0; i < 4; i++) peak = max(peak, fabsf(w[i]));
if (peak > V_MAX) { // SCALE, never clip
float s = V_MAX / peak;
for (int i = 0; i < 4; i++) w[i] *= s;
}
for (int i = 0; i < 4; i++) wheelLoop[i].target = w[i]; // hand to the velocity loops
}
// Forward kinematics for odometry, and the free diagnostic.
float updateOdometry(const float rim[4], float dt) {
float vx = ( rim[0] + rim[1] + rim[2] + rim[3]) * 0.25f;
float vy = (-rim[0] + rim[1] + rim[2] - rim[3]) * 0.25f;
float omega = (-rim[0] + rim[1] - rim[2] + rim[3]) * 0.25f / K;
theta += omega * dt;
poseX += (vx * cosf(theta) - vy * sinf(theta)) * dt;
poseY += (vx * sinf(theta) + vy * cosf(theta)) * dt;
// Four equations, three unknowns. On any rigid, gripping chassis this is zero.
// Large and steady => a wheel is in the wrong corner. Bursty => something slipped.
return (rim[0] + rim[1]) - (rim[2] + rim[3]);
}
El desarrollo de esas cuatro filas, y por qué funciona el residuo, está en
cinemática de ruedas mecanum. Hacer que
wheelLoop[i].target signifique algo es el
control de velocidad de rueda en lazo cerrado. Construir
la cosa es el robot omnidireccional con ruedas mecanum.
Lista de hardware
Componentes
- Cuatro ruedas Mecanum (dos de cada mano, nunca cuatro idénticas)
- Cuatro motorreductores con inversión de giro independiente
- Cuatro encoders de cuadratura para sincronizar velocidades
- Superficie de rodadura plana, rígida y limpia
Explora el grafo
Dónde se usa este simulador
Los proyectos, rutas de aprendizaje y tutoriales que se basan en este laboratorio.
Sigue construyendo
Descargar recursos
Usa estas referencias de la página mientras trabajas en el proyecto. Los paquetes descargables del proyecto se añadirán solo cuando se publiquen su código fuente y su versión.
Preguntas comunes
Preguntas frecuentes
¿Por qué mi robot gira sobre sí mismo cuando le ordeno avanzar de lado?
Casi siempre se debe a una rueda montada en la esquina equivocada. Un juego Mecanum incluye dos ruedas de mano izquierda y dos de mano derecha, cuya orientación debe alternarse alrededor del chasis. Si colocas una rueda invertida, su vector de fuerza apunta en oposición al movimiento lateral provocando un arco con rotación parásita. El avance frontal parecerá normal, lo que despista al depurar. Comprobación visual rápida: sitúate sobre el robot, mira hacia abajo y sigue la línea superior de los rodillos; las cuatro líneas deben converger hacia el centro dibujando una X.
¿Por qué el robot es más lento en trayectorias diagonales a 45°?
Porque un avance a 45° exige la máxima velocidad a dos ruedas diagonales mientras deja a las otras dos completamente detenidas. Tu velocidad diagonal máxima queda limitada a la velocidad de rueda dividida por raíz de dos (~71 % de la velocidad rectilínea). Motores más veloces elevan el umbral global, pero la penalización geométrica de 1/√2 se mantiene invariable.
¿Por qué la odometría con ruedas Mecanum acumula tanto error?
Porque los encoders miden el giro de las ruedas, no el avance real sobre el suelo. En una base Mecanum, los rodillos pasivos deslizan deliberadamente por diseño para permitir el movimiento lateral. Cada milímetro de adherencia perdido se contabiliza en el encoder como desplazamiento inexistente. En suelo resbaladizo, el robot puede terminar a cientos de milímetros de su meta mientras los encoders afirman que completó el recorrido perfecto.
¿Es mejor escalar el vector de consigna completo o limitar cada rueda individualmente?
Siempre escala el vector completo. Limitar cada motor de forma aislada con constrain() conserva la magnitud de velocidad a costa de alterar drásticamente el rumbo. Escalar preserva la dirección deseada reduciendo proporcionalmente todos los ejes. En diagonales puras ambos métodos coinciden numéricamente, por lo que el error suele pasar desapercibido en pruebas preliminares.
¿Un robot más pesado consigue mejor tracción con ruedas Mecanum?
No en lo relativo a aceleración traslacional. Mayor masa incrementa la fuerza normal de fricción en la misma proporción en que aumenta la inercia a vencer, cancelándose ambos efectos: la aceleración máxima es μ·g / √2 sin importar el peso del vehículo. El lastre solo empeora la respuesta dinámica y agota antes la batería.
¿Refleja este modelo el comportamiento de una plataforma física?
La cinemática es rigurosa: utiliza la misma matriz 4×3 que cualquier implementación real y calcula la odometría mediante mínimos cuadrados. La dinámica resuelve el equilibrio de fuerzas considerando la saturación de los motores y el límite de fricción de la superficie. Lo que no reproduce es el microtraqueteo vertical cuando cada rodillo entra y sale de contacto, ni la transferencia dinámica de cargas en aceleraciones violentas.
Lecturas adicionales
Referencias
Fuentes autorizadas para profundizar más allá del modelo educativo acotado de este simulador.