⚡ Robotics & Physical AI Suite — 100% Offline Functional
⌂ Master Directory · RobotForge · FreeRobotics · FreeRTOS ESP32 · URDF 3D Viewer
Autonomous Mapping & Perception Sandbox

2D LiDAR Raycasting & Occupancy Grid SLAM

Simulate real-time 360° laser rangefinding, Gaussian sensor noise, Bresenham ray-marching, and recursive Bayesian log-odds occupancy probability mapping. Export production ROS 2 Nav2 map packages.

WORLD GROUND TRUTH (LIDAR BEAMS)
CONSTRUCTED OCCUPANCY GRID (LOG-ODDS)
Drive: WASD or ↑←↓→ · On-Screen Stick
Robot Pose (x, y, θ) X: 0.00m, Y: 0.00m, 0.0°
Linear / Angular Velocity v: 0.00 m/s · ω: 0.0 °/s
Map Explored / Resolution 0.0% explored · 5 cm/cell
Active Rays & Scan Rate 360 beams · 30.0 Hz
📡 LiDAR Sensor Parameters
Beam Count (Resolution) 360 beams
Max Range (Distance) 8.0 meters
Gaussian Range Noise (σ) 2.0 cm
Robot Drive Speed 1.6 m/s
🧮 Bayesian Log-Odds Updates
P(Occupied | Hit) 0.85 (l_occ = +1.73)
P(Free | Miss / Ray Traversal) 0.35 (l_free = -0.62)
Grid Map Theme
🗺️ Arena Presets & Reset

📐 Mathematical Theory & Log-Odds Bayesian Mapping

1. The Binary Bayes Filter & Log-Odds

Each cell $m_i$ in an occupancy grid represents a static binary random variable: either occupied ($m_i = 1$) or free ($m_i = 0$). Calculating probability directly requires floating point multiplications that suffer from numerical underflow. We map probability $p(m_i)$ to log-odds representation $l(m_i)$:

l(m_i) = \ln\left(\frac{p(m_i)}{1 - p(m_i)}\right) \iff p(m_i) = 1 - \frac{1}{1 + \exp(l(m_i))}

Under Markov assumptions, recursive Bayesian updates turn into simple scalar additions without Bayes theorem divisions:

l_{t}(m_i) = l_{t-1}(m_i) + \text{inverse\_sensor\_model}(m_i, z_t) - l_0

2. Bresenham Ray-Marching & Inverse Sensor Model

For every LiDAR laser pulse fired at bearing angle $\theta$ with measured distance $r$:

  • Free Space Cells (Miss): Using Bresenham's integer line algorithm, all cells traversed between the sensor origin $(x_{bot}, y_{bot})$ and the beam endpoint $(x_{hit}, y_{hit})$ are updated with negative log-odds: $l_{free} = \ln(p_{free} / (1 - p_{free})) < 0$.
  • Obstacle Surface (Hit): The terminal cell $(x_{hit}, y_{hit})$ receives a positive log-odds increment: $l_{occ} = \ln(p_{occ} / (1 - p_{occ})) > 0$.
  • Clamping Limits: Log-odds are clamped between $[L_{min}, L_{max}] = [-5.0, +5.0]$ to prevent confidence saturation.

3. Exporting to ROS 2 Nav2 Map Server

ROS 2 standard nav2_map_server expects an image (PNG or PGM) and an accompanying metadata YAML file:

# map.yaml format
image: map.png
resolution: 0.05 # 5cm per pixel
origin: [-10.0, -10.0, 0.0]
negate: 0
occupied_thresh: 0.65
free_thresh: 0.196

White pixels represent free traversable space, black represents obstacles/walls, and gray represents unmapped territory.