Sistema de navegacion autonoma basado en ROS2 para el robot Yahboom ROSMASTER-A1 (Jetson Orin Nano Super), desarrollado para el Torneo Mexicano de Robotica 2026 — categoria AutoModelCar. Cubre las 4 pruebas del reglamento:
| Prueba | Modo APEX | Web UI | Estado |
|---|---|---|---|
| P1 Reconocimiento de señales de transito | senales_dl |
:8086 |
✓ Calibrado live |
| P2 Navegacion con obstaculos estaticos | obstaculos_dl |
:8084 |
✓ Calibrado live |
| P3 Navegacion con obstaculos en movimiento | obstaculos_dl |
:8084 |
✓ Calibrado live |
| P4 Estacionamiento autonomo | parking |
:8085 |
✓ Calibrado live |
Las cuatro modalidades soportan sentido horario (CW) y antihorario (CCW) seleccionable desde la interfaz web, conforme al reglamento (la pose inicial la asigna el juez).
| Componente | Especificacion |
|---|---|
| Robot | Yahboom ROSMASTER-A1, Ackermann steering, 30cm × 21cm |
| Compute | Jetson Orin Nano Super (8 GB) |
| Camara | Ascamera HP60C USB (RGB, 320×240 @ 10-15 fps) |
| LiDAR | Slamtec C1 (360°, 7-10 Hz, rango 0.08-16 m) |
| Direccionales | Arduino Nano + 4 LEDs ambar (D2..D5), USB-CH340 |
| Conectividad | WiFi 192.168.0.187, SSH jetson@192.168.0.187 |
Arduino Nano puenteado por USB al Jetson, recibe protocolo serial UART 115200:
| Byte | Accion | UInt8 ROS | Uso |
|---|---|---|---|
0 |
OFF | 0 | Conduccion normal |
L |
Izquierda parpadeando | 1 | P2/P3 cambio de carril a izq |
R |
Derecha parpadeando | 2 | P2/P3 cambio de carril a der |
H |
HAZARD (los 4 parpadeando) | 3 | P1 STOP/CRUCE (recompensa -5s) |
direccionales_node.py hace bridge /direccionales/cmd → serial. Auto-reconnect.
Wrapper run_direccionales.sh relanza si el proceso muere.
┌────────────────────────────────────────┐
│ Sensores │
│ ┌──────────┐ ┌──────────┐ ┌──────┐ │
│ │ Camara │ │ LiDAR │ │Encoders│ │
│ │ HP60C │ │ C1 │ │ IMU │ │
│ └────┬─────┘ └─────┬────┘ └───┬───┘ │
└───────┼──────────────┼───────────┼──────┘
│ │ │
┌───────────────────┼──────────────┼───────────┼───────────────────┐
│ │ │ │ │
┌────▼─────┐ ┌─────────▼──┐ ┌───────▼────┐ ┌─▼────────┐ ┌──────▼──────┐
│ U-Net v3 │ │ YOLOv8n │ │ Crosswalk │ │ object_ │ │ Driver │
│ TRT FP16│ │ stop sign │ │ bird-eye │ │ detection│ │ Ackermann │
│ 0.6 ms │ │ TRT FP16 │ │ frequency │ │ PCL │ │ │
└────┬─────┘ └─────┬──────┘ └─────┬──────┘ └────┬─────┘ └──────▲──────┘
│ │ │ │ │
/lane_detection/ /traffic/ /traffic/ /obstacle_* /cmd_vel
control_ref stop_sign crosswalk
lane_state stop_distance crosswalk_distance
confidence
│ │ │ │ │
└───────┬───────┴────────────────┴───────┬───────┘ │
│ │ │
┌───────▼────────┐ ┌───────▼────────┐ │
│ MasterSignals │ │MasterObstacles │ │
│ (P1) │ │ (P2/P3) │ │
│ │ │ │ │
│ MasterParking │ │ ←──CW/CCW──→ │ │
│ (P4) │ │ │ │
└───────┬────────┘ └───────┬────────┘ │
│ │ │
└────────────────┬───────────────┘ │
│ │
└────────────────┬───────────────────────┘
│
┌───────▼────────┐
│ /direccionales │
│ /cmd │
│ (LEDs ambar) │
└────────────────┘
Cada master corre en su propio launch (P1, P2/P3, P4) con su propio Web UI. Solo un modo activo a la vez — el juez selecciona la prueba en mesa.
Pipeline:
lanzar_senales_dl.md· Web UI: http://192.168.0.187:8086
El reglamento exige detectar 5 señales de alto y 5 cruces peatonales aleatorios y detenerse a ≤30 cm durante ≥5 s. Aprobacion: 3 de cada tipo correctos.
┌──────────────────────────┐
│ Camara HP60C │
└────────────┬─────────────┘
│
┌──────────────────────┼──────────────────────┐
│ │ │
┌───────▼────────┐ ┌────────▼──────────┐ ┌──────▼──────────┐
│ image_ │ │ traffic_detector │ │ crosswalk_ │
│ subscriber_dl │ │ (YOLOv8n) │ │ detector │
│ (U-Net) │ │ │ │ (frequency) │
├────────────────┤ ├───────────────────┤ ├─────────────────┤
│ /lane_detect/ │ │ /traffic/ │ │ /traffic/ │
│ control_ref │ │ stop_sign │ │ crosswalk │
│ lane_state │ │ stop_distance │ │ crosswalk_ │
│ confidence │ │ │ │ distance │
└────────┬───────┘ └─────────┬─────────┘ └────────┬────────┘
│ │ │
└──────────────────────┼──────────────────────┘
│
┌─────────▼───────────┐
│ MasterSignals │
│ (FSM) │
└─────────┬───────────┘
│
/cmd_vel /direccionales/cmd
traffic_detection/traffic_detector (C++):
- YOLOv8n preentrenado en COCO, clase 11 = stop sign
- TensorRT FP16, propio CUDA stream (~3 ms @ 320×320)
- Filtros:
yolo_conf_thresh=0.15,sign_min_area_pct=0.30 - Confirmacion temporal 3 de 5 frames
- Distancia: pinhole flat-floor projection sobre
bbox.y2 - Topics:
/traffic/stop_sign(Bool),/traffic/stop_distance(Float32, m)
Nodo standalone traffic_detection/crosswalk_detector (C++) — replica la
etapa de bird-eye + CLAHE de image_subscriber_dl SIN tocar el lane node.
Por que bird-eye: elimina perspectiva. Una franja blanca aparece como horizontal independiente de la distancia/angulo del robot.
Por que frequency: una linea blanca solida da ~2 transiciones blanco-negro por fila; una cebra da 8-20. Imposible confundir lineas de carril con cruces.
Por que CLAHE + adaptive threshold: auto-ajuste a iluminacion oscura/brillante.
Camara RGB (320×240 BGR)
│
┌────▼─────────────┐
│ resize 320×240 │
│ warpPerspective │ ← misma matriz que image_subscriber_dl
│ → bird-eye │ (parametros persp_*)
└────┬─────────────┘
│
┌────▼─────────────┐
│ HLS → L channel │
│ CLAHE (3.0,8x8) │
│ resize 128×128 │
└────┬─────────────┘
│
┌────▼─────────────┐
│ adaptiveThreshold│ block=25, C=-12 (auto-ajuste a luz)
│ MORPH_OPEN 3×3 │
└────┬─────────────┘
│
┌────▼─────────────┐
│ ROI [20-126, │ ← interior, excluye lineas de carril en bordes
│ 10-118] │
│ Por fila: │
│ - count trans │ ← transiciones blanco-negro (cebra: 8+)
│ - count white │
│ density global │
└────┬─────────────┘
│
freq_rows ≥ 25 AND density ≥ 0.18 → raw=1
│
Confirmation buffer 3 de 5 frames
│
Distance (linear interp en bird-eye y):
y=0 → dist_top_m (0.60)
y=127 → dist_bot_m (0.10)
│
/traffic/crosswalk (Bool)
/traffic/crosswalk_distance (Float32, m)
/traffic/crosswalk_debug (Image, 256×256 binary annotated)
┌─────────────────┐
│ DRIVING │ ◄── Lane following normal a max_speed
└────┬────────┬───┘
│ │
│ crosswalk stop_sign
│ detected detected
│ (PRIORIDAD) │
▼ ▼
┌─────────────────┐ ┌───────────────────┐
│ APPROACHING │ │ TRACKING_STOP │
│ (crosswalk) │ │ (stop sign) │
├─────────────────┤ ├───────────────────┤
│ crawl 0.10 m/s │ │ crawl 0.10 m/s │
│ HAZARD ON │ │ HAZARD OFF │
│ trigger DISTANCE│ │ trigger LOST_SIGHT│
│ ≤ 0.14 m │ │ ≥ 2.0 s sin ver │
│ │ │ │
│ ◄── crosswalk │ │ │
│ interrupt │ │ │
└────────┬────────┘ └─────────┬─────────┘
│ │
└──────────┬──────────┘
▼
┌────────────────┐
│ WAITING │ ◄── Detenido 5.0 s, HAZARD ON
└────────┬───────┘ (recompensa reglamento -5s)
│
┌────────▼───────┐
│ RESUMING │ ◄── Cooldown 5.0 s, drena latches
└────────┬───────┘
│
┌────────▼───────┐
│ DRIVING │
└────────────────┘
Reglas de conflicto entre señales (caso real: cebra cerca de stop sign):
-
Co-detectados en DRIVING: el crosswalk tiene prioridad (siempre esta mas cerca; el stop esta en un poste lateral mas lejos).
-
Stop ya en TRACKING_STOP, aparece cebra: la cebra interrumpe el tracking. El robot maneja el cruce primero (APPROACHING → WAITING → RESUMING). Despues del cooldown, si el stop sigue visible, vuelve a entrar a TRACKING_STOP desde DRIVING y lo procesa.
| Componente | Parametro | Valor |
|---|---|---|
master_control |
approach_speed |
0.10 m/s |
master_control |
crosswalk_distance_target |
0.14 m |
master_control |
wait_time / cooldown_time |
5.0 / 5.0 s |
master_control |
lost_sight_time |
2.0 s |
master_control |
approach_time |
10.0 s (max bound) |
crosswalk_detector |
trans_thresh |
12 |
crosswalk_detector |
row_thresh |
25 |
crosswalk_detector |
density_thresh |
0.18 |
crosswalk_detector |
roi_top / roi_bot |
20 / 126 |
crosswalk_detector |
adaptive_block / adaptive_c |
25 / -12 |
crosswalk_detector |
dist_top_m / dist_bot_m |
0.60 / 0.10 |
traffic_detector |
yolo_conf_thresh |
0.15 |
traffic_detector |
sign_min_area_pct |
0.30 |
Pipeline:
lanzar_obstaculos_dl.md· Web UI: http://192.168.0.187:8084
P2 = 3 obstaculos estaticos. P3 = 1 estatico + 2 moviles + vehiculo en contraflujo. En ambas pruebas se usan los vehiculos de otros equipos como obstaculos. Penalizacion: -1 m por cada cambio de carril sin direccional.
┌──────────────┐
│ LANE_DRIVING │ ◄── Sigue lineas a max_speed (0.25)
└──────┬───────┘
│ front < slow_dist (1.0 m)
┌──────▼───────┐
│ SLOWING │ ◄── Reduce velocidad, busca lado libre
└──────┬───────┘
│ front < stop_dist (0.6 m)
┌──────▼───────┐
│ STOPPED │ ◄── Para, evalua lado libre + contraflujo
└──────┬───────┘
│ lado de rebase libre
┌──────▼───────┐
│ PASSING │ ◄── HAZARD L/R segun direccion
│ │ Cambia de carril, rodea obstaculo
└──────┬───────┘
│ obstaculo en zona trasera
┌──────▼───────┐
│ RETURNING │ ◄── HAZARD L/R inverso
│ │ Regresa al carril original
└──────┬───────┘
│
┌──────▼───────┐
│ LANE_DRIVING │
└──────────────┘
| Direccion | Carril | Lado de rebase | leftLaneBusy zone |
|---|---|---|---|
| CW | Derecho | Por izquierda | 200°-220° (LiDAR) |
| CCW | Izquierdo | Por derecha | 140°-160° (LiDAR) |
Defaults clave:
kp_cte=1.7,kp_heading=0.35,steer_bias=-0.04(CW) /+0.08(CCW)max_speed=0.25,slow_dist=1.0,stop_dist=0.6,clear_dist=0.65lane_change_steer=0.4,lane_change_time=3.25 s
Pipeline:
lanzar_parking.md· Web UI: http://192.168.0.187:8085
Detecta un gap entre dos vehiculos (60 cm largo × 30 cm ancho) y se estaciona de reversa. El robot mide 30 × 21 cm.
┌──────────┐
│ SCANNING │ ◄── Sigue linea, detecta gap en lado de scan
└────┬─────┘ (CW=derecho, CCW=izquierdo)
│ gap detectado (>= min_gap, < scan_dist_max)
┌────▼─────┐
│ PASSING │ ◄── Sigue avanzando hasta que car2 sale del rango
└────┬─────┘ LiDAR (zona de scan se despeja)
│ scan side libre
┌────▼─────┐
│ PULL_OUT │ ◄── 0.3 s servo recto → arco reversa hacia el gap
└────┬─────┘ CW: +steer (derecha), CCW: -steer (izquierda)
│ Para si ambos lados < 0.80 m o timeout 8 s
┌────▼─────┐
│ DRIVE_IN │ ◄── 0.3 s servo recto → reversa recta
└────┬─────┘ Para cuando ambos lados < 0.30 m
│
┌────▼─────┐
│ PARKED │ ◄── Stop final, motors_off
└──────────┘
Defaults:
scan_dist_max=0.40m,min_gap=0.15mapproach_speed=0.10m/sturn_steer=0.765(CW),ccw_turn_steer=0.825(CCW)
Las 4 pruebas soportan ambos sentidos. Toggle desde Web UI con confirmacion. El juez asigna la pose inicial; el equipo selecciona la direccion correspondiente.
| CW (horario) | CCW (antihorario) | |
|---|---|---|
| Carril | Derecho | Izquierdo |
| Rebase (P2/P3) | Por izquierda (HAZARD-L) | Por derecha (HAZARD-R) |
steer_bias |
-0.04 | +0.08 |
| Scan parking | Lado derecho [70°-150°] | Lado izquierdo [210°-290°] |
turn_steer (P4) |
0.765 | 0.825 |
Los biases tuneados live se preservan por direccion (cw_steer_bias_,
ccw_steer_bias_) y se intercambian al togglear.
Compartido por las 4 pruebas. Es la columna vertebral del lane following.
Input (1×1×128×128 grayscale, post-CLAHE bird-eye)
│
┌───────▼───────┐
│ Encoder │ 4 bloques conv (16→32→64→128 canales)
│ (downsample) │ BatchNorm + ReLU + MaxPool
└───────┬───────┘
│
┌───────▼───────┐
│ Bottleneck │ 256 canales
└───────┬───────┘
│
┌───────▼───────┐
│ Decoder │ 4 bloques upconv + skip connections
│ (upsample) │ + 3 Attention Gates + Deep Supervision
└───────┬───────┘
│
┌───────▼───────┐
│ 3-class │ Background | Linea izquierda | Linea derecha
│ segmentation │ (128×128 mask)
└───────────────┘
| Propiedad | Valor |
|---|---|
| Version | U-Net v3 (Attention Gates + Deep Supervision) |
| Input | 128×128 grayscale (bird-eye + CLAHE) |
| Output | 3 clases (fondo, izq, der) |
| Parametros | 1.96 M |
| Loss | Focal Tversky + CrossEntropy |
| Datos | 104,364 imagenes (5,798 base × 18 augmentaciones) |
| Mean IoU | 0.856 |
| Inferencia | 0.6 ms (TensorRT FP16) |
| FPS teorico | ~480 (limitado por camara a 10-15 fps) |
Camara RGB (320×240)
│
┌────▼─────────────────┐
│ resize → bird-eye │ warpPerspective con persp_matrix_
│ → HLS → L channel │
│ → CLAHE (3.0,8×8) │
│ → resize 128×128 │
└────┬─────────────────┘
│
┌────▼─────────────────┐
│ TensorRT FP16 │ unet_v3_lane_fp16.engine (0.6 ms)
│ Forward pass │
└────┬─────────────────┘
│
┌────▼─────────────────┐
│ Argmax → mask │
│ Centroid por fila │
│ Polynomial fit (gr 2)│
│ Compute CTE/heading │
└────┬─────────────────┘
│
/lane_detection/control_ref (Vector3: CTE, heading, curvature)
/lane_detection/lane_state (UInt8: 0=BOTH, 1=ONE_LINE, 2=NO_LINES, 3=RECOVERING)
/lane_detection/confidence (Float32 0-1)
image_subscriber_dl mantiene el ultimo cte/heading/curvature. Si no llegan
frames durante 0.5 s, entra modo inertial:
| Tiempo | Accion |
|---|---|
| 0-0.5 s | Conduccion normal |
| 0.5-2 s | Inertial: publica ultimo control_ref con CTE decaying |
| > 2 s | Para master, lanza recovery |
| Recovery exitoso | Re-enable master desde donde se quedo |
Usado por P2/P3 y P4. Pipeline:
LiDAR /scan (LaserScan, 7-10 Hz)
│
┌────▼─────────────────┐
│ Polar → Cartesian │ Filtro de rango
│ ROI angular │ P2/P3: [70°-290°] (excluye trasera)
│ │ P4: rango cercano para gap detection
└────┬─────────────────┘
│
┌────▼─────────────────┐
│ Statistical Outlier │ mean_k=8, stddev=0.5
│ Removal │
└────┬─────────────────┘
│
┌────▼─────────────────┐
│ Euclidean Cluster │ tolerance ajustable (0.08 m parking)
│ Extraction (DBSCAN) │ min_size=3, max_size=5000
└────┬─────────────────┘
│
┌────▼─────────────────┐
│ Temporal Persistence │ Cluster visto en >=2 de ultimos 5 frames
│ Filter │ (reduce ruido y multipath)
└────┬─────────────────┘
│
┌────▼─────────────────┐
│ Zone Classification │ RIGHT [70°-160°]
│ │ FRONT [160°-200°]
│ │ LEFT [200°-290°]
└────┬─────────────────┘
│
/obstacle_summary (Vector3: front, left, right en m)
/obstacle_zones (Float32MultiArray: clusters detallados)
Convencion LiDAR del robot: 0°=atras, 90°=derecha, 180°=adelante, 270°=izquierda.
| Topic | Tipo | Hz | Productor |
|---|---|---|---|
/scan |
LaserScan | 7-10 | sllidar_ros2 |
/ascamera_hp60c/.../rgb0/image |
Image | 10-15 | yahboomcar_depth |
| Topic | Tipo | Hz | Productor |
|---|---|---|---|
/lane_detection/control_ref |
Vector3 | 10-15 | image_subscriber_dl |
/lane_detection/lane_state |
UInt8 | 10-15 | image_subscriber_dl |
/lane_detection/confidence |
Float32 | 10-15 | image_subscriber_dl |
/lane_detection/debug_image |
Image | 10-15 | image_subscriber_dl |
| Topic | Tipo | Hz | Productor |
|---|---|---|---|
/traffic/stop_sign |
Bool | ~5 | traffic_detector |
/traffic/stop_distance |
Float32 | ~5 | traffic_detector |
/traffic/crosswalk |
Bool | ~5 | crosswalk_detector |
/traffic/crosswalk_distance |
Float32 | ~5 | crosswalk_detector |
/traffic/event |
UInt8 | ~5 | traffic_detector (1=stop) |
/traffic/debug_image |
Image | ~5 | traffic_detector |
/traffic/crosswalk_debug |
Image | ~5 | crosswalk_detector |
| Topic | Tipo | Hz | Productor |
|---|---|---|---|
/obstacle_summary |
Vector3 | 7-10 | object_detection_pcl |
/obstacle_zones |
Float32MultiArray | 7-10 | object_detection_pcl |
/object_detection/debug_image |
Image | 7-10 | object_detection_pcl |
| Topic | Tipo | Hz | Productor |
|---|---|---|---|
/cmd_vel |
Twist | 20 | master_* (segun modo) |
/direccionales/cmd |
UInt8 | event-driven | master_* (HAZARD/L/R/OFF) |
/vel_raw |
Vector3 | 10 | Ackman_driver_A1 |
APEX/
├── CLAUDE.md # Guia para Claude Code (Sonnet/Opus)
├── README.md # Este archivo
├── PENDIENTES.md # Tareas TMR 2026 (estado de cada prueba)
├── reglamento.md # Reglas oficiales TMR
│
├── lanzar_senales_dl.md # P1: signals (camara + DL + YOLO + cruce)
├── lanzar_obstaculos_dl.md # P2/P3: obstaculos + DL
├── lanzar_parking.md # P4: estacionamiento
├── lanzar_entrenamiento_datos.md # Recoleccion de datos para retraining
│
├── arduino/direccionales/ # Firmware Arduino Nano (LEDs ambar)
├── estacionamiento2.png # Diagrama del area de parking
│
├── unet_training/ # Entrenamiento U-Net (offline)
│ ├── models/v3/ # Modelo v3 actual
│ ├── tools/ # Augmentacion, evaluacion, QC
│ └── train_v3.py
│
└── yahboomcar_ros2_ws/
├── software/library_ws/src/
│ └── sllidar_ros2/ # Driver LiDAR Slamtec C1 (externo)
│
└── yahboomcar_ws/src/
├── lane_detection/ # Deteccion de carriles
│ ├── image_subscriber.cpp # Clasico (gradiente + scanline)
│ ├── image_subscriber_dl.cpp # DL (U-Net TensorRT) ★
│ └── unet_engine.cpp # Wrapper TensorRT
│
├── traffic_detection/ # P1: señales y cruces ★
│ ├── traffic_detector.cpp # YOLO stop sign (TRT)
│ ├── crosswalk_detector.cpp # Bird-eye frequency ★ (nuevo)
│ ├── yolo_engine.cpp # Wrapper TensorRT
│ └── include/yolo_engine.hpp
│
├── object_detection/ # P2/P3 y P4: LiDAR
│ ├── object_detection_pcl.cpp # General (P2/P3)
│ └── object_detection_parking.cpp # Parking (P4)
│
└── navigation_control/ # FSMs y Web UIs
├── src/
│ ├── MasterSignals.cpp # P1 FSM ★
│ ├── MasterObstacles.cpp # P2/P3 FSM
│ └── MasterParking.cpp # P4 FSM
├── scripts/
│ ├── signals_server.py # Web UI 8086 (P1) ★
│ ├── obstacle_avoidance_server.py # Web UI 8084 (P2/P3)
│ ├── parking_server.py # Web UI 8085 (P4)
│ ├── direccionales_node.py # Bridge serial Arduino
│ ├── camera_watchdog.py # Auto-restart camara
│ ├── ackman_watchdog.py # Auto-restart chasis
│ ├── run_ackman.sh # Wrapper chasis
│ └── run_direccionales.sh # Wrapper direccionales
└── launch/
├── navigation_dl_signals_launch.py
├── navigation_dl_obstacles_launch.py
└── navigation_parking_launch.py
★ = añadido / modificado para cumplir las 4 pruebas en abril 2026.
Cada prueba tiene su propio servidor HTTP en un puerto distinto. Solo uno activo a la vez.
- Streams MJPEG:
- Lane Detection (U-Net): vista camara + carriles + mascara U-Net
- Traffic Detection (YOLO + CV): vista camara + bbox stop sign + distancia, con picture-in-picture en esquina superior izquierda mostrando el bird-eye 128×128 binario del crosswalk_detector
- Estado: DRIVING / TRACKING_STOP / APPROACHING / WAITING / RESUMING
- Contadores: STOP detectados / CRUCES detectados (de 5 cada uno)
- Botones: START / STOP, ARM / DISARM motors, toggle CW / CCW
- Sliders:
- master: max_speed, kp_cte, wait_time, cooldown_time, lost_sight_time, crosswalk_distance_target
- traffic: yolo_conf_thresh, sign_min_area_pct
- crosswalk: trans_thresh, row_thresh, adaptive_c
- Streams MJPEG: vista camara + carriles | vista LiDAR clusters
- Distancias F / L / R en vivo (codigo de color rojo<0.4 / naranja<0.8 / verde)
- Botones START / STOP + toggle CW / CCW
- Sliders: slow_dist, stop_dist, clear_dist, lane_change_time, max_speed, steer_bias
- Streams MJPEG: vista camara + carriles | vista LiDAR clusters
- Estado parking: SCANNING / PASSING / PULL_OUT / DRIVE_IN / PARKED
- Distancias F / L / R en vivo
- Botones START / STOP + toggle CW / CCW
- Sliders: min_gap, approach_speed, turn_steer, scan_dist_max, max_speed
La camara USB (HP60C) se desconecta esporadicamente. Cobertura en 3 niveles:
| Nivel | Activacion | Accion | Tiempo |
|---|---|---|---|
| Inertial | 0.5-2 s sin frames | Master sigue con ultimo control_ref, CTE decay | 0-2 s |
| Stop seguro | > 2 s sin frames | Master enabled=false, robot frena en carril |
inmediato |
| Recovery L1 | Device existe | unbind/bind USB | ~2 s |
| Recovery L2 | Device desaparecio | reset hub + relaunch LiDAR + driver | ~7 s |
camera_watchdog.py arranca con cada launch, monitorea heartbeat de
/lane_detection/confidence. Tras recovery exitoso, re-enable master automatico.
El robot nunca conduce a ciegas — se detiene en carril en lugar de salirse.
Ackman_driver_A1 puede colgarse (MCU lockup, DDS stall). Cobertura:
run_ackman.sh(wrapper, setsid): relanza el driver si terminaackman_watchdog.py: vigila/vel_raw, mata al driver si no publica- udev rule fija el puerto del CH340 del chasis (devpath 2.3.x) vs Arduino (2.4.x)
run_direccionales.sh auto-detecta el puerto del Arduino Nano (salta
/dev/myserial y /dev/rplidar), auto-reconecta si se desenchufa.
pub(-speed, +steer) → CW yaw (reversa, gira derecha) ✓ probado
pub(-speed, -steer) → CCW yaw (reversa, gira izquierda) ✓ probado
pub(+speed, +steer) → CCW yaw (adelante, gira izquierda) ✓ probado
pub(+speed, -steer) → CW yaw (adelante, gira derecha) ✓ probado
LiDAR: 0°=atras, 90°=derecha, 180°=adelante, 270°=izquierda.
# SSH al robot
ssh jetson@192.168.0.187 # password: yahboom
# Compilar todo
cd ~/yahboomcar_ros2_ws/yahboomcar_ws
source /opt/ros/humble/setup.bash
colcon build
# Compilar paquete especifico
colcon build --packages-select navigation_control
colcon build --packages-select traffic_detection # P1
colcon build --packages-select lane_detection # DL lane
colcon build --packages-select object_detection # LiDAR# Editar local en /home/jose/APEX/
# Copiar al robot:
sshpass -p 'yahboom' scp \
/home/jose/APEX/yahboomcar_ros2_ws/yahboomcar_ws/src/navigation_control/src/MasterSignals.cpp \
jetson@192.168.0.187:/home/jetson/yahboomcar_ros2_ws/yahboomcar_ws/src/navigation_control/src/
# Compilar en el robot:
sshpass -p 'yahboom' ssh jetson@192.168.0.187 \
"cd ~/yahboomcar_ros2_ws/yahboomcar_ws && source /opt/ros/humble/setup.bash && \
colcon build --packages-select navigation_control --cmake-args -DCMAKE_BUILD_TYPE=Release"
# Reiniciar el nodo (ver lanzar_*.md de la prueba correspondiente)Cada prueba tiene su markdown con los comandos exactos:
# P1 — Signals
cat lanzar_senales_dl.md # ejecutar comandos en orden
# P2/P3 — Obstacles
cat lanzar_obstaculos_dl.md
# P4 — Parking
cat lanzar_parking.mdTodos los launches arrancan los nodos en estado enabled=false motors_armed=false
por seguridad. La activacion final se hace siempre desde la interfaz web
(START/STOP), nunca por CLI.
| Requisito | Implementacion |
|---|---|
| Vehiculo escala 1:10 con carcasa | ROSMASTER-A1 30×21 cm + carcasa pendiente |
| Servovision | Camara HP60C en toldo |
| Sensores dentro de carcasa | LiDAR + Jetson + bateria internos |
| Maximo 45×25×25 cm + 45 cm sensores | OK |
| Teleoperacion para servir como obstaculo | ✓ topic /cmd_vel + servidor web |
| P1: stop a ≤30 cm en señal/cruce, 5 s detenido | ✓ MasterSignals + dist target |
| P1: 3 de 5 stops + 3 de 5 cruces minimo | ✓ contadores en Web UI |
| P1: HAZARD durante stop (recompensa -5 s) | ✓ DIR_HAZARD en WAITING |
| P2/P3: rebase con direccional (penalizacion -1 m si no) | ✓ DIR_LEFT/RIGHT en PASSING |
| P2/P3: regresar al carril original tras rebase | ✓ RETURNING state |
| P4: estacionarse en gap de 60×30 cm | ✓ MasterParking PULL_OUT + DRIVE_IN |
| P4: navegacion 100% autonoma | ✓ enabled desde Web UI, sin control manual |
| Poster A1 obligatorio | Pendiente |
APEX — TMR 2026 categoria AutoModelCar.