An interactive rollercoaster / marble run simulation on a WS2812 LED strip using physics (gravity, friction, and collision) driven by Python and pyledstrip.
This software simulates virtual particles (marbles) moving along a physical path (e.g. wrapped around a marble run or spiral column) defined by a 2D heightmap layout.
graph TD
WebClient[Web Browser Client] -- HTTP / POST /launch --> PyWebServer[Python Web Server webserver.py]
PyWebServer -- Launches --> PhysicsSim[Physics Simulation particles.py]
PhysicsSim -- Heightmap coordinates --> LEDWorld[LedWorld Map pyledstrip-detector]
PhysicsSim -- UDP commands --> LEDStrip[ESP8266 WS2812 LED Strip]
- Realistic Physics engine:
- Gravity & Slope Acceleration: Particles accelerate/decelerate depending on the slope of the track at their current position (extracted from the heightmap).
- Friction & Drag: Includes friction coefficient and velocity-based damping.
- Elastic Collisions: Particles bounce off each other realistically based on their mass (represented by particle radius) and velocity.
- Web-based Launcher: A mobile-friendly web interface allows users to swipe (or click-and-drag) to launch virtual particles onto the LED strip with customized hue, speed, and direction.
- Dynamic Brightness & Hue: Particle brightness and visual tail length adapt in real-time according to their current velocity and remaining Time-To-Live (TTL).
This simulation depends on:
- pyledstrip — python interface for sending color data to the LED strip.
- pyledstrip-detector — specifically the
ledworldmodule to load coordinate configurations.
Ensure these modules are available in your python environment (e.g., cloned in adjacent directories and included in your PYTHONPATH).
-
Clone this repository:
git clone https://github.com/ledstrip/pyledstrip-particles.git cd pyledstrip-particles -
Make sure you have your heightmap JSON file ready. The heightmap maps each LED ID to its spatial coordinates (
x,y,zor height representation).
Launch the particle simulation by supplying the path to your heightmap:
python3 particles.py path/to/heightmap.json [options]heightmap: (Required) Path to the heightmap JSON file.--show: Visualize the track heightmap directly on the LED strip (renders heights with stretched color gradients).- Additional
pyledstriparguments (such as host/IP of the ESP8266/ESP32, led count, power limits, etc.) can also be passed.
When the simulation starts, a web server is hosted on port 8000.
- Open your browser and navigate to
http://localhost:8000/. - Swipe up or down to launch a particle in the corresponding direction.
- Swipe/drag faster to launch the particle with higher initial velocity.
- Use the gradient bar at the bottom to choose the hue/color of the next particle.
The physics loop runs at approximately 100Hz:
-
Slope & Gravity:
$a_{\text{slope}} = g \cdot \sin(\theta)$ where$\theta$ is the slope angle calculated from the heightmap height difference between adjacent LEDs. -
Friction:
$a_{\text{friction}} = \mu \cdot g \cdot \cos(\theta) \cdot \text{sgn}(v)$ to oppose motion. -
Drag: Air resistance / damping is modeled as
$-0.22 \cdot v$ . -
Collisions: Calculated using the conservation of momentum and kinetic energy for elastic collisions:
$$v_1' = \frac{m_1 v_1 + m_2 (2v_2 - v_1)}{m_1 + m_2}$$ $$v_2' = \frac{m_2 v_2 + m_1 (2v_1 - v_2)}{m_1 + m_2}$$ where particle mass ($m$ ) is proportional to its radius.
This project is open-source. Please refer to the organization rules or LICENSE if present.