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
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 NodeConfigContext
The scene state shared by every randomizer node.
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
| Parameter | Type | Description |
|---|---|---|
auto_config | bool | Configure the scene for default generation. |
camera_config | CameraConfig | None | Camera intrinsics and image resolution. None uses the defaults. |
asset_dir | str | Path | None | Directory 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.
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,
)| Parameter | Type | Description |
|---|---|---|
model_path | str | Path to the 3D model file on disk. |
object_name | str | Unique name within the scene. Instances are keyed <object_name>_INSTANCE_<n>. |
category_name | str | None | COCO category name. Defaults to object_name. Use "distractor" together with category_id=None to exclude the model from the annotations. |
category_id | int | None | Explicit COCO category id. Assigned automatically when omitted. Several models may share one id to fold multiple meshes into a single class. |
min_number_instances | int | Lower bound on visible instances per scene. |
max_number_instances | int | Upper bound on visible instances per scene. Determines how many linked duplicates are created. |
active_in_simulation | bool | Whether the model participates in the physics simulation. Containers are typically False. |
collision_shape | str | Collider type: "CONVEX_HULL" for parts, "MESH" for concave geometry such as bins. |
scale | float | np.ndarray | Uniform or per-axis scale applied on import. |
preprocess_model | bool | Whether 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
| Method | Returns |
|---|---|
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.
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
| Method | Description |
|---|---|
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.
| Field | Type | Default | Description |
|---|---|---|---|
enabled | bool | True | Whether the node runs at all. Disabled nodes are skipped. |
stage | str | STAGE_DEFAULT | The stage this node belongs to (see below). |
priority | int | 0 | Reserved for ordering within a stage. |
seed_key | str | None | None | Reserved for per-node seeding. |
apply_prob | float | 1.0 | Reserved for probabilistic application. |
max_tries | int | 1 | Reserved for node-level retries. |
on_failure | str | "raise" | Reserved failure behavior: "raise", "skip_node", or "skip_sample". |
profile | bool | False | Reserved 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.
| Stage | Constant | Covers |
|---|---|---|
"composition" | STAGE_COMPOSITION | Which and how many instances are visible. |
"pose" | STAGE_POSE | Where the visible objects are placed. |
"appearance" | STAGE_APPEARANCE | Materials and the background HDRI. |
"camera" | STAGE_CAMERA | Camera pose sampling. |
"default" | STAGE_DEFAULT | Assigned 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.
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.
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
| Parameter | Type | Description |
|---|---|---|
num_images | int | Number of scenes to render. |
simulate_physics | bool | Whether to settle the objects with a physics simulation before rendering each scene. |
min_simulation_time_range | tuple[float, float] | Range, in simulated seconds, the minimum simulation time is sampled from. |
max_simulation_time_range | tuple[float, float] | Range, in simulated seconds, the maximum simulation time is sampled from. |
check_object_interval | float | Interval, in simulated seconds, at which objects are checked for having come to rest. |
object_stopped_location_threshold | float | Maximum location change, in meters, allowed between checks for an object to count as at rest. |
object_stopped_rotation_threshold | float | Maximum rotation change, in radians, allowed between checks for an object to count as at rest. |
substeps_per_frame | int | Physics substeps computed per simulation frame. |
solver_iters | int | Solver iterations used by the physics simulation. |
use_volume_com | bool | Compute the center of mass from object volume instead of mesh vertices. |
verbose | bool | Verbose logging from the physics simulation. |
save_blender_scene | bool | Save the first scene as a .blend file, for debugging. |
clean_up_scene | bool | Clean up the scene after generation. Set to False when generating in a loop, as workers do. |
render_max_retries | int | Retries 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.

