ModelPoseRandomizer
SUMMARY
Places the visible models. You write the pose function, a few lines of NumPy that set one model's location and rotation, and the node calls it for each target model, retrying until the model no longer collides with the others.
Usage
import numpy as np
from telekinesis.illusion import config
from telekinesis.illusion.randomizer.randomizer_node import ModelPoseRandomizer
from telekinesis.illusion.types.model import Model
def sample_pose(model: Model) -> None:
model.set_location(np.random.uniform((-0.1, -0.1, 0.05), (0.1, 0.1, 0.2))) # meters
model.set_rotation(np.random.uniform(-np.pi, np.pi, size=3)) # radians
randomizer.add(
ModelPoseRandomizer(config.ModelPoseRandomizerConfig(max_tries=20), sample_pose, target_models=["gear"]),
"poses",
)For each visible instance whose name starts with "gear", the node calls sample_pose and checks the result against the other target models. On a collision it samples again, up to max_tries times.
Constructor
ModelPoseRandomizer(randomizer_config, pose_sampling_function, target_models=(), surface_name_resolver=None)
| Parameter | Description |
|---|---|
randomizer_config | A ModelPoseRandomizerConfig. |
pose_sampling_function | Callable[[Model], None] that sets the model's pose. |
target_models | Instance-name prefixes to place. Empty places every visible model. |
surface_name_resolver | Optional Callable[[Environment], str] that returns the surface model name per scene, used when sample_on_surface is not set. |
ModelPoseRandomizerConfig
| Field | Type | Default | Description |
|---|---|---|---|
max_tries | int | 10 | Attempts per model before giving up on a collision-free pose. |
sample_on_surface | str | None | None | Name (or part of the name) of a model to place the targets on, such as a bin or a table. |
Placing Models on a Surface
ModelPoseRandomizer(config.ModelPoseRandomizerConfig(sample_on_surface="plastic_bin"), sample_pose, ["gear"])With sample_on_surface, the targets are positioned above the named model's surface, spaced apart. They end up hovering slightly above it, so combine this with physics (PhysicsConfig(active=True)) to let them fall and settle into realistic contact. A model that cannot be placed is hidden, so it is neither rendered nor annotated. Physics Based Synthetic Dataset Generation shows the simpler alternative: a pose function that drops the parts above the bin, with physics doing the rest.
Useful Model methods inside a pose function
set_location(xyz) (meters), set_rotation(euler_xyz) (radians), get_location(), get_rotation(), set_scale(scale), get_bound_box() (8 world-space corners) and get_name(), for example to give different parts different height ranges.