embodichain.lab.sim.motion.expansion#
The embodichain.lab.sim.motion.expansion package provides
qpos contracts, constrained trajectory operators, measured coverage, and a
expansion session for simulation expert trajectories. The core algorithms do
not directly import Gym or own simulation stepping. Public imports pass through
embodichain.lab and embodichain.lab.sim initialization and therefore
require the normal simulation dependencies.
This is the motion core for fixed-scene expert expansion. Physical initial-state restoration, planning, rollout execution, task validation, and episode persistence must be supplied by separate host integrations. Those integrations provide actual observations and commands, validation evidence, and persistence confirmations; this package does not instantiate them.
Candidate lineage independent of execution slots and their epochs. |
|
Complete episode recipe; identity is independent of simulator row. |
|
Requested affordance and trajectory ordinals for one workflow call. |
|
One recipe reserved on one compatible physical slot. |
|
Bounded FIFO coordinator for recipe assignment and slot cleanup. |
|
Validated input for one transactional candidate identity allocation. |
|
Source-neutral physical candidate lineage before slot assignment. |
|
Generate source-neutral candidates without owning physical execution. |
|
One logical candidate ready for planning validation or slot assignment. |
|
Logical candidate rows with safe padding and no physical batch assumption. |
|
Sink confirmation tied to stable episode/candidate IDs, never a slot. |
|
Frozen rollout evidence with causal |
|
One copied complete robot state; poses map local frames into the world. |
|
A fixed scene and allowed initial state, with no live environment references. |
|
Local random seed, explicitly enabled factors, and geometry coverage limits. |
|
Source-neutral expansion settings shared by every expert source. |
|
Standalone expansion job configuration; control periods remain host-owned. |
|
Strict episode-level profile for the combined showcase. |
|
One immutable legal initial cube pose and its authored targets. |
|
Return deterministic authored cube pose families for a expansion job. |
|
Requested affordance and trajectory ordinals for one Pick/Place cycle. |
|
Fail-closed validator for measured episode and three-cycle evidence. |
|
Generic compatible-slot reservation with exact release semantics. |
|
Opaque reservation returned by |
|
Resolved visual operations for one physical episode. |
|
Load seedable visual profiles from a strict YAML file. |
|
Built-in immutable sequence. |
|
An explicitly annotated half-open sample interval |
|
A full-joint qpos reference with arrival intervals and explicit permissions. |
|
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str |
|
Per-phase bounds for one root-frame Cartesian deformation. |
|
One single-frame Cartesian trajectory aligned with a joint template. |
|
Projected qpos trajectory and per-sample Cartesian residual evidence. |
|
Evaluate one joint template and authorize selected free phases. |
|
Apply smooth root-frame twists while preserving every phase endpoint. |
|
Project editable Cartesian samples back into the reference joint layout. |
|
One owned source phase normalized onto a segment-local time axis. |
|
Replacement compatibility and boundary distances for two segments. |
|
Insertion-ordered source segments with deterministic selection policies. |
|
One planner-produced joint transition including both boundary samples. |
|
Plan a joint transition between two segment boundary states. |
|
Generate rest-to-rest bridges under sampled velocity/acceleration limits. |
|
Source-segment lineage aligned with its half-open output sample range. |
|
A stitched qpos template with explicit multi-source segment lineage. |
|
Extract every annotated phase as an independently owned segment. |
|
Compare whether a candidate may replace one semantic source phase. |
|
Concatenate phase segments and explicitly plan discontinuous boundaries. |
|
One mandatory check; unavailable and not-run checks cannot accept data. |
|
A fail-closed collection of required validation checks. |
|
Measured joint geometry and elapsed times at uniform phase progress. |
|
Describe an actual rollout without rewarding additional time samples. |
|
Reserve near-distinct measured trajectories and count confirmed geometry. |
|
Yoshikawa manipulability sampled along one trajectory. |
|
Ordered manipulability bands normalized by one reference trajectory. |
|
One selected residual proposal and the evidence used to select it. |
|
Score a sampled trajectory's Jacobians and align them with its phases. |
|
Sample joint residuals and keep the one nearest a requested band. |
|
Rotate a reference grasp about an axis through a fixed object's origin. |
|
Place standoff poses on a cone around a nominal approach direction. |
|
Add one smooth, endpoint-preserving residual per allowed free phase. |
|
Route each allowed free phase through sampled interior joint knots. |
|
Move through the redundancy of a declared task while holding its rows. |
|
Retime permitted free phases and resample onto the host control clock. |
|
Built-in immutable sequence. |
|
One sampled proposal is unusable; another draw may well succeed. |
|
Check sampled finite-difference motion limits without asserting task success. |
|
str(object='') -> str str(bytes_or_buffer[, encoding[, errors]]) -> str |
|
One deterministic combination of augmentation factors. |
|
Accepted candidate rows together with the accounting that produced them. |
|
Enable every implemented factor at magnitudes known to stay executable. |
|
Enumerate deterministic factor combinations without touching a trajectory. |
|
Apply a joint/task-space proposal, optional guidance, then retiming. |
|
Generate up to |
|
Sample tilt angles for |
|
Own one job's bounded candidates, budgets, evidence, and commit history. |
|
Load one callable-free combined Expansion Profile. |
|
Stable source and scene identity supplied by a expansion coordinator. |
|
Convert one expert source unit into a reusable trajectory template. |
|
Adapt an already annotated handwritten qpos template. |
|
Adapt one single-row MotionGenerator result to a qpos template. |
|
|
Enumerate the deterministic |
|
Load and validate seedable visual profile IDs. |
|
Hash the complete schedule in order for deterministic rerun checks. |
|
Return recipes in family round-robin order with FIFO within each family. |
Values and Evidence#
SceneCase separates scene and initial-state identity from physical execution
slots. MotionSnapshot copies robot positions and velocities, the robot root
pose, entity poses, and dependency revisions. Pose validation checks finite
proper SE(3) transforms, including rotation orthogonality and handedness.
Tensor inputs are detached and cloned at construction; consumers must still
treat the resulting owned tensors as read-only.
CandidateSpec combines one Affordance selection and one trajectory variant
under a single slot-independent candidate identity. Observation profiles are
post-rollout fan-out metadata and do not create additional physical candidates.
SourceAdapter is the provider-neutral boundary for handwritten,
MotionGenerator, Atomic Action, and Task Program sources. It exports a complete
qpos template but does not own slots, simulator stepping, candidate identity, or
persistence.
Templates declare the complete joint order and use explicit qpos values.
dt[0] is zero and each subsequent dt is the positive arrival interval
from the preceding sample. Phase ranges are half-open sample intervals
[start_index, stop_index). Unannotated paths permit replay only; operators
also require explicit template, phase, and controlled-joint permissions.
Candidate batches have shape (C, N, D_full), where the logical candidate
count C does not prescribe the host’s physical batch size. valid_length
selects actual samples. Padding holds the final valid position and uses zero
time intervals; it is excluded from execution and recording. Extracting a row
copies its tensor payload and retains aligned identity, phase, factor, and
source-row metadata.
An ExpertEpisode contains T commands actually sent and T+1
observations and timestamps, including the terminal observation. Episode
metadata accepts finite JSON values rather than live host objects. A validation
result accepts only a nonempty collection of passing checks; not_run,
failed, and unavailable remain distinct rejection states. This structural
check does not generate physical evidence or certify the supplied checker.
Persistence uses stable episode, candidate, scene, and commit IDs. The commit ID
remains fixed across write retries, while submission_id distinguishes each
submission and its delayed receipt. A persistence receipt is an input contract;
the package itself does not write or verify storage.
- class embodichain.lab.sim.motion.expansion.SceneCase[source]#
A fixed scene and allowed initial state, with no live environment references.
Methods:
__init__(scene_case_id, initial_state_id, ...)- __init__(scene_case_id, initial_state_id, scene_signature, task_id, robot_profile_id, calibration_id='default')#
- class embodichain.lab.sim.motion.expansion.MotionSnapshot[source]#
One copied complete robot state; poses map local frames into the world.
Methods:
__init__(scene_case, joint_names, ...[, ...])- __init__(scene_case, joint_names, joint_positions, joint_velocities, root_pose, entity_poses=<factory>, dependency_revisions=<factory>)#
- class embodichain.lab.sim.motion.expansion.TrajectoryPhase[source]#
An explicitly annotated half-open sample interval
[start, stop).Phase endpoints are samples
start_indexandstop_index - 1. Adjacent phases may share exactly one endpoint sample; their interiors may not overlap. Unannotated samples remain unchanged by augmentation operators.Methods:
__init__(phase_id, start_index, stop_index)- __init__(phase_id, start_index, stop_index, kind='free', allowed_operators=())#
- class embodichain.lab.sim.motion.expansion.TrajectoryTemplate[source]#
A full-joint qpos reference with arrival intervals and explicit permissions.
dt[0]is zero; every later interval is strictly positive. Empty phases and operator permissions permit replay only. EEF conversion is owned by an injected planning adapter before constructing this qpos contract.Methods:
__init__(source_id, source_revision, ...[, ...])- __init__(source_id, source_revision, template_id, joint_names, positions, dt, phases=(), allowed_operators=(), validator_id='default', controlled_joint_indices=(), representation='qpos')#
- class embodichain.lab.sim.motion.expansion.CandidateIdentity[source]#
Candidate lineage independent of execution slots and their epochs.
Methods:
__init__(scene_case_id, initial_state_id, ...)- __init__(scene_case_id, initial_state_id, candidate_id, geometry_family_id, source_id, source_revision, template_id, attempt_id=0, parent_id=None)#
- class embodichain.lab.sim.motion.expansion.ProposalRequest[source]#
Validated input for one transactional candidate identity allocation.
Methods:
__init__(scene_case_id, initial_state_id, ...)- __init__(scene_case_id, initial_state_id, source_id, source_revision, template_id, operator_id, geometry_family_id=None, parent_id=None)#
- class embodichain.lab.sim.motion.expansion.CandidateSpec[source]#
Source-neutral physical candidate lineage before slot assignment.
Affordance and trajectory factors remain independently inspectable, while the coordinator assigns one final candidate identity. Observation profiles describe post-rollout fan-out and do not create additional physical candidates.
Methods:
__init__(identity[, affordance_selection, ...])- __init__(identity, affordance_selection=<factory>, trajectory_variant=<factory>, compatibility_key='default', estimated_cost=0.0, observation_profiles=())#
- class embodichain.lab.sim.motion.expansion.CandidateCoordinator[source]#
Generate source-neutral candidates without owning physical execution.
The coordinator owns only template expansion and a bounded logical queue. Initial-state restoration, physical slots, measured validation, and persistence remain host responsibilities. A caller must register the source case with the supplied
ExpansionSessionbefore proposing.kinematicsbinds a host-owned root-frame FK/Jacobian callable to the template’s controlled joint order. Task-space and guided proposals share this callable; guidance uses the initial state’s registered reference normalizer. Candidate metadata preserves the actual selection evidence.Methods:
__init__(cfg, *, session, source_adapter, ...)admit_planned(item, validation)Admit one host-validated candidate to ExpansionSession's ready pool.
enqueue_source(source, *, count[, ...])Export one source unit, expand it, and enqueue bounded candidates.
Return the next candidate without changing queue ownership.
Remove and return the next candidate in deterministic FIFO order.
Attributes:
Return the number of logical candidates waiting for host execution.
Return the session that owns candidate lifecycle and receipts.
Return the scene case shared by the current source context.
- __init__(cfg, *, session, source_adapter, source_context, joint_limits, backend_id='unspecified', velocity_limits=None, acceleration_limits=None, task_jacobians=None, kinematics=None)[source]#
- admit_planned(item, validation)[source]#
Admit one host-validated candidate to ExpansionSession’s ready pool.
The host owns collision/path validation; this method only transfers the immutable candidate and its validation result into the session state. It never executes or persists the candidate.
- Return type:
None
- enqueue_source(source, *, count, affordance_selection=None, compatibility_key=None)[source]#
Export one source unit, expand it, and enqueue bounded candidates.
- Parameters:
source (
object) – Source value consumed by the registered SourceAdapter.count (
int) – Maximum accepted trajectory variants for this source unit.affordance_selection (
Mapping[str,object] |None) – Optional lineage for the Affordance proposal that produced the source template.compatibility_key (
str|None) – Optional host compatibility bucket. When omitted, a stable case/control/validator key is derived.
- Return type:
tuple[CandidateWorkItem,...]- Returns:
The newly enqueued work items in deterministic variant order.
- Raises:
BufferError – If the logical ready queue cannot hold the result.
ValueError – If source export or variant expansion fails.
- peek_next()[source]#
Return the next candidate without changing queue ownership.
- Return type:
CandidateWorkItem|None
- property pending_count: int#
Return the number of logical candidates waiting for host execution.
- property session: ExpansionSession#
Return the session that owns candidate lifecycle and receipts.
- take_next()[source]#
Remove and return the next candidate in deterministic FIFO order.
- Return type:
CandidateWorkItem|None
- class embodichain.lab.sim.motion.expansion.CandidateWorkItem[source]#
One logical candidate ready for planning validation or slot assignment.
Methods:
__init__(spec, template)to_batch()Return the single-row logical batch consumed by ExpansionSession.
- __init__(spec, template)#
- class embodichain.lab.sim.motion.expansion.SourceContext[source]#
Stable source and scene identity supplied by a expansion coordinator.
Methods:
__init__(source_id, source_revision, ...)- __init__(source_id, source_revision, unit_id, scene_case, control_dt)#
- class embodichain.lab.sim.motion.expansion.SourceAdapter[source]#
Convert one expert source unit into a reusable trajectory template.
Implementations may be handwritten, MotionGenerator, Atomic Action, or Task Program adapters. They must not own environment slots, reset/step a simulator, allocate candidate identities, or persist episodes.
Methods:
__init__(*args, **kwargs)export_template(source, *, context)Export one complete, phase-annotated qpos template.
- __init__(*args, **kwargs)#
- class embodichain.lab.sim.motion.expansion.TemplateSourceAdapter[source]#
Adapt an already annotated handwritten qpos template.
Methods:
__init__()export_template(source, *, context)Return an owned template with coordinator-owned source identity.
- __init__()#
- class embodichain.lab.sim.motion.expansion.PlanResultSourceAdapter[source]#
Adapt one single-row MotionGenerator result to a qpos template.
Phase annotations and editable operators are supplied by the caller because a generic PlanResult does not own semantic contact or hold boundaries.
Methods:
__init__(joint_names[, phases, ...])export_template(source, *, context)Convert one successful single-row result with explicit timing.
- __init__(joint_names, phases=(), validator_id='default', allowed_operators=None)#
- class embodichain.lab.sim.motion.expansion.CandidateTrajectoryBatch[source]#
Logical candidate rows with safe padding and no physical batch assumption.
positionsis(C,N,D_full),dtis(C,N), and eachvalid_lengthis in[1,N]. An empty candidate set usesC=0. Padded positions hold the final valid sample and padded intervals are zero. They must never be executed or recorded; usevalid_mask.Methods:
__init__(positions, dt, valid_length, ...[, ...])row(index)Copy one candidate and its aligned metadata, retaining padded shape.
Attributes:
Return a fresh boolean mask selecting actual samples in each row.
- __init__(positions, dt, valid_length, identities, joint_names, phases=(), factors=(), source_row_indices=None)#
- row(index)[source]#
Copy one candidate and its aligned metadata, retaining padded shape.
- Parameters:
index (
int) – Nonnegative candidate row index.- Return type:
- Returns:
An owned single-row batch with shape
(1, N, D_full)and aligned metadata.
- property valid_mask: Tensor#
Return a fresh boolean mask selecting actual samples in each row.
- Returns:
A boolean tensor of shape
(C, N)that excludes padded samples.
- class embodichain.lab.sim.motion.expansion.ValidationCheck[source]#
One mandatory check; unavailable and not-run checks cannot accept data.
Methods:
__init__(check_id, status[, detail, metrics])- __init__(check_id, status, detail='', metrics=<factory>)#
- class embodichain.lab.sim.motion.expansion.ValidationResult[source]#
A fail-closed collection of required validation checks.
Methods:
__init__(checks)Attributes:
Return whether every required check was run and passed.
- __init__(checks)#
- property accepted: bool#
Return whether every required check was run and passed.
- Returns:
Trueonly for a nonempty result whose checks all have passing status.
- class embodichain.lab.sim.motion.expansion.ExpertEpisode[source]#
Frozen rollout evidence with causal
obs[t], action[t], obs[t+1]pairs.Observations and timestamps contain
T+1samples, including the terminal observation. Actions contain theTcommands actually submitted. This contract checks structure; hosts remain responsible for measuring evidence.Methods:
__init__(identity, observations, actions, ...)- __init__(identity, observations, actions, timestamps, action_representation, validation, episode_id, commit_id, phases=(), metadata=<factory>)#
- class embodichain.lab.sim.motion.expansion.CommitReceipt[source]#
Sink confirmation tied to stable episode/candidate IDs, never a slot.
The idempotent
commit_idremains fixed across persistence retries.submission_ididentifies an individual write attempt so a delayed failure cannot invalidate a newer retry of the same episode.Methods:
__init__(episode_id, candidate_id, ...[, ...])- __init__(episode_id, candidate_id, attempt_id, storage_id, commit_id, scene_case_id, confirmed=True, error='', submission_id=0)#
- class embodichain.lab.sim.motion.expansion.CombinedExpansionProfile[source]#
Strict episode-level profile for the combined showcase.
Methods:
from_mapping(data)Decode the canonical combined schema without evaluating callables.
validate_for_num_envs(num_envs)Validate the host-owned slot capacity before simulator construction.
validate_registries(*, visual_profile_ids, ...)Validate that host registries contain each requested profile once.
- classmethod from_mapping(data)[source]#
Decode the canonical combined schema without evaluating callables.
- Return type:
- class embodichain.lab.sim.motion.expansion.ReferenceFamilySpec[source]#
One immutable legal initial cube pose and its authored targets.
Methods:
__init__(reference_family_id, cube_position, ...)- __init__(reference_family_id, cube_position, cube_quaternion_xyzw, drop_targets, deterministic_seed, profile_revision='cube_initial_pose:v1', scene_signature='repeated_pick_place_scene_v1')#
- class embodichain.lab.sim.motion.expansion.CubeInitialPoseProvider[source]#
Return deterministic authored cube pose families for a expansion job.
Methods:
__init__([poses, family_ids, ...])enumerate([count])Enumerate the first
countlegal deterministic families.from_yaml(path, *[, seed])Load authored cube families from a strict pose profile.
- __init__(poses=None, *, family_ids=None, profile_revision='cube_initial_pose:v1', drop_targets=(('drop_pose_00', (-0.4, 0.48, 0.1)), ('drop_pose_01', (-0.42, -0.08, 0.1))), seed=0)[source]#
- enumerate(count=None)[source]#
Enumerate the first
countlegal deterministic families.- Return type:
tuple[ReferenceFamilySpec,...]
- class embodichain.lab.sim.motion.expansion.CycleRecipe[source]#
Requested affordance and trajectory ordinals for one Pick/Place cycle.
Methods:
__init__(cycle_index, affordance_requested, ...)- __init__(cycle_index, affordance_requested, trajectory_requested)#
- class embodichain.lab.sim.motion.expansion.CallRecipe[source]#
Requested affordance and trajectory ordinals for one workflow call.
Methods:
__init__(call_index, affordance_requested, ...)- __init__(call_index, affordance_requested, trajectory_requested)#
- class embodichain.lab.sim.motion.expansion.CandidateRecipe[source]#
Complete episode recipe; identity is independent of simulator row.
Methods:
__init__(recipe_index, candidate_id, ...)- __init__(recipe_index, candidate_id, reference_family_id, physical_geometry_family_id, cycle_schedule, call_schedule, visual_profile_id, visual_seed, source_unit_id, source_revision, deterministic_seed_digest)#
- class embodichain.lab.sim.motion.expansion.SlotReservation[source]#
Opaque reservation returned by
PhysicalSlotPool.Methods:
__init__(slot_id, candidate_id, ...)- __init__(slot_id, candidate_id, compatibility_key, token)#
- class embodichain.lab.sim.motion.expansion.PhysicalSlotPool[source]#
Generic compatible-slot reservation with exact release semantics.
A slot can advertise a strict compatibility key. Candidates remain independent of the numeric slot they receive; releasing a stale or foreign reservation raises rather than freeing another candidate’s slot.
Methods:
__init__(slot_count, *[, compatibility_keys])release(reservation)Release exactly the reservation returned by
reserve().reservation_for(slot_id)Inspect a row without exposing mutable pool state.
reserve(candidate_id, compatibility_key)Reserve the first free row compatible with
compatibility_key.Attributes:
Return the number of currently unreserved compatible rows.
Return the number of physical slots.
- property available_count: int#
Return the number of currently unreserved compatible rows.
- property capacity: int#
Return the number of physical slots.
- release(reservation)[source]#
Release exactly the reservation returned by
reserve().- Return type:
None
- reservation_for(slot_id)[source]#
Inspect a row without exposing mutable pool state.
- Return type:
SlotReservation|None
- class embodichain.lab.sim.motion.expansion.VisualProfileApplication[source]#
Resolved visual operations for one physical episode.
Methods:
__init__(profile_id, revision, seed, operations)- __init__(profile_id, revision, seed, operations, status='resolved')#
- class embodichain.lab.sim.motion.expansion.VisualProfileRegistry[source]#
Load seedable visual profiles from a strict YAML file.
Methods:
__init__(profile_id, revision, profiles)apply_to_environment(env, assignments, *, seed)Apply visual operations through existing functors.
from_yaml(path)Load one closed visual registry without importing executable values.
resolve(profile_id, *, seed)Resolve one profile and derive its deterministic episode seed.
Attributes:
Return registered profile IDs in file order.
- apply_to_environment(env, assignments, *, seed)[source]#
Apply visual operations through existing functors.
The method intentionally accepts a narrow structural environment port rather than importing Gym types. A
global_sunoperation is applied once tomain_light; multiple declared global operations must agree, and per-environment operations are then applied to selected rows.- Return type:
tuple[VisualProfileApplication,...]
- classmethod from_yaml(path)[source]#
Load one closed visual registry without importing executable values.
- Return type:
- property profile_ids: tuple[str, ...]#
Return registered profile IDs in file order.
- class embodichain.lab.sim.motion.expansion.CombinedAssignment[source]#
One recipe reserved on one compatible physical slot.
Methods:
__init__(recipe, reservation, compatibility_key)- __init__(recipe, reservation, compatibility_key)#
- class embodichain.lab.sim.motion.expansion.CombinedEpisodeCoordinator[source]#
Bounded FIFO coordinator for recipe assignment and slot cleanup.
Methods:
__init__(recipes, *, slot_pool, ...)Reserve the next recipe, or return
Noneon capacity/cancellation.cancel()Stop new work and release every active reservation safely.
finish(assignment, *, status)Release an active assignment and count its terminal status.
snapshot()Return immutable scheduler counters and queue state.
Attributes:
Return recipes currently holding a physical slot.
Return recipes waiting for assignment.
- acquire_next()[source]#
Reserve the next recipe, or return
Noneon capacity/cancellation.- Return type:
CombinedAssignment|None
- property active_count: int#
Return recipes currently holding a physical slot.
- finish(assignment, *, status)[source]#
Release an active assignment and count its terminal status.
- Return type:
None
- property pending_count: int#
Return recipes waiting for assignment.
- class embodichain.lab.sim.motion.expansion.MeasuredValidator[source]#
Fail-closed validator for measured episode and three-cycle evidence.
Methods:
validate(episode, *[, cycle_count])Return required checks from finite aligned evidence and cycle metadata.
validate_demo_result(result, *[, cycle_count])Validate the measured Gym demo boundary before dataset commit.
- validate(episode, *, cycle_count=3)[source]#
Return required checks from finite aligned evidence and cycle metadata.
- Return type:
- validate_demo_result(result, *, cycle_count=3)[source]#
Validate the measured Gym demo boundary before dataset commit.
Environment integrations can add object pose and contact checks to the result metadata. This base gate always requires completed rows and the expected number of successful Task Program segments.
- Return type:
Configuration and Preflight#
TrajectoryAugmentationCfg owns the local seed, provided-start declaration,
the spatial, redundancy (ik), approach, timing and manipulability factors,
and the joint-geometry coverage limits. spatial.method names one or more of
SPATIAL_METHODS; each requested method becomes its own variant, and a
single name is still accepted where a sequence is expected.
TrajectoryExpansionCfg is the single source-neutral configuration contract
for candidate expansion, validation, collection budgets, and persistence
bookkeeping. Its from_mapping method rejects unknown fields and invalid
types or ranges, while nested values are rechecked after construction.
TrajectoryExpansionJobCfg remains a legacy standalone-job adapter for
existing callers; new source integrations should consume
TrajectoryExpansionCfg directly.
The expansion contract accepts FIFO candidate scheduling, bounded collection,
and synchronous persistence. It keeps control periods, source identity, initial
state restoration, and physical execution owned by the host integration.
Coverage-per-cost scheduling and the still-unimplemented contact,
contact_timing and recovery factors remain rejected. The legacy job
adapter retains its standalone preflight fields for existing callers but is not
used by the new source integration path.
Configuration IDs, including the default lerobot sink name, do not create
services. validate_capabilities requires explicit trusted source, validator,
profile, sink, and operator registries; configuration values are not imported
or evaluated. In particular, accepting a restoration profile ID does not implement physical
restoration in this package, and accepting the perturb_approach_direction
capability does not implement the EEF replanning its poses require. Deployment preflight must still verify those services.
- embodichain.lab.sim.motion.expansion.SPATIAL_METHODS = ('joint_residual', 'via_points')#
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable’s items.
If the argument is a tuple, the return value is the same object.
- class embodichain.lab.sim.motion.expansion.TrajectoryAugmentationCfg[source]#
Local random seed, explicitly enabled factors, and geometry coverage limits.
Methods:
from_mapping(data)Decode closed nested fields without executing configuration values.
Recheck typed nested values, including mutations made after decoding.
- class embodichain.lab.sim.motion.expansion.TrajectoryExpansionCfg[source]#
Source-neutral expansion settings shared by every expert source.
This contract deliberately excludes source identity, Task Program selection, environment ownership, and reset policy. Handwritten, MotionGenerator, Atomic Action, and Task Program adapters can all consume the same expansion settings.
Methods:
from_expansion_job(job)Project a legacy job into the source-neutral expansion contract.
from_mapping(data)Decode source-neutral expansion settings with closed fields.
- classmethod from_expansion_job(job)[source]#
Project a legacy job into the source-neutral expansion contract.
- Return type:
- class embodichain.lab.sim.motion.expansion.TrajectoryExpansionJobCfg[source]#
Standalone expansion job configuration; control periods remain host-owned.
Methods:
from_mapping(data)Decode the supported nested YAML schema and reject unknown fields.
validate_capabilities(*, source_ids, ...[, ...])Require IDs and enabled operators in explicitly supplied registries.
Validate configuration without loading hosts, profiles, or sources.
- classmethod from_mapping(data)[source]#
Decode the supported nested YAML schema and reject unknown fields.
- Parameters:
data (
Mapping[str,Any]) – Nested job settings for source, augmentation, execution, and collection.- Return type:
- Returns:
A decoded job configuration with semantic constraints validated.
- validate_capabilities(*, source_ids, validator_ids, profile_ids, sink_ids, operators=())[source]#
Require IDs and enabled operators in explicitly supplied registries.
This is a preflight step in addition to semantic decoding. Registry membership asserts that the caller has already resolved trusted implementations; it does not itself certify physical validation.
- Parameters:
source_ids (
Collection[str]) – Available trusted trajectory source identifiers.validator_ids (
Collection[str]) – Available trusted validator identifiers.profile_ids (
Collection[str]) – Available preparation, state, validation, and motion-limit profiles.sink_ids (
Collection[str]) – Available episode sink identifiers.operators (
Collection[str]) – Implemented spatial and timing operator names.
- Return type:
None
- embodichain.lab.sim.motion.expansion.load_expansion_profile(path)[source]#
Load one callable-free combined Expansion Profile.
- Parameters:
path (
str|Path) – YAML or JSON profile path.- Return type:
- Returns:
Strictly decoded and semantically validated combined profile.
- Raises:
TypeError – If the serialized root is not a mapping.
ValueError – If the profile contains unknown or invalid fields.
Operators, Coverage, and Session#
rotate_grasp_about_object_axis derives TCP pose candidates from a reference
grasp, rotating its position and orientation about an object-local axis through
the fixed object origin. The caller selects rotations appropriate to the
object’s geometry, such as quarter turns for a cube, and replans each candidate.
The operator does not move the object or establish contact/IK validity.
perturb_approach_direction places standoff poses on a cone around a
nominal approach direction while leaving the contact transform itself exact.
Because it produces Cartesian poses, it must be consumed before IK and path
planning by whichever component builds the waypoints; it cannot be applied to
a qpos template.
joint_residual samples one smooth residual per explicitly permitted free
phase and preserves its endpoints and uncontrolled joints. via_points
routes a phase through several sampled interior knots instead, using clamped
cubic Hermite segments, so two or more knots produce paths that differ in
shape rather than only in amplitude. nullspace_residual projects a residual
onto the null space of caller-supplied task Jacobians, changing arm posture
while holding the declared task rows to first order. Redundancy is decided
on the numerical rank of those Jacobians: a generic full-rank one still leaves
floating-point residue in the projector, so a magnitude test would pass it
through and emit a near-unchanged variant. The operator its phase endpoints
remain exact because the envelope vanishes there, and interior samples require
forward-kinematics verification by the host.
retime rescales permitted free phases and resamples on the supplied host
control period, remapping phase indices. Contact and hold durations are
preserved. Its profile argument additionally redistributes time within a
phase without changing that phase’s total duration or its geometric path, which
turns one path into several velocity profiles; TIMING_PROFILES lists the
available warps. Generated paths still need dynamic, collision, and task checks.
validate_motion_limits supplies a sampled finite-difference speed and
acceleration check; it does not assert collision freedom or task success.
describe_trajectory computes phase-aligned normalized joint geometry and
elapsed-time descriptors from actual observations. CoverageIndex reserves
capacity before persistence and counts geometry only after confirmation.
Timing variants share geometry-family membership. This first descriptor uses
joint geometry; it does not provide EEF workspace coverage.
describe_manipulability scores caller-supplied Jacobians with
yoshikawa_manipulability() and aligns the
result with trajectory phases. ManipulabilityBands partitions those scores
into ordered bands normalized by a reference registered for one initial state,
usually that state’s reference trajectory bottleneck. manipulability_guided_residual draws several
residual proposals from one local generator and keeps the proposal nearest a
requested band, returning a GuidedResidual with the measured profile.
When augmentation.factors.manipulability is enabled, CoverageIndex
additionally enforces a per-band quota, so a well-conditioned posture cannot
absorb the whole collection budget and tighter but still task-valid postures
retain capacity. Bands classify measured evidence: the session reads the
manipulability observation recorded during the rollout, never a planned
score. Manipulability describes posture conditioning only; every banded
candidate still requires the same independent path, dynamic, and task checks.
ExpansionSession owns scene-case registration, stable candidate identity,
local random streams, bounded candidate and pending-episode payloads, collection
budgets, coverage reservations, and commit accounting. Its lifecycle accepts
planning results and measured episode evidence without stepping or resetting a
host. Duplicate receipts do not increment committed counts, and failed writes
release collection and coverage reservations before an explicit write retry.
- embodichain.lab.sim.motion.expansion.rotate_grasp_about_object_axis(object_pose, grasp_pose, *, axis, angles)[source]#
Rotate a reference grasp about an axis through a fixed object’s origin.
The axis is expressed in the object’s local frame. Both the grasp position and orientation rotate about that axis; the object itself is unchanged. For example, a cube permits quarter-turn variants of a centered top grasp. The caller owns object symmetry and grasp validity: arbitrary rotations need not preserve contacts. Every candidate requires fresh IK/path planning and physical grasp validation. This function does not modify a qpos template.
- Parameters:
object_pose (
Tensor) – Object transform in the scene frame, shape(4, 4).grasp_pose (
Tensor) – Reference TCP transform in that same frame, shape(4, 4).axis (
Tensor) – Finite nonzero object-local rotation axis, shape(3,).angles (
Tensor) – Finite rotation angles in radians, shape(C,), with C > 0.
- Return type:
Tensor- Returns:
Owned candidate TCP transforms with shape
(C, 4, 4), using the object pose’s device and dtype, in the original scene frame.- Raises:
ValueError – If transforms, axis, or angles are malformed or nonfinite.
- embodichain.lab.sim.motion.expansion.perturb_approach_direction(contact_pose, *, approach_axis, standoff_distance, polar_angles, azimuth_angles, align_tool=True)[source]#
Place standoff poses on a cone around a nominal approach direction.
The contact transform itself is never modified, so a fixed waypoint stays exact; only the pose the motion departs from changes.
approach_axisis expressed in the contact frame and points from the standoff toward the contact, which is the direction the tool travels while closing the gap. Each candidate tilts that axis by its polar angle about a perpendicular selected by its azimuth angle.The caller owns reachability and clearance: a tilted standoff need not be collision free, within the workspace, or compatible with the object’s contact geometry. Every candidate requires fresh IK and path planning.
- Parameters:
contact_pose (
Tensor) – Fixed contact transform in the scene frame, shape(4, 4).approach_axis (
Tensor) – Finite nonzero contact-local travel direction, shape(3,).standoff_distance (
float) – Positive distance from the standoff to the contact.polar_angles (
Tensor) – Finite tilt angles in radians from the nominal axis, shape(C,).azimuth_angles (
Tensor) – Finite angles in radians selecting the tilt plane, shape(C,).align_tool (
bool) – Rotate each standoff so its own localapproach_axispoints at the contact, making the approach a screw motion.Falsekeeps the contact orientation and varies only the standoff position.
- Return type:
Tensor- Returns:
Owned standoff transforms with shape
(C, 4, 4), using the contact pose’s device and dtype, in the original scene frame.- Raises:
ValueError – If the transform, axis, distance, or angles are malformed.
- embodichain.lab.sim.motion.expansion.joint_residual(template, *, joint_limits, normalized_scale, generator)[source]#
Add one smooth, endpoint-preserving residual per allowed free phase.
This operator applies only to explicitly permitted joint-space motion. Cartesian contact constraints require a planning adapter and cannot be inferred from qpos. It changes only the declared controlled joints.
- Parameters:
template (
TrajectoryTemplate) – Annotated full-joint reference.joint_limits (
Tensor) – Finite lower/upper limits with shape(D, 2).normalized_scale (
float) – Maximum offset as a fraction of each joint range.generator (
Generator) – Explicit local generator; global RNG is never consumed.
- Return type:
- Returns:
A new template requiring path and physical validation.
- Raises:
ValueError – If permissions, limits or resulting positions are invalid.
- embodichain.lab.sim.motion.expansion.via_points(template, *, joint_limits, via_count, normalized_scale, generator)[source]#
Route each allowed free phase through sampled interior joint knots.
Unlike
joint_residual(), which adds one fixed-shape bump per phase, this operator placesvia_countinterior knots and interpolates them with clamped cubic Hermite segments. Two or more knots admit sign changes along a phase, so the resulting paths differ in shape rather than only in amplitude. Phase endpoints and their derivatives are unchanged, which keeps every annotated waypoint exact.All knots displace along one sampled joint-space direction, and only their signed magnitudes vary. Sampling each joint of each knot independently instead would decorrelate the joints, and the tool path that comes out of forward kinematics then wanders: measured on a pick-and-place reference it grew about half as long again, without adding anything a caller wants.
Only the declared controlled joints move. Cartesian contact constraints cannot be inferred from qpos, and the result still requires path and physical validation.
- Parameters:
template (
TrajectoryTemplate) – Annotated full-joint reference.joint_limits (
Tensor) – Finite lower/upper limits with shape(D, 2).via_count (
int) – Number of interior knots per phase, at least one.normalized_scale (
float) – Maximum knot offset as a fraction of each joint range.generator (
Generator) – Explicit local generator; global RNG is never consumed.
- Return type:
- Returns:
A new template requiring path and physical validation.
- Raises:
ValueError – If permissions, knot counts, limits or positions are invalid.
- embodichain.lab.sim.motion.expansion.nullspace_residual(template, *, task_jacobians, joint_limits, normalized_scale, generator, rank_tolerance=1e-06)[source]#
Move through the redundancy of a declared task while holding its rows.
The caller supplies one task Jacobian per sample for the declared controlled joints, already reduced to the rows the task actually constrains. A six-row Jacobian on a six-joint arm generically leaves no redundancy; dropping the rows a gripper is symmetric about, such as spin about its own approach axis, is what creates alternative arm postures for the same tool pose.
The residual is projected onto each sample’s Jacobian null space, so the constrained task rows are preserved to first order only. Phase endpoints are exact because the envelope vanishes there, which keeps annotated waypoints unchanged regardless of linearization error. Interior samples require forward-kinematics verification by the host; this operator certifies neither pose accuracy nor collision freedom.
- Parameters:
template (
TrajectoryTemplate) – Annotated full-joint reference.task_jacobians (
Tensor) – Per-sample task Jacobians with shape(N, R, C), whereNmatches the template samples andCthe declared controlled joints, incontrolled_joint_indicesorder.joint_limits (
Tensor) – Finite lower/upper limits with shape(D, 2).normalized_scale (
float) – Maximum offset as a fraction of each joint range, measured before null-space projection shrinks it.generator (
Generator) – Explicit local generator; global RNG is never consumed.rank_tolerance (
float) – Relative singular-value cutoff shared by the rank test and the pseudoinverse.
- Return type:
- Returns:
A new template requiring pose, path and physical validation.
- Raises:
ValueError – If permissions, shapes, limits or positions are invalid, or if the declared task rows leave no usable redundancy.
- embodichain.lab.sim.motion.expansion.retime(template, *, duration_scale, control_dt, max_samples=1000000, profile='uniform')[source]#
Retime permitted free phases and resample onto the host control clock.
Contact and wait durations, phase endpoints, and inter-phase intervals are preserved. Phase boundaries must already align with the host clock. Scaled phase durations round up to whole control steps; sample counts therefore change. The function does not claim dynamic or collision validity.
profileredistributes time within a phase without changing its total duration or its geometric path, so a single path yields several distinct velocity profiles. The warp is bounded, keeping every arrival interval within a factor of three of the uniform spacing.- Parameters:
template (
TrajectoryTemplate) – Reference containing explicitly permittedretimephases.duration_scale (
float) – Positive factor; greater than one slows free motion.control_dt (
float) – Authoritative host control period in seconds.max_samples (
int) – Allocation bound for the resulting trajectory.profile (
str) –uniformkeeps proportional spacing,ease_instarts slower and finishes faster, andease_outdoes the reverse.
- Return type:
- Returns:
A new uniformly timed template with remapped phase indices.
- Raises:
ValueError – If permissions, timing or allocation constraints fail.
- embodichain.lab.sim.motion.expansion.TIMING_PROFILES = ('uniform', 'ease_in', 'ease_out')#
Built-in immutable sequence.
If no argument is given, the constructor returns an empty tuple. If iterable is specified the tuple is initialized from iterable’s items.
If the argument is a tuple, the return value is the same object.
- class embodichain.lab.sim.motion.expansion.ProposalRejected[source]#
One sampled proposal is unusable; another draw may well succeed.
Operators raise this only for outcomes that depend on the draw. Malformed arguments, unsatisfiable permissions and impossible configurations remain plain
ValueError, so a expansion loop that retries on rejection does not also swallow a programming error.
- embodichain.lab.sim.motion.expansion.validate_motion_limits(template, *, velocity_limits, acceleration_limits)[source]#
Check sampled finite-difference motion limits without asserting task success.
- Parameters:
template (
TrajectoryTemplate) – Timed full-joint path to check.velocity_limits (
Tensor) – Positive per-joint speed bounds, shape(D,).acceleration_limits (
Tensor) – Positive per-joint acceleration bounds, shape(D,).
- Return type:
- Returns:
A single
motion_limitscheck with maximum normalized ratios.
- class embodichain.lab.sim.motion.expansion.TrajectoryDescriptor[source]#
Measured joint geometry and elapsed times at uniform phase progress.
- Parameters:
phase_ids (
tuple[tuple[str,str],...]) – Ordered phase identities, including contact/free mode.geometry (
Tensor) – Normalized joint samples, with shape(P, S, D).timing (
Tensor) – Elapsed seconds within each phase, with shape(P, S).
Methods:
__init__(phase_ids, geometry, timing)- __init__(phase_ids, geometry, timing)#
- embodichain.lab.sim.motion.expansion.describe_trajectory(positions, timestamps, joint_limits, *, phases=(), samples_per_phase=32)[source]#
Describe an actual rollout without rewarding additional time samples.
Geometry is sampled by normalized joint arc length within each phase. Timing includes the phase duration, including stationary waits. Unlabelled gaps are included as separate phases so no measured movement is silently discarded.
- Parameters:
positions (
Tensor) – Actual joint positions with shape(T, D).timestamps (
Tensor) – Strictly increasing observation timestamps, shape(T,).joint_limits (
Tensor) – Finite lower/upper joint limits, shape(D, 2).phases (
tuple[TrajectoryPhase,...]) – Optional half-open ranges in the actual observation sequence.samples_per_phase (
int) – Number of progress samples, at least two.
- Return type:
- Returns:
Owned CPU descriptor separating geometry from timing.
- Raises:
ValueError – If samples, limits, times or phase ranges are invalid.
- class embodichain.lab.sim.motion.expansion.CoverageIndex[source]#
Reserve near-distinct measured trajectories and count confirmed geometry.
One instance belongs to one scene case. Pending writes occupy capacity but do not contribute to formal coverage. A timing variant cannot increase the geometry count even if small physical tracking differences are measured.
An optional per-band quota spreads accepted rollouts over manipulability bands. Once a band is full its further rollouts are rejected even when their geometry is new, so a well-conditioned posture cannot absorb the whole collection budget. Bands are classified by the caller; this index only counts them.
- Parameters:
geometry_tolerance (
float) – Maximum normalized joint difference for near copies.target_per_geometry (
int) – Maximum distinct timing variants per geometry.timing_tolerance_s (
float) – Maximum timing difference for duplicate episodes.target_per_band (
int|None) – Maximum reservations per band, orNonefor unbanded coverage that rejects band arguments.
Methods:
__init__(*[, geometry_tolerance, ...])confirm(commit_id)Confirm a reserved commit; repeated confirmations are idempotent.
family_of(commit_id)Return the geometry family a reserved commit was grouped into.
release(commit_id)Release an uncommitted reservation after write failure.
reserve(commit_id, geometry_family_id, ...)Reserve a distinct measured rollout before submitting its payload.
Attributes:
Return confirmed commit counts for each observed manipulability band.
Number of distinct geometries with a confirmed persistence receipt.
- __init__(*, geometry_tolerance=0.01, target_per_geometry=4, timing_tolerance_s=1e-06, target_per_band=None)[source]#
- property band_counts: dict[int, int]#
Return confirmed commit counts for each observed manipulability band.
- Returns:
A fresh mapping of band index to the number of confirmed commits.
- confirm(commit_id)[source]#
Confirm a reserved commit; repeated confirmations are idempotent.
- Parameters:
commit_id (
str) – Previously reserved persistence identity.- Return type:
None
- family_of(commit_id)[source]#
Return the geometry family a reserved commit was grouped into.
Near-identical geometries share one family even when their proposals requested different family identifiers, so this is the authoritative lineage for splitting a dataset by trajectory family.
- Parameters:
commit_id (
str) – Previously reserved persistence identity.- Return type:
str- Returns:
The resolved geometry family identifier.
- property geometry_count: int#
Number of distinct geometries with a confirmed persistence receipt.
- Returns:
The number of geometry groups containing at least one confirmed commit.
- release(commit_id)[source]#
Release an uncommitted reservation after write failure.
- Parameters:
commit_id (
str) – Previously reserved persistence identity.- Raises:
ValueError – If persistence has already been confirmed.
- Return type:
None
- reserve(commit_id, geometry_family_id, descriptor, *, band=None)[source]#
Reserve a distinct measured rollout before submitting its payload.
- Parameters:
commit_id (
str) – Stable, unique persistence identity.geometry_family_id (
str) – Family shared by proposed timing variants.descriptor (
TrajectoryDescriptor) – Descriptor calculated from the actual execution.band (
int|None) – Manipulability band index, required when a band quota is configured and rejected otherwise.
- Return type:
bool- Returns:
False for a near duplicate, or a geometry or band whose quota is full.
- class embodichain.lab.sim.motion.expansion.ManipulabilityProfile[source]#
Yoshikawa manipulability sampled along one trajectory.
- Parameters:
scores (
Tensor) – Per-sample manipulability with shape(T,).phase_ids (
tuple[str,...]) – Ordered labels of the phases that were scored.phase_bottlenecks (
Tensor) – Minimum score inside each phase, with shape(P,).
Methods:
__init__(scores[, phase_ids, phase_bottlenecks])Attributes:
Return the smallest sampled manipulability along the trajectory.
Return the average sampled manipulability along the trajectory.
- __init__(scores, phase_ids=(), phase_bottlenecks=<factory>)#
- property bottleneck: float#
Return the smallest sampled manipulability along the trajectory.
- Returns:
The minimum score, which marks the trajectory’s tightest posture.
- property mean: float#
Return the average sampled manipulability along the trajectory.
- Returns:
The arithmetic mean of the per-sample scores.
- embodichain.lab.sim.motion.expansion.describe_manipulability(jacobians, *, phases=(), rows='all')[source]#
Score a sampled trajectory’s Jacobians and align them with its phases.
- Parameters:
jacobians (
Tensor) – Per-sample Jacobians with shape(T, R, DOF), in the same sample order as the trajectory positions that produced them.phases (
tuple[TrajectoryPhase,...]) – Optional half-openTrajectoryPhaseranges whose bottleneck scores are reported separately.rows (
str|Sequence[int]) – Jacobian row selection forwarded toselect_jacobian_rows().
- Return type:
- Returns:
An owned CPU profile holding per-sample scores and phase bottlenecks.
- Raises:
ValueError – If the Jacobians are malformed or a phase is out of bounds.
- class embodichain.lab.sim.motion.expansion.ManipulabilityBands[source]#
Ordered manipulability bands normalized by one reference trajectory.
Ratios are taken against a reference value, usually the reference trajectory’s bottleneck manipulability, so band membership stays comparable across robots and tasks. Band
0holds the least manipulable postures and the final band the most manipulable ones; both outer bands are open-ended.- Parameters:
edges (
Sequence[float]) – Strictly increasing positive ratio boundaries.reference (
float) – Positive reference manipulability that normalizes scores.
Methods:
__init__(edges, *, reference)band_of(value)Return the band index owning an absolute manipulability score.
ratio(value)Normalize an absolute manipulability by the configured reference.
Attributes:
Return the number of bands, one more than the number of edges.
- band_of(value)[source]#
Return the band index owning an absolute manipulability score.
- Parameters:
value (
float) – Finite non-negative manipulability score.- Return type:
int- Returns:
The index in
[0, count)of the band containing the score’s ratio.
- property count: int#
Return the number of bands, one more than the number of edges.
- Returns:
The count of ordered bands, including both open-ended outer bands.
- class embodichain.lab.sim.motion.expansion.GuidedResidual[source]#
One selected residual proposal and the evidence used to select it.
- Parameters:
template (
TrajectoryTemplate) – The chosen candidate, still requiring independent validation.profile (
ManipulabilityProfile) – Manipulability measured along the chosen candidate.band (
int) – Band index containing the chosen candidate’s bottleneck.matched (
bool) – Whether the chosen candidate reached the requested band.proposals_scored (
int) – Number of proposals actually sampled and scored.
Methods:
__init__(template, profile, band, matched, ...)- __init__(template, profile, band, matched, proposals_scored)#
- embodichain.lab.sim.motion.expansion.manipulability_guided_residual(template, *, joint_limits, normalized_scale, generator, jacobian_fn, bands, target_band, proposals=4, rows='all')[source]#
Sample joint residuals and keep the one nearest a requested band.
Each proposal is an independent
joint_residual()draw from the supplied local generator, scored by the manipulability of the postures it actually visits. Steering toward a lower band deliberately retains tighter postures that remain task-valid, which uniform sampling around a comfortable reference rarely produces. Proposals that leave the joint limits are skipped; if every proposal fails, the last rejection is raised.Selection never asserts feasibility. The winning candidate still requires path, dynamic, and task validation exactly like an unguided residual.
- Parameters:
template (
TrajectoryTemplate) – Annotated full-joint reference permittingjoint_residual.joint_limits (
Tensor) – Finite lower/upper limits with shape(D, 2).normalized_scale (
float) – Maximum offset as a fraction of each joint range.generator (
Generator) – Explicit local generator; global RNG is never consumed.jacobian_fn (
Callable[[Tensor],Tensor]) – Maps candidate positions(T, D)to Jacobians(T, R, DOF).bands (
ManipulabilityBands) – Reference-normalized bands that classify a candidate.target_band (
int) – Requested band index withinbands.proposals (
int) – Number of residual draws to score, at least one.rows (
str|Sequence[int]) – Jacobian row selection used when scoring candidates.
- Return type:
- Returns:
The selected candidate with its measured profile and band.
- Raises:
ValueError – If permissions, arguments, or every sampled residual fail.
- class embodichain.lab.sim.motion.expansion.ExpansionSession[source]#
Own one job’s bounded candidates, budgets, evidence, and commit history.
This value-only session never reads an environment or steps a simulator. Call
mark_rollout_startedonly after the first actual command. A sink must provide one final outcome per submission and persistcommit_ididempotently across retries. Contradictory final receipts are rejected. The caller serializes operations. Cancellation means stopping new work and releasing individual candidates; pending writes still require final receipts. Byte limits include tensor data and serialized value metadata, excluding Python object allocation overhead. The runner separately bounds host buffers and any copies it allocates outside this session.- Parameters:
cfg (
TrajectoryExpansionCfg|TrajectoryExpansionJobCfg) – Semantically valid job settings, copied on construction.clock (
Callable[[],float]) – Monotonic seconds, injectable for deterministic budget tests.
Methods:
__init__(cfg, *[, clock])accept_episode(episode)Reserve passed measured evidence for writing; rejected evidence releases its slot.
add_planned(batch, validation)Atomically admit validated candidate rows within ready count and byte limits.
apply_receipt(receipt)Apply a final submission result to its original identity, idempotently.
episode_ids(identity)Return the deterministic episode and idempotent commit IDs for an attempt.
expansion_generator(case_id, ...)Allocate the next deterministic logical-expansion random stream.
manipulability_reference(case)Return the fixed guidance normalizer for a registered initial state.
mark_rollout_started(identity)Count an assigned candidate once its first command actually ran.
propose(case_id, initial_state_id, *, ...[, ...])Allocate stable lineage and a local CPU RNG independent of execution slots.
propose_many(requests)Atomically allocate physical candidate identities and private RNGs.
register_case(case, joint_limits, *, joint_names)Register immutable case conditions and complete joint normalization limits.
release(identity, *[, reason])Discard uncommitted work while preserving its failure reason and checks.
retry_write(commit_id)Re-reserve a failed payload and return a copy plus its next submission ID.
snapshot()Return read-only counters, case coverage, and lightweight lifecycle audit.
take_ready(case_id, initial_state_id, *[, ...])Reserve a row, rollout attempt, and pending payload capacity before execution.
Attributes:
Return the maximum bytes reservable by pending episode writes.
Report exhausted collection budgets while allowing outstanding results to finish.
- accept_episode(episode)[source]#
Reserve passed measured evidence for writing; rejected evidence releases its slot.
Joint positions, observation timestamps, and actual phase intervals supply coverage. Planned targets are never used as measured evidence.
- Parameters:
episode (
ExpertEpisode) – Actual commands, observations, and validation for a running candidate.- Return type:
bool- Returns:
Truewhen the episode is reserved for persistence;Falsewhen validation or coverage rejects it. No storage write occurs here.
- add_planned(batch, validation)[source]#
Atomically admit validated candidate rows within ready count and byte limits.
The caller owns physical planning checks. Nonempty, passing checks must include
path_collisionwhen required by this job.- Parameters:
batch (
CandidateTrajectoryBatch) – Planned rows matching candidates previously proposed by this session.validation (
ValidationResult) – One planning result per row, including required collision checks.
- Return type:
None
- apply_receipt(receipt)[source]#
Apply a final submission result to its original identity, idempotently.
A repeated receipt is ignored. Different outcomes for one submission are invalid even after retry; the sink must resolve ambiguous writes before reporting a final failure and releasing its reservation.
- Parameters:
receipt (
CommitReceipt) – Final outcome for an outstanding episode write submission.- Return type:
bool- Returns:
Truewhen a new success or failure receipt is applied, orFalsefor an identical previously applied receipt.
- episode_ids(identity)[source]#
Return the deterministic episode and idempotent commit IDs for an attempt.
- Parameters:
identity (
CandidateIdentity) – Candidate identity registered in this session.- Return type:
tuple[str,str]- Returns:
The episode ID and commit ID, stable across persistence retries.
- expansion_generator(case_id, initial_state_id, *, source_id, source_revision, template_id, operation_id)[source]#
Allocate the next deterministic logical-expansion random stream.
Logical expansion ordinals do not consume physical proposal capacity. The caller serializes this operation with the rest of the session.
- Return type:
Generator
- manipulability_reference(case)[source]#
Return the fixed guidance normalizer for a registered initial state.
- Parameters:
case (
SceneCase) – Exact scene and initial-state identity registered by the host.- Return type:
float|None- Returns:
The positive reference score, or
Nonewhen banded coverage is off.- Raises:
ValueError – If the case has not been registered with these conditions.
- mark_rollout_started(identity)[source]#
Count an assigned candidate once its first command actually ran.
- Parameters:
identity (
CandidateIdentity) – Assigned candidate whose first command has been executed.- Return type:
None
- property pending_max_bytes: int#
Return the maximum bytes reservable by pending episode writes.
- propose(case_id, initial_state_id, *, source_id, source_revision, template_id, operator_id, geometry_family_id=None, parent_id=None)[source]#
Allocate stable lineage and a local CPU RNG independent of execution slots.
- Parameters:
case_id (
str) – Registered scene-case identifier.initial_state_id (
str) – Registered initial state within that case.source_id (
str) – Identifier of the reference trajectory source.source_revision (
str) – Revision of the source used for this proposal.template_id (
str) – Identifier of the reference template.operator_id (
str) – Operator name selecting the deterministic proposal stream.geometry_family_id (
str|None) – Shared geometry lineage, orNonefor a new family.parent_id (
str|None) – Existing candidate in the same case and initial state, if any.
- Return type:
tuple[CandidateIdentity,Generator]- Returns:
The new candidate identity and its seeded local CPU generator.
- propose_many(requests)[source]#
Atomically allocate physical candidate identities and private RNGs.
- Return type:
tuple[tuple[CandidateIdentity,Generator],...]
- register_case(case, joint_limits, *, joint_names, manipulability_reference=None)[source]#
Register immutable case conditions and complete joint normalization limits.
manipulability_referencenormalizes measured manipulability into the configured bands and is usually the reference trajectory’s bottleneck score. It is required exactly when the manipulability factor is enabled. Because it describes one reference trajectory rather than the scene, it belongs to a single initial state and may differ between the initial states of one case; band quotas stay shared by scene case.- Parameters:
case (
SceneCase) – Scene and initial-state identity with fixed robot conditions.joint_limits (
Tensor) – Finite increasing joint intervals, shape(D_full, 2).joint_names (
tuple[str,...]) – Complete unique joint order matching the limit rows.manipulability_reference (
float|None) – Positive reference manipulability for band classification, orNonewhen banded coverage is disabled.
- Return type:
None
- release(identity, *, reason='discarded')[source]#
Discard uncommitted work while preserving its failure reason and checks.
- Parameters:
identity (
CandidateIdentity) – Candidate to release before a write is pending or confirmed.reason (
str) – Nonempty rejection or cancellation reason retained in diagnostics.
- Return type:
None
- retry_write(commit_id)[source]#
Re-reserve a failed payload and return a copy plus its next submission ID.
A failed write frees collection and coverage quota. Retry therefore fails if another candidate has occupied either quota in the meantime. It never adds a proposal, rollout attempt, or accepted-episode count.
- Parameters:
commit_id (
str) – Stable commit identifier of an episode whose last write failed.- Return type:
tuple[ExpertEpisode,int]- Returns:
An owned episode copy and the incremented submission ID for the retry.
- snapshot()[source]#
Return read-only counters, case coverage, and lightweight lifecycle audit.
Diagnostics retain each check’s status, first 256 detail characters, and first 16 numeric metrics. Results support at most 64 checks. Manipulability band counts stay empty while banded coverage is disabled. Pending reservations cover assigned/running upper bounds and retained payload bytes, including failed writes that remain available for retry.
- Return type:
Mapping[str,object]- Returns:
Immutable mappings of counters, reservations, coverage, candidate audit entries, diagnostics, and the current stop reason.
- property stop_reason: str | None#
Report exhausted collection budgets while allowing outstanding results to finish.
- Returns:
An exhausted budget identifier, or
Nonewhile new work is permitted.
- take_ready(case_id, initial_state_id, *, episode_byte_budget=None, candidate_id=None)[source]#
Reserve a row, rollout attempt, and pending payload capacity before execution.
episode_byte_budgetis a trusted upper bound on serialized metadata plus tensor data in the eventual episode.Nonereserves the entire pending byte limit, conservatively allowing only one outstanding episode. Smaller explicit bounds permit concurrent rows; exceeding a bound rejects the episode. The runner owns separate limits on host-side allocations.- Parameters:
case_id (
str) – Registered scene-case identifier to execute next.initial_state_id (
str) – Registered initial state whose ready rows may be selected.episode_byte_budget (
int|None) – Maximum episode payload bytes to reserve for this row.candidate_id (
str|None) – Optional exact ready candidate to reserve. Omission preserves deterministic FIFO selection within the case.
- Return type:
CandidateTrajectoryBatch|None- Returns:
One assigned candidate row, or
Nonewhen no matching row or capacity is available or the session has stopped.
Task-Space Deformation and Segment Stitching#
These pure-trajectory helpers do not consume visual observations or affordance
labels. task_space_from_joint_template evaluates an existing full-joint
template through an injected batched kinematics function. Editable free phases
may then receive bounded root-frame translation and rotation residuals from
deform_task_space_trajectory. The deformation envelope is zero at both
phase endpoints. project_task_space_trajectory solves all editable interior
samples with batched damped least squares, leaves locked samples and phase
endpoints at their exact reference qpos, and returns per-sample pose residuals
and success evidence. The result still requires collision, dynamics, and task
validation before execution.
extract_trajectory_segments converts annotated demonstrations into
local-time, source-owned phases. TrajectorySegmentBank filters candidates
by semantic phase, motion kind, joint layout, controlled joints, dtype, device,
and timing dtype, then selects deterministically in FIFO or nearest-start
order. stitch_trajectory_segments de-duplicates shared boundaries and
retains multi-source lineage. Discontinuous boundaries require an explicit
TrajectoryBridgePlanner. MinimumJerkBridgePlanner is a velocity- and
acceleration-limited geometric fallback; it does not claim collision freedom.
The stitched TrajectoryTemplate can be passed directly to
TemplateSourceAdapter. Task-space projection also returns a normal
TrajectoryTemplate, so both paths compose with existing candidate
coordination, execution, validation, and persistence integrations without
giving this package ownership of simulator state.
- embodichain.lab.sim.motion.expansion.TASK_SPACE_RESIDUAL_OPERATOR = 'task_space_residual'#
str(object=’’) -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to ‘strict’.
- class embodichain.lab.sim.motion.expansion.TaskSpaceDeformationConstraint[source]#
Per-phase bounds for one root-frame Cartesian deformation.
- Parameters:
phase_id (
str) – Phase authorized to use this constraint.translation_axes (
tuple[bool,bool,bool]) – Root-frame translation axes that may change.rotation_axes (
tuple[bool,bool,bool]) – Root-frame rotation-vector axes that may change.max_translation_m (
float) – Maximum translation-vector norm in meters.max_rotation_rad (
float) – Maximum rotation-vector norm in radians.
Methods:
__init__(phase_id[, translation_axes, ...])- __init__(phase_id, translation_axes=(True, True, True), rotation_axes=(True, True, True), max_translation_m=0.0, max_rotation_rad=0.0)#
- class embodichain.lab.sim.motion.expansion.TaskSpaceTrajectory[source]#
One single-frame Cartesian trajectory aligned with a joint template.
Poses map the controlled frame into the kinematics root frame. This is an intermediate expansion value: a caller must project and physically validate it before execution.
- Parameters:
source_id (
str) – Stable source identity.source_revision (
str) – Source revision used to create the trajectory.template_id (
str) – Source-unit identity aligned with the joint template.frame_id (
str) – Controlled tool or end-effector frame.poses (
Tensor) – Root-frame transforms with shape(T, 4, 4).dt (
Tensor) – Arrival intervals with shape(T,); the first value is zero.phases (
tuple[TrajectoryPhase,...]) – Ordered semantic phase annotations.allowed_operators (
tuple[str,...]) – Operators authorized anywhere in the trajectory.validator_id (
str) – Physical validation contract required downstream.
Methods:
__init__(source_id, source_revision, ...[, ...])- __init__(source_id, source_revision, template_id, frame_id, poses, dt, phases=(), allowed_operators=(), validator_id='default')#
- class embodichain.lab.sim.motion.expansion.TaskSpaceProjectionResult[source]#
Projected qpos trajectory and per-sample Cartesian residual evidence.
- Parameters:
template (
TrajectoryTemplate) – Final DLS iterate in the original full joint layout.success (
Tensor) – Per-sample IK and locked-reference verification mask.position_error (
Tensor) – Final root-frame translation residuals, shape(T, 3).rotation_error (
Tensor) – Final root-frame rotation residuals, shape(T, 3).
Methods:
__init__(template, success, position_error, ...)Attributes:
Return whether every trajectory sample satisfies the IK contract.
- __init__(template, success, position_error, rotation_error)#
- property accepted: bool#
Return whether every trajectory sample satisfies the IK contract.
- Returns:
Trueonly when every sample passes pose and joint-limit checks.
- embodichain.lab.sim.motion.expansion.task_space_from_joint_template(template, *, frame_id, kinematics, editable_phase_ids=())[source]#
Evaluate one joint template and authorize selected free phases.
- Parameters:
template (
TrajectoryTemplate) – Full-joint qpos reference trajectory.frame_id (
str) – Controlled kinematic frame identity.kinematics (
Callable[[Tensor],tuple[Tensor,Tensor]]) – Batched FK/Jacobian callable over controlled joints.editable_phase_ids (
Sequence[str]) – Free phases allowed to receive Cartesian residuals.
- Return type:
- Returns:
An owned task-space trajectory aligned sample-for-sample with
template.
- embodichain.lab.sim.motion.expansion.deform_task_space_trajectory(trajectory, *, constraints, generator)[source]#
Apply smooth root-frame twists while preserving every phase endpoint.
- Parameters:
trajectory (
TaskSpaceTrajectory) – Cartesian reference with explicit phase permissions.constraints (
Mapping[str,TaskSpaceDeformationConstraint]) – Exactly one bounded deformation contract per editable phase.generator (
Generator) – Explicit local generator; global RNG is never consumed.
- Return type:
- Returns:
A new Cartesian trajectory requiring IK, path, and physical validation.
- embodichain.lab.sim.motion.expansion.project_task_space_trajectory(trajectory, reference, *, kinematics, joint_limits, ik_cfg=None)[source]#
Project editable Cartesian samples back into the reference joint layout.
Locked samples and every phase endpoint retain the reference qpos exactly. Editable samples are solved together with fixed-iteration damped least squares, keeping storage linear in
T * (DOF + task_dim).- Parameters:
trajectory (
TaskSpaceTrajectory) – Task-space target aligned withreference.reference (
TrajectoryTemplate) – Full-joint seed and locked-sample source.kinematics (
Callable[[Tensor],tuple[Tensor,Tensor]]) – Batched FK/Jacobian callable over controlled joints.joint_limits (
Tensor) – Full ordered lower/upper limits with shape(D, 2).ik_cfg (
DifferentiableIKCfg|None) – Optional fixed-step DLS configuration.
- Return type:
- Returns:
Final qpos iterate and per-sample residual evidence. Failed samples are retained for diagnostics and must not be executed as expert data.
- class embodichain.lab.sim.motion.expansion.TrajectorySegment[source]#
One owned source phase normalized onto a segment-local time axis.
- Parameters:
segment_id (
str) – Stable identity of this source segment.source_id (
str) – Source trajectory provider identity.source_revision (
str) – Source provider revision.source_template_id (
str) – Template containing the original phase.source_start_index (
int) – Inclusive phase start in the source template.source_stop_index (
int) – Exclusive phase stop in the source template.phase_id (
str) – Semantic phase used for replacement compatibility.kind (
Literal['free','contact','hold']) – Motion mode: free, contact, or hold.joint_names (
tuple[str,...]) – Complete ordered joint layout.positions (
Tensor) – Segment positions with shape(N >= 2, D).dt (
Tensor) – Local arrival intervals withdt[0] == 0.allowed_operators (
tuple[str,...]) – Operators permitted on this phase.controlled_joint_indices (
tuple[int,...]) – Joints controlled by the source trajectory.validator_id (
str) – Downstream physical validation contract.
Methods:
__init__(segment_id, source_id, ...[, ...])- __init__(segment_id, source_id, source_revision, source_template_id, source_start_index, source_stop_index, phase_id, kind, joint_names, positions, dt, allowed_operators=(), controlled_joint_indices=(), validator_id='default')#
- class embodichain.lab.sim.motion.expansion.SegmentCompatibility[source]#
Replacement compatibility and boundary distances for two segments.
- Parameters:
compatible (
bool) – Whether the candidate may replace the reference segment.reasons (
tuple[str,...]) – Field names that make an incompatible pair unsafe to combine.start_distance (
float) – Joint-space distance between the starting samples.end_distance (
float) – Joint-space distance between the ending samples.
Methods:
__init__(compatible, reasons, ...)- __init__(compatible, reasons, start_distance, end_distance)#
- class embodichain.lab.sim.motion.expansion.TrajectorySegmentBank[source]#
Insertion-ordered source segments with deterministic selection policies.
- Parameters:
segments (
Sequence[TrajectorySegment]) – Initial immutable segments in registration order.
Methods:
__init__([segments])add(segment)Register one uniquely identified immutable segment.
candidates(reference)Return insertion-ordered segments compatible with a reference slot.
select(reference, *[, strategy, ...])Select one compatible source segment deterministically.
- add(segment)[source]#
Register one uniquely identified immutable segment.
- Parameters:
segment (
TrajectorySegment) – Segment to retain in insertion order.- Return type:
None
- candidates(reference)[source]#
Return insertion-ordered segments compatible with a reference slot.
- Parameters:
reference (
TrajectorySegment) – Semantic phase and layout contract to match.- Return type:
tuple[TrajectorySegment,...]- Returns:
Compatible source segments in stable registration order.
- select(reference, *, strategy='fifo', current_position=None, ordinal=0)[source]#
Select one compatible source segment deterministically.
- Parameters:
reference (
TrajectorySegment) – Semantic phase and layout contract to match.strategy (
Literal['fifo','nearest_start']) – Registration order or nearest starting joint state.current_position (
Tensor|None) – Full joint state required bynearest_start.ordinal (
int) – Stable selection rank after applying the strategy.
- Return type:
- Returns:
The selected compatible source segment.
- class embodichain.lab.sim.motion.expansion.TrajectoryBridge[source]#
One planner-produced joint transition including both boundary samples.
- Parameters:
positions (
Tensor) – Full joint positions with shape(N >= 2, D).dt (
Tensor) – Local arrival intervals withdt[0] == 0.
Methods:
__init__(positions, dt)- __init__(positions, dt)#
- class embodichain.lab.sim.motion.expansion.TrajectoryBridgePlanner[source]#
Plan a joint transition between two segment boundary states.
Methods:
__init__(*args, **kwargs)plan(start_position, goal_position)Plan a transition containing the exact start and goal samples.
- __init__(*args, **kwargs)#
- plan(start_position, goal_position)[source]#
Plan a transition containing the exact start and goal samples.
- Parameters:
start_position (
Tensor) – Full starting joint state with shape(D,).goal_position (
Tensor) – Full goal joint state with shape(D,).
- Return type:
- Returns:
A transition whose first and last positions equal the inputs.
- class embodichain.lab.sim.motion.expansion.MinimumJerkBridgePlanner[source]#
Generate rest-to-rest bridges under sampled velocity/acceleration limits.
This geometric fallback does not check collisions. A host should inject a collision-aware planner for cluttered transitions and validate every final stitched trajectory before execution.
- Parameters:
control_dt (
float) – Positive host control period in seconds.velocity_limits (
Tensor) – Positive per-joint velocity limits.acceleration_limits (
Tensor) – Positive per-joint acceleration limits.minimum_sample_count (
int) – Lower bound for interpolation samples.
Methods:
__init__(control_dt, velocity_limits, ...[, ...])plan(start_position, goal_position)Interpolate one exact endpoint pair on the configured control clock.
- __init__(control_dt, velocity_limits, acceleration_limits, minimum_sample_count=3)#
- plan(start_position, goal_position)[source]#
Interpolate one exact endpoint pair on the configured control clock.
- Parameters:
start_position (
Tensor) – Full starting joint state, shape(D,).goal_position (
Tensor) – Full goal joint state, shape(D,).
- Return type:
- Returns:
A rest-to-rest minimum-jerk transition requiring collision checks.
- class embodichain.lab.sim.motion.expansion.StitchedSegmentPlacement[source]#
Source-segment lineage aligned with its half-open output sample range.
- Parameters:
segment_id (
str) – Stable identity of the source segment.source_id (
str) – Source trajectory provider identity.source_revision (
str) – Source provider revision.source_template_id (
str) – Template containing the source phase.source_start_index (
int) – Inclusive source phase start.source_stop_index (
int) – Exclusive source phase stop.output_phase_id (
str) – Unique phase identity in the stitched template.output_start_index (
int) – Inclusive output phase start.output_stop_index (
int) – Exclusive output phase stop.
Methods:
__init__(segment_id, source_id, ...)- __init__(segment_id, source_id, source_revision, source_template_id, source_start_index, source_stop_index, output_phase_id, output_start_index, output_stop_index)#
- class embodichain.lab.sim.motion.expansion.StitchedTrajectory[source]#
A stitched qpos template with explicit multi-source segment lineage.
- Parameters:
template (
TrajectoryTemplate) – Composite full-joint trajectory accepted by expansion sources.placements (
tuple[StitchedSegmentPlacement,...]) – Source lineage for every non-bridge output phase.bridge_phase_ids (
tuple[str,...]) – Output phases produced by boundary planners.
Methods:
__init__(template, placements[, ...])- __init__(template, placements, bridge_phase_ids=())#
- embodichain.lab.sim.motion.expansion.extract_trajectory_segments(template)[source]#
Extract every annotated phase as an independently owned segment.
- Parameters:
template (
TrajectoryTemplate) – Phase-annotated full-joint source trajectory.- Return type:
tuple[TrajectorySegment,...]- Returns:
Source-order segments with local timing and retained source lineage.
- embodichain.lab.sim.motion.expansion.compare_trajectory_segments(reference, candidate)[source]#
Compare whether a candidate may replace one semantic source phase.
- Parameters:
reference (
TrajectorySegment) – Segment slot whose semantics and joint layout must be retained.candidate (
TrajectorySegment) – Source segment proposed for that slot.
- Return type:
- Returns:
Compatibility reasons plus unnormalized start/end joint distances.
- embodichain.lab.sim.motion.expansion.stitch_trajectory_segments(segments, *, source_id, source_revision, template_id, bridge_planner=None, boundary_tolerance=1e-06, validator_id=None)[source]#
Concatenate phase segments and explicitly plan discontinuous boundaries.
Segment first samples are shared boundaries and are emitted only once. The adjacent output phases both reference that one endpoint, which keeps each phase independently extractable without duplicating trajectory samples. A planned bridge follows the same boundary convention. The result is structurally continuous but still requires motion-limit, collision, and task validation.
- Parameters:
segments (
Sequence[TrajectorySegment]) – Ordered source phases to compose.source_id (
str) – Identity of the new composite source.source_revision (
str) – Revision of the composition policy.template_id (
str) – Identity of this stitched source unit.bridge_planner (
TrajectoryBridgePlanner|None) – Required when adjacent boundary positions differ.boundary_tolerance (
float) – Maximum absolute joint difference treated as shared.validator_id (
str|None) – Override for the final validator; omitted requires all source segments to agree.
- Return type:
- Returns:
A full qpos template plus source and bridge lineage.
Trajectory Variants#
These helpers answer a narrower question than affordance expansion: given a reference trajectory whose annotated waypoints are already settled, how many genuinely different ways are there to execute it? Only the free motion between annotated phase endpoints changes, so contacts, grasps, and placements stay exactly where planning put them.
Configuration is optional. Asking for a number of variants is enough: the
helpers resolve default_variant_factors(), which enables every
implemented factor the supplied inputs support at magnitudes measured to stay
executable, and leaves the null-space factor off when no Jacobians are given.
An explicitly constructed configuration is never overridden. An explicitly
enabled factor that cannot produce a variant raises rather than disappearing:
ik without task_jacobians, and approach, whose Cartesian standoff
poses have to be replanned through IK before they are a trajectory. The resolved settings come back on the
result’s cfg.
plan_trajectory_variants enumerates deterministic factor combinations without
touching a trajectory. Ordinal zero is always the unmodified reference, and
later ordinals cycle through the enabled spatial operators, then the duration
scales, then the time warps. apply_trajectory_variant applies one such
combination, running at most one joint-path operator so a null-space
projection is never stacked on an already displaced joint path. Neither
function can see whether the caller has Jacobians, so both resolve the default
policy with the null-space factor off and the pair works unconfigured. Pass
default_variant_factors(redundancy=True) to both, or use
expand_trajectory_variants, to include posture variants.
expand_trajectory_variants collects several variants for one fixed scene. It
rejects proposals that an operator refuses, that fail sampled motion limits, or
whose measured geometry and timing duplicate an accepted row. Each rejection is
counted under a key naming its reason, so a caller can retune the offending
setting instead of guessing why a proposal disappeared.
Only ProposalRejected counts as a rejection. Operators raise it for
outcomes that depend on the draw, such as a residual leaving the joint limits;
malformed arguments and impossible configurations stay plain ValueError and
propagate, so a caller error cannot hide in a rejection count behind an
already successful nominal variant.
spatial.method and ik.task_rows are both applied in the variant path:
the configured rows are selected from the supplied spatial Jacobians before the
null-space projection, so callers pass every row their task could constrain
rather than pre-reducing them.
Joint-limit rejection covers only the joints an operator actually moved. An observed reference can hold an untouched joint a few microradians outside its declared range, and blaming a sampled residual for that would reject every proposal.
Deduplication compares measured joint geometry and elapsed phase time. It does
not certify collision freedom, task success, or dynamic feasibility; each
accepted row must still be executed and validated by the host.
sample_approach_cone samples angles for the Cartesian approach operator and
is likewise a geometric proposal only.
- class embodichain.lab.sim.motion.expansion.TrajectoryVariant[source]#
One deterministic combination of augmentation factors.
- Parameters:
ordinal (
int) – Zero-based enumeration index; ordinal zero is the reference.spatial_operator (
str) – Applied joint-path operator, or"none".duration_scale (
float) – Free-phase duration factor passed to retiming.timing_profile (
str) – Within-phase time warp passed to retiming.task_space (
bool) – Whether to deform and project the tool path before retiming.manipulability_band (
int|None) – Requested guidance band, orNonefor unguided draws.
Methods:
__init__(ordinal, spatial_operator, ...[, ...])Attributes:
Return this variant's provenance for candidate-row metadata.
Whether this variant leaves the reference trajectory unchanged.
- __init__(ordinal, spatial_operator, duration_scale, timing_profile, task_space=False, manipulability_band=None)#
- property factors: dict[str, float | int | str]#
Return this variant’s provenance for candidate-row metadata.
- Returns:
Finite JSON-compatible factor values describing the variant.
- property is_nominal: bool#
Whether this variant leaves the reference trajectory unchanged.
- Returns:
Truewhen no spatial operator and no retiming apply.
- class embodichain.lab.sim.motion.expansion.TrajectoryVariantSet[source]#
Accepted candidate rows together with the accounting that produced them.
- Parameters:
candidates (
CandidateTrajectoryBatch) – Accepted rows, the first of which is the reference branch.variants (
tuple[TrajectoryVariant,...]) – One accepted variant per candidate row, in row order.attempted (
int) – Number of proposals evaluated, including rejections.rejected (
Mapping[str,int]) – Count of rejected proposals by reason.cfg (
TrajectoryAugmentationCfg|None) – Settings that produced these variants, including a policy resolved on the caller’s behalf.Noneonly when a caller builds this value itself.
Methods:
__init__(candidates, variants, attempted, ...)- __init__(candidates, variants, attempted, rejected, cfg=None)#
- embodichain.lab.sim.motion.expansion.NOMINAL_OPERATOR = 'none'#
str(object=’’) -> str str(bytes_or_buffer[, encoding[, errors]]) -> str
Create a new string object from the given object. If encoding or errors is specified, then the object must expose a data buffer that will be decoded using the given encoding and error handler. Otherwise, returns the result of object.__str__() (if defined) or repr(object). encoding defaults to sys.getdefaultencoding(). errors defaults to ‘strict’.
- embodichain.lab.sim.motion.expansion.default_variant_factors(*, seed=0, redundancy=True)[source]#
Enable every implemented factor at magnitudes known to stay executable.
This is what the expansion helpers use when a caller asks for a number of variants without describing how to produce them. Callers that do care can build a
TrajectoryAugmentationCfgthemselves; an explicitly constructed configuration is never overridden.The offsets are fractions of each joint’s declared range, so their absolute size depends on how generous the robot’s limits are. They are a starting point, not a guarantee: the host still has to execute and validate what comes back.
- Parameters:
seed (
int) – Base seed for the sampling streams.redundancy (
bool) – Whether the caller can supply task Jacobians. When false the null-space factor is left off instead of proposing variants that would be rejected for missing inputs.
- Return type:
- Returns:
A configuration enabling the spatial, timing and optional ik factors.
- embodichain.lab.sim.motion.expansion.plan_trajectory_variants(count, cfg=None)[source]#
Enumerate deterministic factor combinations without touching a trajectory.
Ordinal zero is always the unmodified reference. Later ordinals cycle through the enabled spatial operators, then the duration scales, then the within-phase time warps, so a small request still spreads across every enabled dimension instead of exhausting one. Stochastic operators repeat with a different local seed, which is why the enumeration is unbounded while the number of distinct results is not.
- Parameters:
count (
int) – Number of variants to enumerate, at least one.cfg (
TrajectoryAugmentationCfg|None) – Augmentation settings whose enabled factors select the combinations. Defaults todefault_variant_factors()with redundancy off, because this function cannot know whether the caller has task Jacobians. Passdefault_variant_factors(redundancy=True), or useexpand_trajectory_variants(), to include posture variants.
- Return type:
tuple[TrajectoryVariant,...]- Returns:
Deterministically ordered variants beginning with the reference branch.
- Raises:
ValueError – If
countis not a positive integer, or if the configuration enables a factor that cannot produce a qpos variant.
- embodichain.lab.sim.motion.expansion.apply_trajectory_variant(template, variant, *, cfg=None, joint_limits, control_dt, task_jacobians=None, generator=None, kinematics=None, manipulability_reference=None)[source]#
Apply a joint/task-space proposal, optional guidance, then retiming.
At most one joint-path operator runs per proposal. A combined task-space proposal projects before joint edits and re-projects afterward. Null-space edits use fresh Jacobians when the task-space projection moved the path. Guidance samples up to
guided_proposalsdraws and selects the first matching band, or the nearest reachable band with stable tie-breaking.The default generator is seeded from the configuration seed, the template identifier and the variant ordinal, so the same variant applied to two differently identified references draws independently while remaining reproducible.
- Parameters:
template (
TrajectoryTemplate) – Annotated reference whose phase endpoints are already fixed.variant (
TrajectoryVariant) – Factor combination to apply; a nominal variant returns the reference.cfg (
TrajectoryAugmentationCfg|None) – Augmentation settings supplying operator magnitudes and the seed. Defaults todefault_variant_factors(), with redundancy enabled whentask_jacobiansorkinematicsis supplied.joint_limits (
Tensor) – Finite lower/upper limits with shape(D, 2).control_dt (
float) – Authoritative host control period used by retiming.task_jacobians (
Tensor|None) – Reference spatial Jacobians(N, R, C)for the declared controlled joints, required only by the redundancy operator.cfg.factors.ik.task_rowsselects the constrained rows from them, so supply every row the task could constrain.generator (
Generator|None) – Optional explicit local generator replacing the derived one.kinematics (
Callable[[Tensor],tuple[Tensor,Tensor]] |None) – Batched root-frame FK/Jacobian callable over controlled columns; required by task-space deformation and guidance.manipulability_reference (
float|None) – Positive reference score for guidance bands. Omission measures the nominal trajectory; hosted callers use the initial state’s registered reference.
- Return type:
- Returns:
A new template requiring path and physical validation.
- Raises:
ValueError – If the variant names an unknown operator, if required inputs are missing, or if an operator rejects its own proposal.
- embodichain.lab.sim.motion.expansion.expand_trajectory_variants(template, *, case, count, cfg=None, joint_limits, control_dt, velocity_limits=None, acceleration_limits=None, task_jacobians=None, generator=None, max_attempts=None, kinematics=None, manipulability_reference=None)[source]#
Generate up to
countdistinct execution variants for one fixed reference.Row zero is the unmodified reference, so a caller always retains the trajectory it already trusts. Later rows apply the configured joint, task-space and guidance factors before the timing choice. A proposal is discarded when an operator rejects it, when sampled motion limits fail, or when its measured geometry and timing duplicate an already accepted row. Every rejection is counted and reported rather than silently dropped.
Accepted rows share the candidate padding rule: padded samples repeat the final valid position and carry zero arrival intervals, so a shorter row holds its final command instead of being executed past its own end. Use
valid_maskbefore recording.Deduplication compares measured joint geometry and elapsed phase time. It does not certify collision freedom, task success or dynamic feasibility; the host must still execute and validate each accepted row.
- Parameters:
template (
TrajectoryTemplate) – Annotated reference whose phase endpoints are already fixed.case (
SceneCase) – Scene and initial-state identity shared by every candidate.count (
int) – Maximum number of accepted variants, at least one.cfg (
TrajectoryAugmentationCfg|None) – Augmentation settings selecting factors, seed and coverage limits. Omit it to enable every implemented factor the supplied inputs support, throughdefault_variant_factors().joint_limits (
Tensor) – Finite lower/upper limits with shape(D, 2).control_dt (
float) – Authoritative host control period used by retiming.velocity_limits (
Tensor|None) – Optional positive per-joint speed bounds, shape(D,).acceleration_limits (
Tensor|None) – Optional positive per-joint acceleration bounds.task_jacobians (
Tensor|None) – Reference spatial Jacobians(N, R, C)required only when the ik factor is enabled.cfg.factors.ik.task_rowsselects the constrained rows, so supply every row the task could constrain rather than pre-reducing them.generator (
Generator|None) – Optional private CPU generator shared by the sequential proposal draws. Omission preserves standalone digest-based streams.max_attempts (
int|None) – Total numerical-draw budget, including guidance’s inner proposals. Defaults to four per requested variant.kinematics (
Callable[[Tensor],tuple[Tensor,Tensor]] |None) – Batched root-frame FK/Jacobian callable over controlled columns, required by task-space deformation and guided selection.manipulability_reference (
float|None) – Positive band normalizer. Omission measures the nominal reference; coordinators use the registered initial state.
- Return type:
- Returns:
The accepted candidate rows, their variants, and rejection accounting.
- Raises:
ValueError – If arguments are malformed, if limits are supplied inconsistently, or if an explicitly enabled factor is missing the inputs it needs.
- embodichain.lab.sim.motion.expansion.sample_approach_cone(cfg, *, count, generator)[source]#
Sample tilt angles for
perturb_approach_direction().The first pair is the nominal direction with zero tilt, preserving the reference branch. Remaining pairs are uniform over the spherical cap area, so directions do not bunch near the cone axis. Sampling is a geometric proposal only: reachability, clearance and grasp validity belong to the caller that replans the resulting poses.
- Parameters:
cfg (
TrajectoryAugmentationCfg) – Augmentation settings whose approach factor must be enabled.count (
int) – Number of direction candidates, at least one.generator (
Generator) – Explicit local generator; global RNG is never consumed.
- Return type:
tuple[Tensor,Tensor]- Returns:
Polar and azimuth angle tensors in radians, each with shape
(count,).- Raises:
ValueError – If the approach factor is disabled or
countis invalid.
Implementation Modules#
The following module paths expose the same contracts and implementations. The package import path above is convenient for callers combining them.
A fixed scene and allowed initial state, with no live environment references. |
|
One copied complete robot state; poses map local frames into the world. |
|
An explicitly annotated half-open sample interval |
|
A full-joint qpos reference with arrival intervals and explicit permissions. |
|
Candidate lineage independent of execution slots and their epochs. |
|
Validated input for one transactional candidate identity allocation. |
|
Source-neutral physical candidate lineage before slot assignment. |
|
Logical candidate rows with safe padding and no physical batch assumption. |
|
One mandatory check; unavailable and not-run checks cannot accept data. |
|
A fail-closed collection of required validation checks. |
|
Frozen rollout evidence with causal |
|
Sink confirmation tied to stable episode/candidate IDs, never a slot. |
Stable source and scene identity supplied by a expansion coordinator. |
|
Convert one expert source unit into a reusable trajectory template. |
|
Adapt an already annotated handwritten qpos template. |
|
Adapt one single-row MotionGenerator result to a qpos template. |
Generate source-neutral candidates without owning physical execution. |
|
One logical candidate ready for planning validation or slot assignment. |
Load one callable-free combined Expansion Profile. |
- embodichain.lab.sim.motion.expansion.profile.load_expansion_profile(path)[source]#
Load one callable-free combined Expansion Profile.
- Parameters:
path (
str|Path) – YAML or JSON profile path.- Return type:
- Returns:
Strictly decoded and semantically validated combined profile.
- Raises:
TypeError – If the serialized root is not a mapping.
ValueError – If the profile contains unknown or invalid fields.
|
Joint-path methods the spatial factor can enumerate. |
Local random seed, explicitly enabled factors, and geometry coverage limits. |
|
Source-neutral expansion settings shared by every expert source. |
|
Standalone expansion job configuration; control periods remain host-owned. |
Measured joint geometry and elapsed times at uniform phase progress. |
|
|
Describe an actual rollout without rewarding additional time samples. |
Reserve near-distinct measured trajectories and count confirmed geometry. |
Yoshikawa manipulability sampled along one trajectory. |
|
Ordered manipulability bands normalized by one reference trajectory. |
|
One selected residual proposal and the evidence used to select it. |
|
|
Score a sampled trajectory's Jacobians and align them with its phases. |
|
Sample joint residuals and keep the one nearest a requested band. |
|
Return the free phases a template authorizes one operator to reshape. |
|
Rotate a reference grasp about an axis through a fixed object's origin. |
|
Place standoff poses on a cone around a nominal approach direction. |
|
Add one smooth, endpoint-preserving residual per allowed free phase. |
|
Route each allowed free phase through sampled interior joint knots. |
|
Move through the redundancy of a declared task while holding its rows. |
|
Retime permitted free phases and resample onto the host control clock. |
|
Monotone within-phase time warps selectable by |
One sampled proposal is unusable; another draw may well succeed. |
|
|
Check sampled finite-difference motion limits without asserting task success. |
|
Spatial-operator name of the preserved unmodified reference branch. |
One deterministic combination of augmentation factors. |
|
Accepted candidate rows together with the accounting that produced them. |
|
|
Enable every implemented factor at magnitudes known to stay executable. |
|
Enumerate deterministic factor combinations without touching a trajectory. |
|
Apply a joint/task-space proposal, optional guidance, then retiming. |
|
Generate up to |
|
Sample tilt angles for |
|
Phase permission used by endpoint-preserving Cartesian deformation. |
Per-phase bounds for one root-frame Cartesian deformation. |
|
One single-frame Cartesian trajectory aligned with a joint template. |
|
Projected qpos trajectory and per-sample Cartesian residual evidence. |
|
|
Evaluate one joint template and authorize selected free phases. |
|
Apply smooth root-frame twists while preserving every phase endpoint. |
|
Project editable Cartesian samples back into the reference joint layout. |
One owned source phase normalized onto a segment-local time axis. |
|
Replacement compatibility and boundary distances for two segments. |
|
Insertion-ordered source segments with deterministic selection policies. |
|
One planner-produced joint transition including both boundary samples. |
|
Plan a joint transition between two segment boundary states. |
|
Generate rest-to-rest bridges under sampled velocity/acceleration limits. |
|
Source-segment lineage aligned with its half-open output sample range. |
|
A stitched qpos template with explicit multi-source segment lineage. |
|
|
Extract every annotated phase as an independently owned segment. |
|
Compare whether a candidate may replace one semantic source phase. |
|
Concatenate phase segments and explicitly plan discontinuous boundaries. |
Own one job's bounded candidates, budgets, evidence, and commit history. |
Combined Episode Scheduling#
The combined profile and recipe values describe a complete repeated episode. They are simulator-independent, so a host can validate capacity and persist the same schedule before assigning any physical environment row.
Strict episode-level profile for the combined showcase. |
|
One immutable legal initial cube pose and its authored targets. |
|
Return deterministic authored cube pose families for a expansion job. |
|
Requested affordance and trajectory ordinals for one Pick/Place cycle. |
|
Requested affordance and trajectory ordinals for one workflow call. |
|
Complete episode recipe; identity is independent of simulator row. |
|
Opaque reservation returned by |
|
Generic compatible-slot reservation with exact release semantics. |
|
Enumerate the deterministic |
|
Load and validate seedable visual profile IDs. |
|
Hash the complete schedule in order for deterministic rerun checks. |
- class embodichain.lab.sim.motion.expansion.combined.CombinedExpansionProfile[source]#
Strict episode-level profile for the combined showcase.
Methods:
from_mapping(data)Decode the canonical combined schema without evaluating callables.
validate_for_num_envs(num_envs)Validate the host-owned slot capacity before simulator construction.
validate_registries(*, visual_profile_ids, ...)Validate that host registries contain each requested profile once.
- classmethod from_mapping(data)[source]#
Decode the canonical combined schema without evaluating callables.
- Return type:
- class embodichain.lab.sim.motion.expansion.combined.ReferenceFamilySpec[source]#
One immutable legal initial cube pose and its authored targets.
Methods:
__init__(reference_family_id, cube_position, ...)- __init__(reference_family_id, cube_position, cube_quaternion_xyzw, drop_targets, deterministic_seed, profile_revision='cube_initial_pose:v1', scene_signature='repeated_pick_place_scene_v1')#
- class embodichain.lab.sim.motion.expansion.combined.CubeInitialPoseProvider[source]#
Return deterministic authored cube pose families for a expansion job.
Methods:
__init__([poses, family_ids, ...])enumerate([count])Enumerate the first
countlegal deterministic families.from_yaml(path, *[, seed])Load authored cube families from a strict pose profile.
- __init__(poses=None, *, family_ids=None, profile_revision='cube_initial_pose:v1', drop_targets=(('drop_pose_00', (-0.4, 0.48, 0.1)), ('drop_pose_01', (-0.42, -0.08, 0.1))), seed=0)[source]#
- enumerate(count=None)[source]#
Enumerate the first
countlegal deterministic families.- Return type:
tuple[ReferenceFamilySpec,...]
- class embodichain.lab.sim.motion.expansion.combined.CycleRecipe[source]#
Requested affordance and trajectory ordinals for one Pick/Place cycle.
Methods:
__init__(cycle_index, affordance_requested, ...)- __init__(cycle_index, affordance_requested, trajectory_requested)#
- class embodichain.lab.sim.motion.expansion.combined.CallRecipe[source]#
Requested affordance and trajectory ordinals for one workflow call.
Methods:
__init__(call_index, affordance_requested, ...)- __init__(call_index, affordance_requested, trajectory_requested)#
- class embodichain.lab.sim.motion.expansion.combined.CandidateRecipe[source]#
Complete episode recipe; identity is independent of simulator row.
Methods:
__init__(recipe_index, candidate_id, ...)- __init__(recipe_index, candidate_id, reference_family_id, physical_geometry_family_id, cycle_schedule, call_schedule, visual_profile_id, visual_seed, source_unit_id, source_revision, deterministic_seed_digest)#
- class embodichain.lab.sim.motion.expansion.combined.SlotReservation[source]#
Opaque reservation returned by
PhysicalSlotPool.Methods:
__init__(slot_id, candidate_id, ...)- __init__(slot_id, candidate_id, compatibility_key, token)#
- class embodichain.lab.sim.motion.expansion.combined.PhysicalSlotPool[source]#
Generic compatible-slot reservation with exact release semantics.
A slot can advertise a strict compatibility key. Candidates remain independent of the numeric slot they receive; releasing a stale or foreign reservation raises rather than freeing another candidate’s slot.
Methods:
__init__(slot_count, *[, compatibility_keys])release(reservation)Release exactly the reservation returned by
reserve().reservation_for(slot_id)Inspect a row without exposing mutable pool state.
reserve(candidate_id, compatibility_key)Reserve the first free row compatible with
compatibility_key.Attributes:
Return the number of currently unreserved compatible rows.
Return the number of physical slots.
- property available_count: int#
Return the number of currently unreserved compatible rows.
- property capacity: int#
Return the number of physical slots.
- release(reservation)[source]#
Release exactly the reservation returned by
reserve().- Return type:
None
- reservation_for(slot_id)[source]#
Inspect a row without exposing mutable pool state.
- Return type:
SlotReservation|None
- embodichain.lab.sim.motion.expansion.combined.enumerate_candidate_recipes(profile, *, job_id='repeated_pick_place_expansion', families=None)[source]#
Enumerate the deterministic
m × a × tepisode recipes.- Return type:
tuple[CandidateRecipe,...]
- embodichain.lab.sim.motion.expansion.combined.load_visual_profile_registry(path, *, requested_profile_ids=None)[source]#
Load and validate seedable visual profile IDs.
This compatibility helper exposes only IDs; full profile resolution uses the same canonical parser through
VisualProfileRegistry.- Return type:
tuple[str,...]
- embodichain.lab.sim.motion.expansion.combined.schedule_digest(recipes)[source]#
Hash the complete schedule in order for deterministic rerun checks.
- Return type:
str
Resolved visual operations for one physical episode. |
|
Load seedable visual profiles from a strict YAML file. |
|
One recipe reserved on one compatible physical slot. |
|
Bounded FIFO coordinator for recipe assignment and slot cleanup. |
|
Fail-closed validator for measured episode and three-cycle evidence. |
|
Return recipes in family round-robin order with FIFO within each family. |
- class embodichain.lab.sim.motion.expansion.combined_runtime.VisualProfileApplication[source]#
Resolved visual operations for one physical episode.
Methods:
__init__(profile_id, revision, seed, operations)- __init__(profile_id, revision, seed, operations, status='resolved')#
- class embodichain.lab.sim.motion.expansion.combined_runtime.VisualProfileRegistry[source]#
Load seedable visual profiles from a strict YAML file.
Methods:
__init__(profile_id, revision, profiles)apply_to_environment(env, assignments, *, seed)Apply visual operations through existing functors.
from_yaml(path)Load one closed visual registry without importing executable values.
resolve(profile_id, *, seed)Resolve one profile and derive its deterministic episode seed.
Attributes:
Return registered profile IDs in file order.
- apply_to_environment(env, assignments, *, seed)[source]#
Apply visual operations through existing functors.
The method intentionally accepts a narrow structural environment port rather than importing Gym types. A
global_sunoperation is applied once tomain_light; multiple declared global operations must agree, and per-environment operations are then applied to selected rows.- Return type:
tuple[VisualProfileApplication,...]
- classmethod from_yaml(path)[source]#
Load one closed visual registry without importing executable values.
- Return type:
- property profile_ids: tuple[str, ...]#
Return registered profile IDs in file order.
- class embodichain.lab.sim.motion.expansion.combined_runtime.CombinedAssignment[source]#
One recipe reserved on one compatible physical slot.
Methods:
__init__(recipe, reservation, compatibility_key)- __init__(recipe, reservation, compatibility_key)#
- class embodichain.lab.sim.motion.expansion.combined_runtime.CombinedEpisodeCoordinator[source]#
Bounded FIFO coordinator for recipe assignment and slot cleanup.
Methods:
__init__(recipes, *, slot_pool, ...)Reserve the next recipe, or return
Noneon capacity/cancellation.cancel()Stop new work and release every active reservation safely.
finish(assignment, *, status)Release an active assignment and count its terminal status.
snapshot()Return immutable scheduler counters and queue state.
Attributes:
Return recipes currently holding a physical slot.
Return recipes waiting for assignment.
- acquire_next()[source]#
Reserve the next recipe, or return
Noneon capacity/cancellation.- Return type:
CombinedAssignment|None
- property active_count: int#
Return recipes currently holding a physical slot.
- finish(assignment, *, status)[source]#
Release an active assignment and count its terminal status.
- Return type:
None
- property pending_count: int#
Return recipes waiting for assignment.
- class embodichain.lab.sim.motion.expansion.combined_runtime.MeasuredValidator[source]#
Fail-closed validator for measured episode and three-cycle evidence.
Methods:
validate(episode, *[, cycle_count])Return required checks from finite aligned evidence and cycle metadata.
validate_demo_result(result, *[, cycle_count])Validate the measured Gym demo boundary before dataset commit.
- validate(episode, *, cycle_count=3)[source]#
Return required checks from finite aligned evidence and cycle metadata.
- Return type:
- validate_demo_result(result, *, cycle_count=3)[source]#
Validate the measured Gym demo boundary before dataset commit.
Environment integrations can add object pose and contact checks to the result metadata. This base gate always requires completed rows and the expected number of successful Task Program segments.
- Return type:
- embodichain.lab.sim.motion.expansion.combined_runtime.round_robin_recipes(recipes, *, family_count)[source]#
Return recipes in family round-robin order with FIFO within each family.
- Return type:
tuple[CandidateRecipe,...]