CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-pybullet

Official Python Interface for the Bullet Physics SDK specialized for Robotics Simulation and Reinforcement Learning

Pending
Overview
Eval results
Files

state-management-logging.mddocs/

State Management and Logging

Save and restore simulation states, log data for analysis, and manage user-defined data attachments. Essential for reproducible experiments, data collection, and simulation checkpointing.

Capabilities

State Management

def saveState(physicsClientId=0):
    """
    Save complete world state to memory.
    
    Args:
        physicsClientId (int, optional): Physics client ID
    
    Returns:
        int: State unique ID for later restoration
    """

def restoreState(stateId, fileName=None, physicsClientId=0):
    """
    Restore world state from saved state ID or file.
    
    Args:
        stateId (int): State unique ID (if restoring from memory)
        fileName (str, optional): File name (if restoring from file)
        physicsClientId (int, optional): Physics client ID
    """

def removeState(stateId, physicsClientId=0):
    """
    Remove saved state from memory.
    
    Args:
        stateId (int): State unique ID to remove
        physicsClientId (int, optional): Physics client ID
    """

def loadBullet(bulletFileName, physicsClientId=0):
    """
    Load world state from .bullet file.
    
    Args:
        bulletFileName (str): Path to .bullet file
        physicsClientId (int, optional): Physics client ID
    
    Returns:
        list: List of loaded object IDs
    """

def saveBullet(bulletFileName, physicsClientId=0):
    """
    Save complete world state to .bullet file.
    
    Args:
        bulletFileName (str): Output .bullet file path
        physicsClientId (int, optional): Physics client ID
    """

def saveWorld(worldFileName, physicsClientId=0):
    """
    Save world as approximate Python script.
    
    Args:
        worldFileName (str): Output Python file path
        physicsClientId (int, optional): Physics client ID
    """

Data Logging

def startStateLogging(loggingType, fileName, objectUniqueIds=None, maxLogDof=None, bodyUniqueIdA=None, bodyUniqueIdB=None, linkIndexA=None, linkIndexB=None, physicsClientId=0):
    """
    Start logging simulation data to file.
    
    Args:
        loggingType (int): Type of logging (STATE_LOGGING_VIDEO_MP4, etc.)
        fileName (str): Output file name
        objectUniqueIds (list, optional): Objects to log
        maxLogDof (int, optional): Maximum degrees of freedom to log
    
    Returns:
        int: Logging unique ID
    """

def stopStateLogging(loggingUniqueId, physicsClientId=0):
    """
    Stop data logging.
    
    Args:
        loggingUniqueId (int): Logging unique ID from startStateLogging
        physicsClientId (int, optional): Physics client ID
    """

User Data Management

def addUserData(bodyUniqueId, key, value, linkIndex=-1, visualShapeIndex=-1, physicsClientId=0):
    """
    Add or update user data entry for object.
    
    Args:
        bodyUniqueId (int): Object unique ID
        key (str): Data key identifier
        value (str): Data value
        linkIndex (int, optional): Link index (-1 for base)
        visualShapeIndex (int, optional): Visual shape index
        physicsClientId (int, optional): Physics client ID
    
    Returns:
        int: User data unique ID
    """

def getUserData(userDataId, physicsClientId=0):
    """
    Get user data value by ID.
    
    Args:
        userDataId (int): User data unique ID
        physicsClientId (int, optional): Physics client ID
    
    Returns:
        str: User data value
    """

def getUserDataId(bodyUniqueId, key, linkIndex=-1, visualShapeIndex=-1, physicsClientId=0):
    """
    Get user data ID by key.
    
    Args:
        bodyUniqueId (int): Object unique ID
        key (str): Data key identifier
        linkIndex (int, optional): Link index
        visualShapeIndex (int, optional): Visual shape index
        physicsClientId (int, optional): Physics client ID
    
    Returns:
        int: User data unique ID
    """

def removeUserData(userDataId, physicsClientId=0):
    """
    Remove user data entry.
    
    Args:
        userDataId (int): User data unique ID
        physicsClientId (int, optional): Physics client ID
    """

def getNumUserData(bodyUniqueId, physicsClientId=0):
    """
    Get number of user data entries for object.
    
    Args:
        bodyUniqueId (int): Object unique ID
        physicsClientId (int, optional): Physics client ID
    
    Returns:
        int: Number of user data entries
    """

def getUserDataInfo(bodyUniqueId, userDataIndex, physicsClientId=0):
    """
    Get user data information by index.
    
    Args:
        bodyUniqueId (int): Object unique ID
        userDataIndex (int): User data index (0 to getNumUserData-1)
        physicsClientId (int, optional): Physics client ID
    
    Returns:
        tuple: (userDataId, key, bodyUniqueId, linkIndex, visualShapeIndex)
    """

def syncUserData(bodyUniqueIds=None, physicsClientId=0):
    """
    Synchronize user data from server.
    
    Args:
        bodyUniqueIds (list, optional): Specific objects to sync
        physicsClientId (int, optional): Physics client ID
    """

Usage Examples

State Save and Restore

import pybullet as p
import time

p.connect(p.GUI)
p.setGravity(0, 0, -9.81)

# Set up initial scene
p.loadURDF("plane.urdf")
cube_id = p.loadURDF("cube_small.urdf", [0, 0, 1])
robot_id = p.loadURDF("r2d2.urdf", [1, 0, 1])

