Introducción al control de posición MIT en reBot Arm B601-RS
6+1 GDL · RobStride · CAN @ 1 Mbps · Control de posición MIT · Protección de temperatura · Retorno seguro a cero · API de Python de código abierto

MotorBridge es un SDK CAN en Python para motores RobStride / Damiao. rebot_control lo envuelve con una API de control de posición MIT para el reBot Arm B601-RS: configuración YAML, límites de velocidad por articulación, protección de temperatura MOS de tres niveles y retorno suave a cero mediante Esc / Ctrl+C / stop().
Este tutorial te guía a través de: configuración del entorno → configuración de CAN → ejecución de ejemplos → uso del paquete como biblioteca.
- Este proyecto solo proporciona APIs de control — sin límites de articulación por software ni límites de espacio de trabajo. Los ángulos objetivo que configures se envían directamente a los motores.
- Mantén el brazo dentro de aproximadamente el 70% de su espacio de trabajo. Permanecer más allá del espacio de trabajo durante períodos prolongados puede activar la protección contra bloqueo en la articulación 2 y el brazo puede caer.
- En el primer uso, haz pruebas con ángulos pequeños y bajas velocidades, y mantén el espacio de trabajo libre de personas y obstáculos.
Características
-
Control de posición MIT
Comandos de posición MIT por defecto a 200 Hz; límites de velocidad por articulación con suavizado en el bucle de control. -
6+1 motores
J1–J6 son articulaciones del brazo; J7 (ID CAN 7) es el gripper del efector final, controlado medianteset_joint_angles/set_joint_angle. -
Protección de temperatura de tres niveles
Monitorización en tiempo real de la temperatura MOS: alarma y continuar → sobretemperatura con retorno lento a cero y luego deshabilitar → deshabilitado de emergencia (sin retorno a cero). -
Salida segura y retorno a cero
Esc / Ctrl+C /arm.stop()activan un retorno a cero tipo smoothstep; un segundo Ctrl+C durante el retorno a cero aborta inmediatamente y deshabilita los motores. -
Configuración basada en YAML
Canal CAN, umbrales de temperatura, parámetros de retorno a cero ykp/kddel motor se encuentran enconfig/rebotarm_rs.yaml— ajusta sin cambiar código. -
Lista para usar como biblioteca
Capas claras (config / API / ejemplos); importa confrom rebot import ReBotRSMITController.
Especificaciones
El hardware para este tutorial es proporcionado por Seeed Studio.
| Parámetro | Especificación |
|---|---|
| Modelo de brazo | Kit ensamblado reBot Arm B601-RS con gripper |
| GDL | 6+1 (incluyendo gripper) |
| Radio de trabajo | 754.7 mm (con gripper) / 587.5 mm (sin gripper) |
| Carga útil | Nominal 2.5 kg / Máx 5 kg |
| Rango de articulación | J1: ±150° / J2: 220° ~ 0° / J3: 220° ~ 0° / J4: ±90° / J5: ±90° / J6: ±180° / Gripper: 345° ~ 0° |
| Repetibilidad | 0.1 mm |
| Peso | 6.7 kg |
| Servomotores | RobStride 06 × 3 / RobStride 00 × 4 (incluyendo gripper) |
| Comunicación | Bus CAN @ 1 Mbps |
| Tensión de alimentación | CC 48V |
| Fuente de alimentación | CC 48V 15A |
| Temperatura de funcionamiento | -20°C ~ 50°C |
| Control | PC |
Asignación de motores en este proyecto
| Articulación | ID CAN | Modelo | Notas |
|---|---|---|---|
| J1 | 1 | RS06 | Base |
| J2 | 2 | RS06 | |
| J3 | 3 | RS06 | |
| J4 | 4 | RS00 | |
| J5 | 5 | RS00 | |
| J6 | 6 | RS00 | Muñeca |
| J7 | 7 | RS00 | Gripper del efector final |
Capacidades de software (este repositorio)
| Función | Estado |
|---|---|
| Control de posición MIT | ✅ |
| Límites de velocidad por articulación | ✅ |
| Control del gripper (ID CAN 7) | ✅ |
| Monitorización de temperatura MOS y protección de tres niveles | ✅ |
| Retorno seguro a cero / deshabilitado de emergencia | ✅ |
| Configuración YAML | ✅ |
| API de biblioteca Python | ✅ |
| Cinemática directa / inversa (Pinocchio) | ❌ (ver reBotArm_control_py) |
| Simulación MeshCat | ❌ (ver repositorio anterior) |
Parámetros de los motores de las articulaciones
| Parámetro | RobStride 00 | RobStride 06 |
|---|---|---|
| Tensión nominal | 48V | 48V |
| Corriente nominal | 4.7 Apk ± 10% | 14.3 Apk ± 10% |
| Corriente pico | 15.5 Apk ± 10% | 57 Apk ± 10% |
| Par nominal | 5 N.m | 11 N.m |
| Par pico | 14 N.m | 36 N.m |
| Velocidad nominal | 100 rpm ± 10% | 100 rpm ± 10% |
| Velocidad máxima en vacío | 315 rpm ± 10% | 480 rpm ± 10% |
| Relación de reducción | 10 : 1 | 9 : 1 |
| Interfaz de control | CAN @ 1 Mbps | CAN @ 1 Mbps |
| Modos de control | MIT / Velocidad / Posición / Par | MIT / Velocidad / Posición / Par |
Lista de materiales (BOM)
| Ítem | Cantidad | Incluido |
|---|---|---|
| reBot Arm B601-RS | 1 | ✅ |
| Adaptador CAN (CANABLE / PCAN-USB, etc.) | 1 | ✅ |
| Fuente de alimentación (CC 48V 15A) | 1 | ✅ |
| Cable USB-C | 1 | ✅ |
| Gripper | 1 | ✅ |
Requisitos
| Ítem | Requisito |
|---|---|
| Python | 3.10+ |
| SO | Ubuntu 22.04+ (recomendado) |
| Interfaz CAN | can0 por defecto |
| Alimentación | CC 48V 15A |
| Dependencias | motorbridge, pyyaml; opcional pynput (tecla Esc) |
Instalación
Paso 1. Clonar el repositorio
git clone https://github.com/LAN-GER/rebot_control.git
cd rebot_control
Paso 2. Instalar dependencias
pip install motorbridge pynput pyyaml
pynput habilita la escucha de la tecla Esc. Sin él, solo Esc queda deshabilitada; Ctrl+C y arm.stop() siguen funcionando.
Paso 3. Configurar la interfaz CAN
# List interfaces (PCAN-USB, etc.)
sudo modprobe peak_usb # if using a PEAK adapter
ip -br link
# Set can0 to 1 Mbps (RobStride default)
sudo ip link set can0 down 2>/dev/null
sudo ip link set can0 up type can bitrate 1000000
Después de desconectar y volver a conectar un adaptador CAN USB, normalmente necesitas ejecutar de nuevo los comandos ip link.
Paso 4. (Opcional) Editar el archivo de configuración
Edita config/rebotarm_rs.yaml:
| Clave | Descripción | Valor por defecto |
|---|---|---|
can.channel | Nombre de la interfaz CAN | can0 |
can.host_id | ID del host | 0xFD |
control.control_hz | Frecuencia de comandos MIT (no velocidad de movimiento) | 200 Hz |
control.telemetry_hz | Frecuencia de lectura de temperatura | 2 Hz |
temperatures.alarm_c | Umbral de alarma de temperatura | 80°C |
temperatures.return_zero_c | Umbral de retorno a cero por sobretemperatura | 125°C |
temperatures.disconnect_c | Umbral de deshabilitado de emergencia | 140°C |
return_zero.max_speed_deg_s | Velocidad pico normal de retorno a cero | 30°/s |
return_zero.thermal_max_speed_deg_s | Velocidad pico térmica de retorno a cero | 30°/s |
return_zero.min_time_s | Duración mínima de retorno a cero | 3.0 s |
return_zero.settle_time_s | Tiempo de mantenimiento en cero después del retorno | 0.30 s |
motors | ID / modelo del motor / MIT kp / kd | Ver YAML |
Las claves que faltan usan valores por defecto en el código; las claves desconocidas generan un error para detectar errores tipográficos.
Estructura del código
rebot_control/
├── config/
│ └── rebotarm_rs.yaml # CAN / motors / temperature / return-to-zero
├── rebot/
│ ├── __init__.py # Public API
│ ├── config.py # Config loading and validation
│ └── controller.py # ReBotRSMITController
└── examples/
├── _bootstrap.py # Path setup + wait-for-target helpers
├── quick_start.py # Tutorial 1: quick start
├── custom_config.py # Tutorial 2: custom config
├── monitor_status.py # Tutorial 3: monitor status
├── single_joint_adjust.py # Tutorial 4: single joint + gripper
├── read_joint_angles.py # Tutorial 5: read actual positions
├── stop_options.py # Tutorial 6: stop options
├── recommended_structure.py # Tutorial 7: recommended structure
└── mit_position_control.py # Full editable demo
Capas:
- Archivo de configuración: única fuente de parámetros ajustables.
- Capa de configuración:
load_config()→ControllerConfig. - Capa de API: lógica de control sin valores de demostración codificados.
- Capa de ejemplos: ángulos objetivo, velocidades y flujo de ejecución.
Cómo funciona
Control MIT y suavizado de velocidad
control_hz(200 Hz por defecto) establece solo la frecuencia de envío de comandos.- La velocidad real de movimiento proviene de
set_max_speeds([...])(grados/s). set_joint_angles()solo actualiza los objetivos; el bucle de control incrementa los ángulos de comando hacia los objetivos bajo el límite de velocidad.
Si llamas a stop() inmediatamente después de establecer los objetivos, puede que veas casi ningún movimiento. Los ejemplos usan wait_for_command_targets() (ver examples/_bootstrap.py) para esperar hasta que los ángulos de comando se acerquen a los objetivos antes de volver a cero.
Secuencia de conexión y habilitación
Dentro de connect(), el orden es: registrar motores → cambiar a modo MIT → habilitar → leer posiciones mecánicas actuales (para inicializar los objetivos y evitar un salto repentino después de habilitar). El mechPos (0x7019) de RobStride se puede leer de forma fiable después de habilitar.
Para lectura pasiva de posición (Tutorial 5), llama a disable_motors() después de connect() para que puedas mover el brazo a mano y seguir leyendo ángulos.
Protección de temperatura de tres niveles
| Umbral (por defecto) | Comportamiento |
|---|---|
| ≥ 80°C | Alarma de temperatura (una vez por motor por cruce de sobretemperatura), continuar en funcionamiento |
| ≥ 125°C | Detener el movimiento, retorno lento a cero a velocidad pico térmica y luego deshabilitar |
| ≥ 140°C | Deshabilitado de emergencia inmediato, sin retorno a cero |
Retorno seguro a cero
El retorno a cero utiliza una trayectoria smoothstep. Duración:
duration = max(min_time_s, per-joint time estimated from peak speed)
La velocidad máxima es max_speed_deg_s (normal) o thermal_max_speed_deg_s (térmica). Ambas tienen como valor predeterminado 30°/s; min_time_s tiene como valor predeterminado 3.0 s.
| Método de salida | Comportamiento |
|---|---|
Esc / primer Ctrl+C / arm.stop() | Retorno lento a cero → deshabilitar → cerrar CAN |
| Segundo Ctrl+C durante el retorno a cero | Aborta el retorno a cero y deshabilita inmediatamente |
| Error de comunicación | Deshabilitado de emergencia, sin retorno a cero |
Unidades
| Contexto | Unidades |
|---|---|
| API externa (ángulos, velocidades) | grados, deg/s |
| Internos de MotorBridge MIT | radianes, rad/s |
Tutoriales
Ejecuta todos los ejemplos desde la raíz del proyecto. Cada script documenta el Movimiento esperado al principio e imprime una línea [Expected / 预期] al iniciar.
| Tutorial | Archivo | Comando |
|---|---|---|
| 1. Inicio rápido | examples/quick_start.py | python3 examples/quick_start.py |
| 2. Configuración personalizada | examples/custom_config.py | python3 examples/custom_config.py |
| 3. Monitorizar estado | examples/monitor_status.py | python3 examples/monitor_status.py |
| 4. Articulación única + pinza | examples/single_joint_adjust.py | python3 examples/single_joint_adjust.py |
| 5. Leer posiciones | examples/read_joint_angles.py | python3 examples/read_joint_angles.py |
| 6. Opciones de parada | examples/stop_options.py | python3 examples/stop_options.py default |
| 7. Estructura del programa | examples/recommended_structure.py | python3 examples/recommended_structure.py |
| Demostración completa | examples/mit_position_control.py | python3 examples/mit_position_control.py |
1. Inicio rápido (quick_start.py)
Movimiento esperado: J1 se mueve a +20° a ~15°/s; las demás articulaciones y la pinza permanecen en 0°; luego retorno lento a cero y deshabilitar.
python3 examples/quick_start.py
Flujo: start() → set_max_speeds() → set_joint_angles() → esperar al movimiento → stop().
2. Archivo de configuración personalizada (custom_config.py)
python3 examples/custom_config.py
python3 examples/custom_config.py config/rebotarm_rs.yaml
Movimiento esperado: J1 → +15° (~15°/s), las demás en 0°, luego retorno a cero.
3. Monitorizar mientras se ejecuta (monitor_status.py)
python3 examples/monitor_status.py
Movimiento esperado: J1 → +30°; la terminal imprime continuamente objetivo / enviado / temperatura del MOS. Pulsa Esc o Ctrl+C para salir y volver a cero.
Notas:
- Objetivo vs enviado: los ángulos enviados van con retraso respecto a los objetivos (suavizado limitado por velocidad).
- Temperatura: lee
arm.last_temperatures; no necesitas sondear el bus CAN tú mismo.
4. Ajuste de una sola articulación y pinza (single_joint_adjust.py)
python3 examples/single_joint_adjust.py
Objetivos predeterminados:
| J1 | J2 | J3 | J4 | J5 | J6 | J7 Pinza |
|---|---|---|---|---|---|---|
| +25° | +15° | +15° | -15° | 0° | 0° | 180° |
joint_id: 1–6 son articulaciones del brazo; 7 es la pinza (ID CAN 7).
5. Leer posiciones reales (read_joint_angles.py)
python3 examples/read_joint_angles.py
Movimiento esperado:
connect(): cambia al modo MIT y habilita (establece la comunicación), lee los ángulos actuales como semillas de objetivo.disable_motors(): deshabilita inmediatamente para que puedas mover el brazo a mano.- La terminal imprime los ángulos reales de las articulaciones a ~30 Hz; los valores deberían cambiar cuando muevas el brazo.
- Pulsa Ctrl+C para salir;
stop(return_to_zero=False)cierra el bus CAN sin retorno a cero.
Este ejemplo no llama a start(), por lo que no se ejecuta ningún hilo de control MIT y no se envían objetivos de movimiento.
Flujo del código:
arm.connect() # MIT → enable → read current angles
arm.disable_motors() # disable — arm can be moved by hand
while True:
actual = arm.read_joint_angles() # ~30 Hz
print(actual)
# After Ctrl+C
arm.stop(return_to_zero=False, wait=True)
read_joint_angles() accede al bus CAN de forma síncrona (lee mechPos de los 7 motores en secuencia), por lo que la frecuencia alcanzable depende del tiempo de ida y vuelta del bus. El ejemplo apunta a 30 Hz; si cada lectura tarda más, la frecuencia real será menor. Mientras el control MIT está en ejecución, usa get_command_angles() para monitorizar el movimiento comandado en lugar de llamar a read_joint_angles() a alta frecuencia.
6. Opciones de parada segura (stop_options.py)
Cada modo primero mueve J1 a ~+20°, luego se detiene según el modo:
python3 examples/stop_options.py default # slow return-to-zero (recommended)
python3 examples/stop_options.py no_return # disable without return-to-zero
python3 examples/stop_options.py async # stop(wait=False) + wait_until_stopped()
python3 examples/stop_options.py emergency # emergency disable, no return-to-zero
no_return / emergency dejan el brazo en una pose distinta de cero y deshabilitan los motores. Asegúrate de que el área sea segura; sujeta el brazo con la mano si es necesario.
7. Estructura de programa recomendada (recommended_structure.py)
Demuestra try / except / finally para que stop() se ejecute incluso en caso de errores.
python3 examples/recommended_structure.py
Demostración completa de parámetros (mit_position_control.py)
Edita TARGET_ANGLES (longitud 7) y JOINT_SPEEDS_DEG_S al principio del archivo, luego ejecuta:
python3 examples/mit_position_control.py
Predeterminado: J1 → +50° (20°/s), las demás y la pinza en 0°; la terminal muestra objetivo / enviado / temperatura; Esc / Ctrl+C sale con retorno a cero.
El brazo puede moverse rápidamente en modo MIT. Mantén a las personas y el equipo alejados, y permanece dentro de aproximadamente el 70% del espacio de trabajo.
Uso como biblioteca
Ejemplo mínimo
from rebot import ReBotRSMITController
arm = ReBotRSMITController() # loads config/rebotarm_rs.yaml
arm.start(enable_esc=True)
arm.set_max_speeds([15.0] * 7)
arm.set_joint_angles([20.0, 0, 0, 0, 0, 0, 0]) # J1–J6 + gripper J7
# Wait for motion to finish before stop; see examples/quick_start.py
arm.stop() # slow return-to-zero → disable → close CAN
Configuración personalizada y pinza
from rebot import (
ReBotRSMITController,
load_config,
GRIPPER_JOINT_ID,
)
arm = ReBotRSMITController(load_config("config/rebotarm_rs.yaml"))
arm.start()
arm.set_max_speeds([20.0] * 7)
arm.set_joint_angles([25, 15, 15, -15, 0, 0, 0])
arm.set_joint_angle(GRIPPER_JOINT_ID, 180.0) # gripper = J7
Lectura pasiva de posición
from rebot import ReBotRSMITController
arm = ReBotRSMITController()
arm.connect() # MIT → enable → read current angles
arm.disable_motors() # disable — move arm by hand
actual = arm.read_joint_angles()
print(actual)
arm.stop(return_to_zero=False, wait=True) # close CAN, no return-to-zero
Ciclo de vida del controlador
Control de movimiento MIT:
create → start() → set_max_speeds() → set_joint_angles() / set_joint_angle() → … → stop()
Lectura pasiva de posición (sin movimiento comandado):
create → connect() → disable_motors() → read_joint_angles() → … → stop(return_to_zero=False)
API principal
| Método / atributo | Descripción |
|---|---|
connect() | Conecta CAN, modo MIT, habilita, lee los ángulos actuales; llamado automáticamente por start() |
disable_motors() | Deshabilita todos los motores sin cerrar el bus CAN (para lectura pasiva) |
start(enable_esc=True, install_signal_handlers=True) | Inicia los hilos de control y de temperatura |
set_joint_angles(angles_deg) | Establece 7 ángulos objetivo (grados) |
set_joint_angle(joint_id, angle_deg) | Establece una articulación / pinza (1–7) |
set_max_speeds(speeds_deg_s) | Establece 7 velocidades máximas (deg/s) |
get_target_angles() / get_command_angles() | Ángulos objetivo / de comando suavizados |
read_joint_angles() | Lectura síncrona de posiciones mecánicas reales (grados); usa CAN |
last_temperatures | Temperatura del MOS por motor |
is_stopped | Indica si la parada segura ha finalizado |
stop(return_to_zero=True, wait=True) | Detiene (retorno a cero por defecto) |
request_stop(..., emergency=True) | Parada avanzada / deshabilitado de emergencia |
Constantes exportadas: GRIPPER_MOTOR_ID = 7, GRIPPER_JOINT_ID = 7.
Preguntas frecuentes
-
Permission denied/ no se puede abrir can0
Asegúrate de que la interfaz CAN estéupy de que tu usuario pueda acceder a los dispositivos de red. Usasudoparaip linksi es necesario, o revisa las reglas de udev. -
Sin respuesta del motor / fallo al habilitar
- Confirma que la velocidad de transmisión es 1 Mbps;
- Confirma que
channel,host_idy los IDs de los motores enconfig/rebotarm_rs.yamlcoinciden con el hardware; - Vuelve a ejecutar
ip linkdespués de reconectar el USB CAN.
-
Se establecen ángulos pero el brazo apenas se mueve
set_joint_angles()solo actualiza los objetivos. Estableceset_max_speeds()razonables y espera hasta que los ángulos de comando se acerquen a los objetivos antes destop(). Consultaexamples/quick_start.py. -
La pinza no se mueve
La pinza es J7 / CAN ID 7. Pasa 7 valores aset_joint_angles(el último es la pinza), o usaset_joint_angle(7, angle). -
Tiempo de espera al leer posición / no se pueden leer ángulos
mechPosse puede leer de forma fiable en modo MIT después de habilitar. El tutorial 5 usaconnect()y luegodisable_motors()para que puedas mover el brazo a mano y seguir leyendo. Siensure_modeo las lecturas de parámetros agotan el tiempo de espera, revisa el cableado CAN, la terminación y la alimentación de los motores. -
Spam de alarma de temperatura
Las alarmas se disparan por flancos con histéresis: una alarma por motor por evento de sobretemperatura; se vuelve a alarmar solo después de que la temperatura baje por debajo dealarm_c - 2°C. -
Protección contra bloqueo de la articulación 2 / el brazo cae
A menudo es causado por permanecer más allá de ~70% de extensión del espacio de trabajo. Apaga y enciende para borrar la protección y reduce los ángulos objetivo y el tiempo de permanencia. -
Comportamiento tras errores de comunicación
Ante un fallo de comunicación en el bucle de control, el programa deshabilita de emergencia sin volver a cero para evitar movimiento bajo malas comunicaciones. -
Pinocchio / MeshCat / compensación de gravedad
Este repositorio se centra en el control de posición MIT. Para cinemática, simulación y compensación de gravedad, consulta reBotArm_control_py y la guía de Pinocchio y MeshCat en el Wiki de Seeed.
Contacto
- Repositorio: https://github.com/LAN-GER/rebot_control
- Incidencias: GitHub Issues
- Foro: Seeed Studio Forum
Referencias
- MotorBridge SDK
- reBotArm_control_py (cinemática / simulación / compensación de gravedad)
- Documentación del motor RobStride
- README en chino en este repositorio:
README_zh.md - README en inglés en este repositorio:
README.md