UI Guide
The BulletLab UI is a separate Dear ImGui window that runs alongside the PyBullet simulation window.
Architecture
┌─────────────────────────┐ ┌──────────────────────────────┐
│ PyBullet Window │ │ BulletLab ImGui Window │
│ • Physics simulation │ │ • Explorer Panel │
│ • 3D rendering │ │ • Properties Panel │
│ • Camera controls │ │ • Telemetry Panel │
│ │ │ • Console Panel │
│ │ │ • Plots Panel │
│ │ │ • Custom Panels │
└─────────────────────────┘ └──────────────────────────────┘
communicate via Python objects
Basic Usage
from bulletlab.ui import BulletLabUI
from bulletlab.telemetry import TelemetryManager
telemetry = TelemetryManager()
telemetry.watch("Speed", lambda: robot.speed)
app = BulletLabUI(sim=sim, robots=[robot], telemetry=telemetry)
app.run() # blocking
Non-Blocking Usage
app = BulletLabUI(sim=sim, robots=[robot])
app.start()
while True:
sim.step()
telemetry.update(t=sim.elapsed_time)
app.step()
if app.should_close:
break
app.stop()
Built-in Panels
| Panel | Purpose |
|---|---|
| Explorer | Scene tree: Simulation → Robots → Joints/Links |
| Properties | Editable properties for selected object |
| Telemetry | Live key-value table |
| Plots | Inline sparkline charts |
| Console | Interactive Python REPL |
Custom Panels
Using the decorator
from bulletlab.ui import BulletLabUI
from bulletlab.ui import widgets as ui
app = BulletLabUI(sim=sim, robots=[robot])
@app.custom_panel("Motor Control")
def motor_panel():
ui.text("Robot", robot.name)
ui.separator()
ui.slider("Left Wheel", lambda: robot.joints["wheel_l"].velocity, -20, 20,
setter=lambda v: setattr(robot.joints["wheel_l"], "velocity", v))
ui.slider("Right Wheel", lambda: robot.joints["wheel_r"].velocity, -20, 20,
setter=lambda v: setattr(robot.joints["wheel_r"], "velocity", v))
ui.separator()
ui.button("Stop All", lambda: [setattr(j, "velocity", 0) for j in robot.controllable_joints])
app.run()
Using register_panel
Widget Reference
| Function | Description |
|---|---|
ui.button(label, callback) |
Clickable button |
ui.text(label, value) |
Read-only text field |
ui.slider(label, getter, min, max, setter) |
Float slider |
ui.drag_float(label, getter, setter, speed) |
Drag-to-edit field |
ui.input_float(label, getter, setter) |
Float input box |
ui.checkbox(label, getter, setter) |
Boolean toggle |
ui.color_edit(label, getter, setter) |
RGB color picker |
ui.combo(label, items, getter, setter) |
Dropdown list |
ui.collapsing_header(label) |
Collapsible section |
ui.separator(label) |
Horizontal divider |
ui.tooltip(text) |
Hover tooltip |
Console Panel
The console provides an interactive Python REPL inside the UI:
# Example commands you can type in the console:
robot.links["wheel"].mass = 10
robot.joints["motor"].velocity = 15
print(robot.base_position)
sim.pause()
The console namespace includes sim, robot (first robot), and telemetry by default.