# Simulate for a while
for i in range(100):
    p.stepSimulation()
    time.sleep(1./240.)

# Save current state
state_id = p.saveState()
print(f"Saved state with ID: {state_id}")

# Continue simulation and make changes
p.applyExternalForce(cube_id, -1, [10, 0, 0], [0, 0, 0], p.WORLD_FRAME)
for i in range(100):
    p.stepSimulation()
    time.sleep(1./240.)

cube_pos, _ = p.getBasePositionAndOrientation(cube_id)
print(f"Cube position after force: {cube_pos}")

# Restore to saved state
p.restoreState(state_id)

# Verify restoration
cube_pos_restored, _ = p.getBasePositionAndOrientation(cube_id)
print(f"Cube position after restore: {cube_pos_restored}")

# Clean up
p.removeState(state_id)

File-based State Management

import pybullet as p

p.connect(p.GUI)
p.setGravity(0, 0, -9.81)

# Create scene
plane_id = p.loadURDF("plane.urdf")
cube_id = p.loadURDF("cube_small.urdf", [0, 0, 1])

# Save to file
p.saveBullet("my_simulation.bullet")
print("Saved simulation to bullet file")

# Save as Python script (approximate)
p.saveWorld("recreate_simulation.py")
print("Saved world recreation script")

# Reset and load from file
p.resetSimulation()
loaded_objects = p.loadBullet("my_simulation.bullet")
print(f"Loaded objects: {loaded_objects}")

Data Logging

import pybullet as p
import time

p.connect(p.GUI)
p.setGravity(0, 0, -9.81)

# Set up scene
plane_id = p.loadURDF("plane.urdf")
robot_id = p.loadURDF("r2d2.urdf", [0, 0, 1])

# Start video logging
video_log = p.startStateLogging(
    loggingType=p.STATE_LOGGING_VIDEO_MP4,
    fileName="simulation_video.mp4"
)

# Start generic robot state logging
robot_log = p.startStateLogging(
    loggingType=p.STATE_LOGGING_GENERIC_ROBOT,
    fileName="robot_states.txt",
    objectUniqueIds=[robot_id],
    maxLogDof=7
)

# Run simulation with logging
num_joints = p.getNumJoints(robot_id)
joint_indices = list(range(num_joints))

for step in range(500):
    # Apply some control
    if num_joints > 0:
        target_positions = [0.1 * step * ((-1) ** i) for i in range(num_joints)]
        p.setJointMotorControlArray(
            robot_id, joint_indices, p.POSITION_CONTROL,
            targetPositions=target_positions
        )
    
    p.stepSimulation()
    time.sleep(1./240.)

# Stop logging
p.stopStateLogging(video_log)
p.stopStateLogging(robot_log)
print("Logging completed")

User Data Management

import pybullet as p

p.connect(p.GUI)
plane_id = p.loadURDF("plane.urdf")
robot_id = p.loadURDF("r2d2.urdf", [0, 0, 1])

# Add user data to robot
metadata_id = p.addUserData(robot_id, "robot_type", "R2-D2")
config_id = p.addUserData(robot_id, "max_speed", "2.5")
author_id = p.addUserData(robot_id, "created_by", "Luke Skywalker")

# Retrieve user data
robot_type = p.getUserData(metadata_id)
max_speed = p.getUserData(config_id)
print(f"Robot type: {robot_type}, Max speed: {max_speed}")

# Find user data by key
speed_id = p.getUserDataId(robot_id, "max_speed")
speed_value = p.getUserData(speed_id)
print(f"Found max_speed: {speed_value}")

# List all user data
num_data = p.getNumUserData(robot_id)
print(f"Robot has {num_data} user data entries:")

for i in range(num_data):
    data_info = p.getUserDataInfo(robot_id, i)
    data_id, key, body_id, link_idx, shape_idx = data_info
    value = p.getUserData(data_id)
    print(f"  {key}: {value}")

# Remove user data
p.removeUserData(config_id)
print(f"Removed max_speed data, now has {p.getNumUserData(robot_id)} entries")

# Sync user data (useful in multi-client scenarios)
p.syncUserData([robot_id])

Logging Types and Constants

# State logging types
p.STATE_LOGGING_VIDEO_MP4           # MP4 video recording
p.STATE_LOGGING_GENERIC_ROBOT       # Robot state data
p.STATE_LOGGING_CONTACT_POINTS      # Contact point information
p.STATE_LOGGING_VR_CONTROLLERS      # VR controller states
p.STATE_LOGGING_MINITAUR            # Minitaur-specific logging

Best Practices

  1. Memory Management - Remove unused saved states to prevent memory leaks
  2. File Organization - Use descriptive names for saved files and organize by experiment
  3. Logging Efficiency - Only log necessary data to minimize file sizes and performance impact
  4. State Validation - Verify state restoration worked correctly before continuing simulation
  5. User Data Structure - Use consistent key naming conventions for user data
  6. Backup Strategy - Save critical states to files for permanent storage
  7. Multi-client Sync - Use sync functions when multiple clients modify the same simulation

Install with Tessl CLI

npx tessl i tessl/pypi-pybullet

docs

collision-detection.md

connection-simulation.md

index.md

inverse-kinematics-dynamics.md

joint-motor-control.md

mathematical-utilities.md

object-loading.md

physics-configuration.md

rendering-visualization.md

state-management-logging.md

vr-input-handling.md

tile.json