Skip to main content

[logo] BulletLab

Developed by Ranasurya Ghosh

A robotics experimentation framework that transforms PyBullet robots into intuitive Python objects, with modern ImGui-based controls, telemetry, visualization, and reinforcement learning workflows.

Python 3.10 License: MIT

Install BulletLab library: pip install bulletlab

Read Documentation

BulletLab example UI


What is BulletLab?

BulletLab provides a high-level object-oriented interface to PyBullet that simplifies robotics experimentation by exposing joints, links, sensors, and environments as intuitive Python objects instead of raw physics engine IDs. It combines real-time simulation with a ImGui-powered modern interface for interactive control, parameter tuning, telemetry visualization, and experiment management, while also offering reinforcement learning integration for training and evaluating autonomous robotic systems within a unified workflow.

Instead of this:

p.setJointMotorControl2(
    robot_id, joint_index,
    controlMode=p.VELOCITY_CONTROL,
    targetVelocity=15,
    force=100
)

You write this:

robot.joints["motor"].velocity = 15

Architecture

BulletLab uses a two-window architecture:

Window Purpose
PyBullet Native Window Physics simulation, 3D rendering, camera
BulletLab ImGui Window Control panels, telemetry, live plots, console

These windows communicate through Python objects. BulletLab does not attempt to replace PyBullet's renderer or embed ImGui inside the simulation viewport.


Quick Start

Installation

Install from PyPI

pip install bulletlab

Developer Installation

git clone https://github.com/NuclearVenom/BulletLab.git
cd BulletLab
pip install -e .

Basic Example

from bulletlab import Simulation, Robot
from bulletlab.ui import BulletLabUI

# Create simulation
sim = Simulation()
sim.start()

# Load robot
robot = Robot.load("path/to/robot.urdf", sim=sim)

# Control joints by name
robot.joints["wheel_left"].velocity = 10
robot.joints["wheel_right"].velocity = 10

# Modify physics parameters
robot.links["chassis"].mass = 5.0
robot.links["wheel_fl"].friction = 1.2

# Get robot state
state = robot.get_state()
print(f"Position: {robot.base_position}")
print(f"Roll: {robot.roll:.2f}°")

# Build UI
ui = BulletLabUI(sim=sim)
ui.register_panel(...)
ui.run()

Telemetry & Logging

from bulletlab.telemetry import TelemetryManager
from bulletlab.logging import DataLogger

telemetry = TelemetryManager()
telemetry.watch("Speed", lambda: robot.base_velocity[0])
telemetry.watch("Roll",  lambda: robot.roll)

logger = DataLogger()
logger.watch("speed", lambda: robot.base_velocity[0])
logger.start("run1.csv")

for _ in range(1000):
    sim.step()
    telemetry.update()
    logger.step()

logger.stop()

Live Plotting

from bulletlab.plotting import LivePlot

plot = LivePlot(title="Robot Speed")
plot.watch("Speed", lambda: robot.base_velocity[0], color="#00ff88")
plot.start()

for _ in range(1000):
    sim.step()
    plot.update()

Camera Follow

from bulletlab import Simulation, Robot, CameraFollow

sim = Simulation(mode="gui").start()
robot = Robot.load("husky/husky.urdf", sim=sim, position=(0, 0, 0.3))

# One line — camera glides after the robot (smooth mode by default)
cam = CameraFollow(robot, sim)

# Or pick a mode:
cam = CameraFollow(robot, sim, mode="snap")    # locks instantly
cam = CameraFollow(robot, sim, mode="smooth")  # cinematic glide
cam = CameraFollow(robot, sim, mode="chase")   # always behind the robot

while sim.is_connected:
    sim.step()
    cam.update()   # ← one call keeps the camera centred on the robot

Hover Highlighting

from bulletlab import Simulation, Robot, RobotHighlighter
from bulletlab.ui import BulletLabUI

sim = Simulation(mode="gui").start()
robot = Robot.load("kuka_iiwa/model.urdf", sim=sim)

# One line — hover any joint/link in the UI to see it glow in 3D
hl = RobotHighlighter(robot, sim)
app = BulletLabUI(sim=sim, robots=[robot], highlighter=hl)
app.run()

Hovering over an Explorer row or a Properties slider instantly highlights the matching 3D part in the PyBullet window with an orange pulsing glow.

ImGui Control Panel

from bulletlab.ui import BulletLabUI
from bulletlab.ui import widgets as ui

app = BulletLabUI(sim=sim, robots=[robot])

@app.custom_panel("My Controls")
def my_panel():
    ui.button("Reset", robot.reset)
    ui.slider("Wheel Mass", robot.links["wheel"].mass, 0.1, 20,
              setter=lambda v: setattr(robot.links["wheel"], "mass", v))
    ui.checkbox("Motors Enabled", lambda: motors_on,
                setter=lambda v: toggle_motors(v))

