Skip to content

Context and Randomizer

telekinesis-illusion separates what is in the scene from how the scene varies. The Context holds the scene state – registered models, categories, materials, background, camera. The Randomizer holds the randomizer tree: a directed acyclic graph of nodes, each changing one aspect of that scene. SyntheticDataGenerator runs the loop that randomizes, optionally simulates physics, renders, and writes.

Import

python
from telekinesis.illusion.core.context import Context
from telekinesis.illusion.core.synthetic_data_generator import SyntheticDataGenerator
from telekinesis.illusion.randomizer.randomizer import Randomizer, EdgeConfig
from telekinesis.illusion.randomizer.randomizer_node import NodeConfig

Context

The scene state shared by every randomizer node.

python
context = Context(
    auto_config=True,    # pick a default background HDRI
    camera_config=None,  # CameraConfig, or None for defaults
    asset_dir=None,      # directory holding models/, hdris/, materials/
)

Parameters

ParameterTypeDescription
auto_configboolConfigure the scene for default generation.
camera_configCameraConfig | NoneCamera intrinsics and image resolution. None uses the defaults.
asset_dirstr | Path | NoneDirectory holding models/, hdris/, and materials/. None resolves the bundled default asset directory.

Creating a Context initializes BlenderProc, so a process holds exactly one scene at a time.

Registering Models

add_model() loads a 3D model, assigns it a COCO category, and pre-creates linked duplicates so instance counts can be randomized without reloading geometry.

python
context.add_model(
    model_path,                   # path to the model file
    object_name,                  # unique name within the scene
    category_name=None,           # COCO category name
    category_id=None,             # COCO category id
    min_number_instances=1,
    max_number_instances=1,
    active_in_simulation=False,   # participates in physics
    collision_shape="CONVEX_HULL",  # "CONVEX_HULL" | "MESH"
    scale=1.0,
    preprocess_model=True,
)
ParameterTypeDescription
model_pathstrPath to the 3D model file on disk.
object_namestrUnique name within the scene. Instances are keyed <object_name>_INSTANCE_<n>.
category_namestr | NoneCOCO category name. Defaults to object_name. Use "distractor" together with category_id=None to exclude the model from the annotations.
category_idint | NoneExplicit COCO category id. Assigned automatically when omitted. Several models may share one id to fold multiple meshes into a single class.
min_number_instancesintLower bound on visible instances per scene.
max_number_instancesintUpper bound on visible instances per scene. Determines how many linked duplicates are created.
active_in_simulationboolWhether the model participates in the physics simulation. Containers are typically False.
collision_shapestrCollider type: "CONVEX_HULL" for parts, "MESH" for concave geometry such as bins.
scalefloat | np.ndarrayUniform or per-axis scale applied on import.
preprocess_modelboolWhether to run import-time preprocessing.

Object names must be unique. Registering the same model twice raises a ValueError – increase max_number_instances instead. Category ids and names are kept in a strict one-to-one mapping; providing a combination that conflicts with an existing mapping also raises a ValueError.

Reading the Scene

MethodReturns
get_objects()All registered instances, keyed by instance name.
get_objects_by_name(name)The instance, or the list of instances, whose name contains name.
get_object_group(object_name)Every instance of the model registered under object_name.
get_visible_object_names()Names of the objects currently visible in the scene.
get_camera()The Camera used for rendering.
get_background()The scene Background.
get_categories()The category-id to category-name mapping.
get_asset_dir()The resolved asset directory.

Randomizer

The randomizer tree. Nodes are executed in dependency order, each receiving the Context.

python
randomizer = Randomizer()

randomizer.add_randomizer(
    randomizer_node,     # a RandomizerNode
    node_name,           # unique node name
    node_config=None,    # NodeConfig
    edge_config=None,    # EdgeConfig
)

add_randomizer() appends the node to the chain: the first node becomes the start of the graph, and every subsequent node is added as a successor of the previous one. Execution order is recomputed on every randomize() call using a topological sort, so nodes always run in dependency order.

Methods

MethodDescription
add_randomizer(randomizer_node, node_name, node_config=None, edge_config=None)Append a node to the chain.
add_node(randomizer_node, name, node_config=None)Register a node without connecting it.
add_edge(from_node_name, to_node_name, edge_config=None)Connect two registered nodes.
get_randomizer_node(node_name)The node registered under node_name, or None.
replace_randomizer(node_name, randomizer_node)Swap a node's implementation, leaving the graph topology and node config untouched.
get_node_stages()The stage each registered node belongs to, keyed by node name.
randomize(context, stages=None)Execute the tree over context.

replace_randomizer() is what interactive tools use to re-tune a node's parameters between runs without rebuilding the scene. The Blender extension relies on it for live preview.

NodeConfig

Per-node execution metadata, passed as node_config.

FieldTypeDefaultDescription
enabledboolTrueWhether the node runs at all. Disabled nodes are skipped.
stagestrSTAGE_DEFAULTThe stage this node belongs to (see below).
priorityint0Reserved for ordering within a stage.
seed_keystr | NoneNoneReserved for per-node seeding.
apply_probfloat1.0Reserved for probabilistic application.
max_triesint1Reserved for node-level retries.
on_failurestr"raise"Reserved failure behavior: "raise", "skip_node", or "skip_sample".
profileboolFalseReserved for per-node profiling.

EdgeConfig currently carries a single enabled flag for an edge.

Stages

Stages group nodes by which part of the scene they change, so a caller can re-run only part of the tree.

StageConstantCovers
"composition"STAGE_COMPOSITIONWhich and how many instances are visible.
"pose"STAGE_POSEWhere the visible objects are placed.
"appearance"STAGE_APPEARANCEMaterials and the background HDRI.
"camera"STAGE_CAMERACamera pose sampling.
"default"STAGE_DEFAULTAssigned when a node opts into no stage. Never filtered out.

A node left at STAGE_DEFAULT runs in every pass, so a node that does not opt into a stage is never skipped by accident.

python
from telekinesis.illusion.randomizer.randomizer_node import (
    NodeConfig,
    STAGE_POSE,
    STAGE_CAMERA,
)

randomizer.add_randomizer(
    randomizer_node=object_pose_randomizer,
    node_name="pose_randomizer",
    node_config=NodeConfig(stage=STAGE_POSE),
)

# Re-sample geometry only: poses and camera, keeping materials and selection
randomizer.randomize(context, stages={STAGE_POSE, STAGE_CAMERA})

# A full generation run passes no stages, so everything executes
randomizer.randomize(context)

SyntheticDataGenerator

The generation loop: randomize, optionally simulate physics, render, write.

python
generator = SyntheticDataGenerator(context, randomizer, writer)

generator.generate(
    num_images=5,
    simulate_physics=False,
    min_simulation_time_range=(0.5, 1.0),
    max_simulation_time_range=(2.0, 5.0),
    save_blender_scene=False,
    clean_up_scene=True,
    render_max_retries=2,
)

Parameters

ParameterTypeDescription
num_imagesintNumber of scenes to render.
simulate_physicsboolWhether to settle the objects with a physics simulation before rendering each scene.
min_simulation_time_rangetuple[float, float]Range, in simulated seconds, the minimum simulation time is sampled from.
max_simulation_time_rangetuple[float, float]Range, in simulated seconds, the maximum simulation time is sampled from.
check_object_intervalfloatInterval, in simulated seconds, at which objects are checked for having come to rest.
object_stopped_location_thresholdfloatMaximum location change, in meters, allowed between checks for an object to count as at rest.
object_stopped_rotation_thresholdfloatMaximum rotation change, in radians, allowed between checks for an object to count as at rest.
substeps_per_frameintPhysics substeps computed per simulation frame.
solver_itersintSolver iterations used by the physics simulation.
use_volume_comboolCompute the center of mass from object volume instead of mesh vertices.
verboseboolVerbose logging from the physics simulation.
save_blender_sceneboolSave the first scene as a .blend file, for debugging.
clean_up_sceneboolClean up the scene after generation. Set to False when generating in a loop, as workers do.
render_max_retriesintRetries after a transient render failure before the error is raised.

Rendering targets an NVIDIA GPU through OptiX, and segmentation output is enabled for category_id, instance, and name, which is what produces the instance masks in the annotations.

Randomizer Nodes
The individual axes of variation: instance count, object pose, material, background, and camera pose.
Read more →