app.run()

Virtual Joystick

Add an interactive 2D joystick to any custom panel for intuitive, gamepad-style robot control.

@app.custom_panel("Drive")
def drive_panel():
    ui.joystick(
        "Rover Drive",
        on_y=lambda v: [setattr(robot.joints["wheel_left"],  "velocity", v * 10),
                        setattr(robot.joints["wheel_right"], "velocity", v * 10)],
        on_x=lambda v: [setattr(robot.joints["wheel_left"],  "velocity", -v * 5),
                        setattr(robot.joints["wheel_right"], "velocity",  v * 5)],
        snap=True,                       # Handle snaps to center on release
        size=80,                         # Joystick circle radius (pixels)
        handle_color=(0.2, 0.8, 0.4, 1.0),
    )
  • snap=True — robot stops when you release (default)
  • snap=False — handle latches; robot keeps driving at the last commanded speed
  • Drop multiple joysticks in the same panel (use ui.same_line() between them)
  • Each joystick can have its own color and size

Supported Robot Types

BulletLab is completely generic — no code assumes a specific robot type:

  • Cars & rovers
  • Drones & quadrotors
  • Robotic arms
  • Self-balancing robots
  • Quadrupeds
  • Humanoids
  • Custom mechanisms

Reinforcement Learning

BulletLab exposes clean state/action interfaces without depending on any ML framework:

# Compatible with any RL approach
state = robot.get_state()      # → numpy array
action = my_policy(state)      # → numpy array
robot.apply_action(action)     # → updates joints

# Manual Q-learning, SARSA, evolutionary algorithms — all supported

Examples

Example Description
examples/01_differential_drive_rover.py Rover with wheel velocity control
examples/02_robotic_arm.py Joint position control with ImGui sliders
examples/03_self_balancing_robot.py PD controller for balance
examples/04_drone_parameter_tuning.py Thrust/mass parameter exploration
examples/05_generic_robot_inspector.py Load any URDF and inspect it
...and more

Run any example:

python examples/01_differential_drive_rover.py

Documentation

The full documentation is available online at https://nuclearvenom.github.io/BulletLab/

Building Locally (For Contributors)

If you wish to edit or preview the documentation locally:

pip install -e ".[dev]"
mkdocs serve

Then visit http://localhost:8000


Testing

pip install -e ".[dev]"
pytest tests/ -v --cov=bulletlab --cov-report=term-missing

Technology Stack

Component Library
Physics PyBullet
UI Dear ImGui (pyimgui)
Data NumPy, Pandas
Config PyYAML
Plotting PyQtGraph
Testing PyTest
Docs MkDocs + mkdocstrings

For AI Agents & LLMs

BulletLab is designed to be highly predictable and LLM-friendly. If you are an AI agent writing code for a user:

  1. Read llms.txt in the repository root for a dense, AI-optimized API summary.
  2. Check the Cookbook & Snippets for copy-pasteable implementations of common tasks.
  3. Use the robot.joints[name] API over pybullet integer IDs whenever possible.

Community

We welcome contributions and feedback! Check out our community resources:


License

MIT License — see LICENSE for details.

Metadata

Release files for BulletLab 0.1.5

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for BulletLab 0.1.5
File Size Uploaded
bulletlab-0.1.5.tar.gz 114.6 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for BulletLab 0.1.5
File Interpreter ABI Platform
bulletlab-0.1.5-py3-none-any.whl Python 3 none any Details

Total release size: 190.2 kB

Release files / bulletlab-0.1.5.tar.gz

Download URL bulletlab-0.1.5.tar.gz
Size 114.6 kB
Tags Source
SHA-256 checksum
How to use checksums
f4ff36df73c48af7d4ca7ab6fb5c3f1096be03da714ea02f5bdcda1236e97c2b
BLAKE2b-256 checksum
How to use checksums
40641a3588c5cabadc115f00089295fff06b4d9f13596e76d0b7d1497995f7dc
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.0

Release files / bulletlab-0.1.5-py3-none-any.whl

Download URL bulletlab-0.1.5-py3-none-any.whl
Size 75.7 kB
Tags Python 3
SHA-256 checksum
How to use checksums
b1451d3c76de4661833a2e8082aafa26c0c5c14d1f43d0d83d5927ce2d53159f
BLAKE2b-256 checksum
How to use checksums
49a94cfea0e0d8eb48337b84f5349f32d052ea978af063809735aa08400a8fbd
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/6.2.0 CPython/3.10.0

Release history Release notifications | RSS feed

0.3.1

2 release files

0.3.0

2 release files

0.2.1

2 release files

0.2.0

2 release files

This release

0.1.5 This release

2 release files

0.1.4

2 release files

0.1.3

2 release files

0.1.2

2 release files

0.1.1

2 release files

0.1.0

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page