Karana.KUtils.kdpy_loops

Contents

Karana.KUtils.kdpy_loops#

Analyze, report, and safely edit kdFlex closed-loop mobility.

The module follows a staged workflow: discover coupled loop groups, inspect their constraint Jacobians, explore connected closure-feasible motion, classify coordinate participation, and only then apply an explicitly requested edit. Read-only analysis and serialized-model mutation have separate class APIs.

Attributes#

Exceptions#

LockedLoopError

Indicate that a loop coordinate cannot be retained as independent.

ZeroLocalMobilityError

Indicate that a coordinate is zero in every local nullspace vector.

IndirectCoordinateChartError

Indicate that scalar Q continuation cannot represent one velocity DOF.

FrozenLoopCoordinateError

Indicate that a loop coordinate was frozen before range exploration.

RangeLimitComputationError

Indicate that numerical closure did not establish a range limit.

Classes#

MobilityRequest

Define the target nullity and admissible drivers for one loop group.

LoopGroup

Identify constraint rows and velocity columns coupled into one loop.

MobilityCandidate

Describe one canonical cut-joint coordinate considered for insertion.

MobilityChange

Summarize an accepted connected-loop mobility augmentation.

GeometryChange

Summarize one accepted or rejected weak-mode axis reconciliation.

SerializedSubhingeRef

Locate one serialized subhinge and the object that owns its hinge.

FeasibleRangeLimit

Record one connected feasible interval and its evidence quality.

CoordinateMobilityEvidence

Summarize range-wide evidence for one candidate inert DOF.

BallReductionHint

Describe a BALL coordinate's local active rotational subspace.

LoopMobilityStatus

Provide one presentation-ready loop-coordinate classification record.

LoopAnalyzer

Provide reusable analysis services for one live closed-loop graph.

LoopModelEditor

Apply validated topology and geometry changes to one serialized model.

Functions#

mobilityRequests(→ tuple[MobilityRequest, Ellipsis])

Validate and merge repeatable four-field DOF requests by loop anchor.

normalizedLoopOptions(→ dict[str, Any])

Return concrete loop defaults in place of Kclick omission sentinels.

mobilityCheckSelections(→ tuple[tuple[str, int], ...)

Parse repeatable SUBHINGE[/OFFSET] mobility-check selectors.

discoverLoopGroups(→ tuple[LoopGroup, Ellipsis])

Discover connected cut-joint groups through shared active coordinates.

optimizeLoopGeometry(→ GeometryChange | None)

Remove weak nonzero modes using bounded finite-motion axis corrections.

recommendMobilityAdditions(→ MobilityChange)

Select the smallest well-conditioned coordinate set meeting a request.

synchronizeSerializedRangeLimits(→ None)

Copy live Q-coordinate range limits into a retained BasicPrefab specification.

loadSimplifiedModel(...)

Apply validated hinge reductions and load the rebuilt root model.

loadTransformedModel(...)

Optimize geometry, add requested DOFs, and load a rebuilt SubGraph.

feasibleRangeLimit(→ FeasibleRangeLimit)

Find the connected projected feasible interval around one subhinge DOF.

updateSubhingeRangeLimits(→ bool)

Measure and store one physical-subhinge coordinate's feasible range.

updateRangeLimits(→ None)

Update feasible ranges for physical coordinates in a subgraph.

updateLoopRangeLimits() → None)

Find, apply, and report Q ranges for loop-active physical subhinges.

checkRangeLimits(→ tuple[tuple[FeasibleRangeLimit, ...)

Check feasible ranges without applying them to the multibody.

detectInertDofs(→ tuple[CoordinateMobilityEvidence, ...)

Update ranges and return physical coordinates with finite zero spans.

findReducibleBallJoints(→ tuple[BallReductionHint, ...)

Return BALL joints whose local rotational subspace merits reduction.

mobilityCheck(...)

Update ranges and combine inertness, BALL hints, and status records.

loopMobilityInfo(→ str)

Update ranges and return a Markdown loop-coordinate mobility report.

writeLoopMobilityInfo(→ None)

Write a loop-mobility Markdown report to a file or standard output.

loopStoredRangesInfo(→ str)

Return stored range limits for every physical subhinge Q coordinate.

writeLoopStoredRangesInfo(→ None)

Write the stored Q-coordinate range inventory to a destination.

Module Contents#

Karana.KUtils.kdpy_loops.INERT_SUBHINGE_TOLERANCE = 2e-07#
class Karana.KUtils.kdpy_loops.MobilityRequest[source]#

Define the target nullity and admissible drivers for one loop group.

anchor: str#
target_mobility: int#
drivers: tuple[str, Ellipsis]#
allowed_components: tuple[str, Ellipsis]#
class Karana.KUtils.kdpy_loops.LoopGroup[source]#

Identify constraint rows and velocity columns coupled into one loop.

constraints: tuple[str, Ellipsis]#
rows: tuple[int, Ellipsis]#
columns: tuple[int, Ellipsis]#
coordinate_ids: tuple[int, Ellipsis]#
coordinate_names: tuple[str, Ellipsis]#
class Karana.KUtils.kdpy_loops.MobilityCandidate[source]#

Describe one canonical cut-joint coordinate considered for insertion.

constraint: str#
component: str#
subhinge_type: str#
axis: tuple[float, float, float]#
column: tuple[float, Ellipsis]#
class Karana.KUtils.kdpy_loops.MobilityChange[source]#

Summarize an accepted connected-loop mobility augmentation.

anchor: str#
constraints: tuple[str, Ellipsis]#
before_rank: int#
before_nullity: int#
target_mobility: int#
additions: tuple[MobilityCandidate, Ellipsis]#
predicted_rank: int#
predicted_nullity: int#
before_smallest_singular: float#
predicted_smallest_singular: float#
class Karana.KUtils.kdpy_loops.GeometryChange[source]#

Summarize one accepted or rejected weak-mode axis reconciliation.

constraints: tuple[str, Ellipsis]#
accepted: bool#
before_rank: int#
after_rank: int#
before_nullity: int#
after_nullity: int#
before_weak_singular: float#
after_weak_singular: float#
axis_changes: tuple[tuple[str, float], Ellipsis]#
validation_spans: tuple[tuple[str, float, float, str], Ellipsis] = ()#
rejection_reason: str | None = None#
Karana.KUtils.kdpy_loops.mobilityRequests(loop_options: dict[str, Any] | None) → tuple[MobilityRequest, Ellipsis][source]#

Validate and merge repeatable four-field DOF requests by loop anchor.

Kclick returns one record per --add-dofs occurrence. Multiple records may contribute drivers to the same loop, but target mobility and allowed component families must agree. The result is canonical input for the Jacobian-based recommendation phase.

Karana.KUtils.kdpy_loops.normalizedLoopOptions(options: dict[str, Any]) → dict[str, Any][source]#

Return concrete loop defaults in place of Kclick omission sentinels.

Kclick distinguishes an uninvoked chained command from one whose options hold ordinary false or empty values. Downstream loop code consumes stable Python values and does not depend on sentinel identity.

Karana.KUtils.kdpy_loops.mobilityCheckSelections(values: tuple[str, Ellipsis]) → tuple[tuple[str, int], Ellipsis] | None[source]#

Parse repeatable SUBHINGE[/OFFSET] mobility-check selectors.

None represents the special all-coordinate selection. A missing suffix selects offset zero, while an explicit suffix must be a nonnegative integer.

Karana.KUtils.kdpy_loops.discoverLoopGroups(subgraph: Karana.Dynamics.SubGraph, *, activity_tolerance: float = 1e-10) → tuple[LoopGroup, Ellipsis][source]#

Discover connected cut-joint groups through shared active coordinates.

Two constraints belong to the same group when their Jacobian rows touch a common active coordinate, including transitive connections. Grouping first prevents kdpy from making an invalid independent decision for each cut joint when several closures are algebraically coupled.

Karana.KUtils.kdpy_loops.optimizeLoopGeometry(subgraph: Karana.Dynamics.SubGraph, group: LoopGroup, *, weak_relative_tolerance: float = 0.001, exact_relative_tolerance: float = 1e-09, maximum_axis_parameter: float = 0.001) → GeometryChange | None[source]#

Remove weak nonzero modes using bounded finite-motion axis corrections.

Small nonzero singular values often indicate nominally aligned hinge axes that differ by modeling noise. Candidate axes are adjusted only within the configured bound and evaluated at predictor poses along the weak modes. A change is accepted only when the corrected mechanism then closes through a finite two-sided range and retains the intended rank there; otherwise the original geometry is restored.

Karana.KUtils.kdpy_loops.recommendMobilityAdditions(subgraph: Karana.Dynamics.SubGraph, group: LoopGroup, request: MobilityRequest, states: tuple[numpy.ndarray, Ellipsis]) → MobilityChange[source]#

Select the smallest well-conditioned coordinate set meeting a request.

Candidate combinations are evaluated against every retained closed state. A valid result reaches the requested nullity, preserves independent driver projections, and avoids weaker singular modes than same-size alternatives.

class Karana.KUtils.kdpy_loops.SerializedSubhingeRef[source]#

Locate one serialized subhinge and the object that owns its hinge.

name: str#
owner: Any#
owner_attribute: str#
subhinge_index: int#
Karana.KUtils.kdpy_loops.synchronizeSerializedRangeLimits(subgraph: Karana.Dynamics.SubGraph, model_target: Any) → None[source]#

Copy live Q-coordinate range limits into a retained BasicPrefab specification.

SubGraph outputs serialize their live object directly. BasicPrefab loading, however, retains the input DataStruct so that its wrapper, assets, and model metadata survive output. Range analysis changes the instantiated Multibody, so this synchronization step transfers each coordinate result back to the matching serialized subhinge immediately before --to-model.

Karana.KUtils.kdpy_loops.loadSimplifiedModel(model_file: pathlib.Path, remove_inert: tuple[str, Ellipsis], reduce_ball: tuple[str, Ellipsis], reduce_spherical: tuple[str, Ellipsis]) → tuple[Karana.KUtils.kdpy_model_io.LoadedModel, tuple[str, Ellipsis], tuple[str, Ellipsis]][source]#

Apply validated hinge reductions and load the rebuilt root model.

Karana.KUtils.kdpy_loops.loadTransformedModel(model_file: pathlib.Path, optimize_mobility: bool, requests: tuple[MobilityRequest, Ellipsis]) → tuple[Karana.KUtils.kdpy_model_io.LoadedModel, tuple[GeometryChange, Ellipsis], tuple[MobilityChange, Ellipsis]][source]#

Optimize geometry, add requested DOFs, and load a rebuilt SubGraph.

class Karana.KUtils.kdpy_loops.FeasibleRangeLimit[source]#

Record one connected feasible interval and its evidence quality.

Limit flags distinguish a closure boundary from a configured search bound. worst_feasible_residual records the largest accepted pose error, while range_limits_supported states whether native limits can store the result.

coordinate: str#
current: float#
lower: float#
upper: float#
lower_limited: bool#
upper_limited: bool#
worst_feasible_residual: float#
old_limits: tuple[float, float] | None = None#
dof_index: int = 0#
range_limits_supported: bool = True#
class Karana.KUtils.kdpy_loops.CoordinateMobilityEvidence[source]#

Summarize range-wide evidence for one candidate inert DOF.

Global inertness requires complete connected-range coverage and acceptable participation and displacement at every retained closed state.

coordinate: str#
dof_index: int#
classification: str#
sampled_states: int#
max_participation: float#
max_displacement: float#
complete_connected_range: bool#
class Karana.KUtils.kdpy_loops.BallReductionHint[source]#

Describe a BALL coordinate’s local active rotational subspace.

The axes are candidates for fixed-axis gimbal validation, not proof that a rotational component can be removed.

coordinate: str#
participation_rank: int#
coordinate_dofs: int#
axes: tuple[tuple[float, float, float], Ellipsis]#
class Karana.KUtils.kdpy_loops.LoopMobilityStatus[source]#

Provide one presentation-ready loop-coordinate classification record.

coordinate: str#
coordinate_type: str#
dof_index: int#
mobility: str#
feasible_range: tuple[float, float] | None#
details: str#
exception Karana.KUtils.kdpy_loops.LockedLoopError[source]#

Bases: ValueError

Indicate that a loop coordinate cannot be retained as independent.

exception Karana.KUtils.kdpy_loops.ZeroLocalMobilityError[source]#

Bases: LockedLoopError

Indicate that a coordinate is zero in every local nullspace vector.

exception Karana.KUtils.kdpy_loops.IndirectCoordinateChartError[source]#

Bases: LockedLoopError

Indicate that scalar Q continuation cannot represent one velocity DOF.

exception Karana.KUtils.kdpy_loops.FrozenLoopCoordinateError[source]#

Bases: ValueError

Indicate that a loop coordinate was frozen before range exploration.

exception Karana.KUtils.kdpy_loops.RangeLimitComputationError[source]#

Bases: RuntimeError

Indicate that numerical closure did not establish a range limit.

Karana.KUtils.kdpy_loops.feasibleRangeLimit(subgraph: Karana.Dynamics.SubGraph, subhinge: Karana.Dynamics.PhysicalSubhinge, *, dof_index: int = 0, initial_step: float | None = None, maximum_step: float | None = None, maximum_distance: float | None = None, closure_tolerance: float = 1e-09, rank_tolerance: float = 1e-09, boundary_tolerance: float = 1e-07, sample_callback: Callable[[numpy.ndarray], None] | None = None) → FeasibleRangeLimit[source]#

Find the connected projected feasible interval around one subhinge DOF.

For every tested value of the selected coordinate, all remaining direct position coordinates are optimization variables. Consequently the test answers exists q_other: C(q) = 0 and does not impose the artificial path or frozen-coordinate partition used by the older continuation scan. Scanning stops at the first infeasible value in each direction, retaining only the connected interval containing the initial configuration.

Karana.KUtils.kdpy_loops.updateSubhingeRangeLimits(subgraph: Karana.Dynamics.SubGraph, subhinge: Karana.Dynamics.PhysicalSubhinge, coordinate_offset: int) → bool[source]#

Measure and store one physical-subhinge coordinate’s feasible range.

Finite values denote established feasibility boundaries, infinities denote open search directions, and NaNs denote a failed numerical measurement. Frozen coordinates and unsupported indirect charts are left unchanged.

Parameters:
  • subgraph (kd.SubGraph) – Graph supplying closure constraints and its CK solver.

  • subhinge (kd.PhysicalSubhinge) – Physical subhinge whose range-limit row is updated.

  • coordinate_offset (int) – Local Q row to measure and store.

Returns:

True when the stored endpoint pair changed; otherwise False.

Return type:

bool

Karana.KUtils.kdpy_loops.updateRangeLimits(subgraph: Karana.Dynamics.SubGraph, selected_dofs: tuple[tuple[str, int], Ellipsis] | None = None) → None[source]#

Update feasible ranges for physical coordinates in a subgraph.

When selected_dofs is supplied, only the named coordinate offsets are processed. Otherwise every physical hinge and cut-joint coordinate in the graph is updated once.

Parameters:
  • subgraph (kd.SubGraph) – Graph whose physical-subhinge range metadata is updated.

  • selected_dofs (tuple[tuple[str, int], ...] | None) – Optional coordinate-name and local-offset pairs. None updates every physical coordinate in the graph.

Karana.KUtils.kdpy_loops.updateLoopRangeLimits(subgraph: Karana.Dynamics.SubGraph, selected_names: tuple[str, Ellipsis] = ('all',)) → None[source]#

Find, apply, and report Q ranges for loop-active physical subhinges.

Parameters:
  • subgraph (kd.SubGraph) – Graph whose physical range metadata is updated.

  • selected_names (tuple[str, ...]) – Requested subhinge names, or ("all",). Defaults to ("all",).

Karana.KUtils.kdpy_loops.checkRangeLimits(multibody: Karana.Dynamics.SubGraph, selected_dofs: tuple[tuple[str, int], Ellipsis] | None = None, *, report_progress: bool = False, _analysis: _MobilityAnalysisResult | None = None) → tuple[tuple[FeasibleRangeLimit, Ellipsis], tuple[LoopMobilityStatus, Ellipsis]][source]#

Check feasible ranges without applying them to the multibody.

multibody is first so this operation can move to SubGraph without changing its user-facing arguments. The returned statuses include unresolved or immobile coordinates for which no interval was measured.

Parameters:
  • multibody (kd.SubGraph) – SubGraph-compatible multibody to analyze.

  • selected_dofs (tuple[tuple[str, int], ...] | None) – Optional coordinate-name and local-offset selections.

  • report_progress (bool) – Whether to emit continuation progress. Defaults to False.

  • _analysis (_MobilityAnalysisResult | None) – Optional shared internal result supplied by mobilityCheck.

Returns:

The completed range measurements and report-ready coordinate statuses.

Return type:

tuple[tuple[FeasibleRangeLimit, …], tuple[LoopMobilityStatus, …]]

Karana.KUtils.kdpy_loops.detectInertDofs(multibody: Karana.Dynamics.SubGraph, selected_dofs: tuple[tuple[str, int], Ellipsis] | None = None, *, tolerance: float = 2e-07, update_ranges: bool = True) → tuple[CoordinateMobilityEvidence, Ellipsis][source]#

Update ranges and return physical coordinates with finite zero spans.

Only two finite endpoints can establish inertness. Open intervals and failed measurements therefore remain non-inert without auxiliary flags.

Parameters:
  • multibody (kd.SubGraph) – SubGraph-compatible multibody whose ranges are inspected.

  • selected_dofs (tuple[tuple[str, int], ...] | None) – Optional coordinate-name and local-offset selections.

  • tolerance (float) – Largest finite interval width classified as inert. Defaults to 2.0e-7.

  • update_ranges (bool) – Whether to recompute stored ranges before classification. Defaults to True.

Returns:

Deterministically ordered evidence for coordinates classified inert.

Return type:

tuple[CoordinateMobilityEvidence, …]

Karana.KUtils.kdpy_loops.findReducibleBallJoints(multibody: Karana.Dynamics.SubGraph, selected_dofs: tuple[tuple[str, int], Ellipsis] | None = None, *, report_progress: bool = False, _analysis: _MobilityAnalysisResult | None = None) → tuple[BallReductionHint, Ellipsis][source]#

Return BALL joints whose local rotational subspace merits reduction.

Results are candidates rather than topology edits; range-wide fixed-axis validation remains required before a BALL is replaced. This separation keeps a future SubGraph method non-mutating and independently usable.

Parameters:
  • multibody (kd.SubGraph) – SubGraph-compatible multibody to analyze.

  • selected_dofs (tuple[tuple[str, int], ...] | None) – Optional coordinate-name and local-offset selections.

  • report_progress (bool) – Whether to emit continuation progress. Defaults to False.

  • _analysis (_MobilityAnalysisResult | None) – Optional shared internal result supplied by mobilityCheck.

Returns:

Advisory spherical-joint reduction candidates.

Return type:

tuple[BallReductionHint, …]

Karana.KUtils.kdpy_loops.mobilityCheck(multibody: Karana.Dynamics.SubGraph, selected_dofs: tuple[tuple[str, int], Ellipsis] | None = None, *, report_progress: bool = False) → tuple[tuple[CoordinateMobilityEvidence, Ellipsis], tuple[BallReductionHint, Ellipsis], tuple[LoopMobilityStatus, Ellipsis]][source]#

Update ranges and combine inertness, BALL hints, and status records.

Parameters:
  • multibody (kd.SubGraph) – SubGraph-compatible multibody to analyze.

  • selected_dofs (tuple[tuple[str, int], ...] | None) – Optional coordinate-name and local-offset selections.

  • report_progress (bool) – Whether to emit continuation progress. Defaults to False.

Returns:

  • tuple[ – tuple[CoordinateMobilityEvidence, …], tuple[BallReductionHint, …], tuple[LoopMobilityStatus, …],

  • ] – Inert-coordinate evidence, spherical reduction hints, and report-ready coordinate statuses.

Karana.KUtils.kdpy_loops.loopMobilityInfo(subgraph: Karana.Dynamics.SubGraph, source: pathlib.Path, selected_dofs: tuple[tuple[str, int], Ellipsis] | None = None, *, report_progress: bool = False) → str[source]#

Update ranges and return a Markdown loop-coordinate mobility report.

The report combines continuation status, feasible spans, and advisory BALL hints without editing topology. Optional selections restrict projection work while retaining the same report schema.

Parameters:
  • subgraph (kd.SubGraph) – Graph to analyze and update.

  • source (Path) – Source-model path displayed in the report.

  • selected_dofs (tuple[tuple[str, int], ...] | None) – Optional coordinate-name and local-offset selections.

  • report_progress (bool) – Whether to emit continuation progress. Defaults to False.

Returns:

Markdown mobility report text.

Return type:

str

Karana.KUtils.kdpy_loops.writeLoopMobilityInfo(subgraph: Karana.Dynamics.SubGraph, source: pathlib.Path, destination: str, selected_dofs: tuple[tuple[str, int], Ellipsis] | None = None) → None[source]#

Write a loop-mobility Markdown report to a file or standard output.

Parameters:
  • subgraph (kd.SubGraph) – Graph to analyze and update.

  • source (Path) – Source-model path displayed in the report.

  • destination (str) – Output filename, or - for standard output.

  • selected_dofs (tuple[tuple[str, int], ...] | None) – Optional coordinate-name and local-offset selections.

Karana.KUtils.kdpy_loops.loopStoredRangesInfo(subgraph: Karana.Dynamics.SubGraph, source: pathlib.Path) → str[source]#

Return stored range limits for every physical subhinge Q coordinate.

This inventory performs no closure solve and does not infer feasibility. It reports exactly what the currently loaded model stores, making it suitable for quickly checking the result of loops --ranges-update.

Parameters:
  • subgraph (kd.SubGraph) – Graph whose stored physical-subhinge limits are inventoried.

  • source (Path) – Source-model path displayed in the report.

Returns:

Markdown inventory of stored range-limit rows.

Return type:

str

Karana.KUtils.kdpy_loops.writeLoopStoredRangesInfo(subgraph: Karana.Dynamics.SubGraph, source: pathlib.Path, destination: str) → None[source]#

Write the stored Q-coordinate range inventory to a destination.

Parameters:
  • subgraph (kd.SubGraph) – Graph whose stored ranges are inventoried.

  • source (Path) – Source-model path displayed in the report.

  • destination (str) – Output filename, or - for standard output.

class Karana.KUtils.kdpy_loops.LoopAnalyzer(subgraph: Karana.Dynamics.SubGraph)[source]#

Provide reusable analysis services for one live closed-loop graph.

The class owns no native object and caches no configuration. Each operation delegates to the functional analysis pipeline, which restores the caller-visible graph state after its temporary continuation solves.

subgraph#
scan(selected_names: tuple[str, Ellipsis] = ('all',)) → tuple[tuple[FeasibleRangeLimit, Ellipsis], tuple[CoordinateMobilityEvidence, Ellipsis], tuple[BallReductionHint, Ellipsis], tuple[LoopMobilityStatus, Ellipsis]][source]#

Return ranges, inertness evidence, BALL hints, and status records.

scan selects the non-mutating pipeline used by advisory tooling. The four result collections are kept separate so callers can choose their own presentation without parsing Markdown output.

Parameters:

selected_names (tuple[str, ...]) – Requested subhinge names, or ("all",). Defaults to ("all",).

Returns:

  • tuple[ – tuple[FeasibleRangeLimit, …], tuple[CoordinateMobilityEvidence, …], tuple[BallReductionHint, …], tuple[LoopMobilityStatus, …],

  • ] – Range measurements, inertness evidence, spherical reduction hints, and report-ready statuses.

updateRanges(selected_names: tuple[str, Ellipsis] = ('all',)) → None[source]#

Measure, report, and store Q range limits on the bound graph.

Parameters:

selected_names (tuple[str, ...]) – Requested subhinge names, or ("all",). Defaults to ("all",).

writeMobilityCheck(source: pathlib.Path, destination: str, selected_dofs: tuple[tuple[str, int], Ellipsis] | None) → None[source]#

Update ranges and write the resulting mobility-analysis report.

Parameters:
  • source (Path) – Source-model path displayed in the report.

  • destination (str) – Output filename, or - for standard output.

  • selected_dofs (tuple[tuple[str, int], ...] | None) – Optional coordinate-name and offset selections.

writeRangesInfo(source: pathlib.Path, destination: str) → None[source]#

Write stored Q-coordinate ranges without running analysis.

Parameters:
  • source (Path) – Source-model path displayed in the report.

  • destination (str) – Output filename, or - for standard output.

class Karana.KUtils.kdpy_loops.LoopModelEditor(model_file: pathlib.Path)[source]#

Apply validated topology and geometry changes to one serialized model.

Keeping mutation behind this class makes launcher control flow explicit and prevents report-only operations from accidentally selecting an editing path. Calls reload model_file and return a live model plus an audit summary of accepted changes.

model_file#
simplify(remove_inert: tuple[str, Ellipsis], reduce_ball: tuple[str, Ellipsis], reduce_spherical: tuple[str, Ellipsis]) → tuple[Karana.KUtils.kdpy_model_io.LoadedModel, tuple[str, Ellipsis], tuple[str, Ellipsis]][source]#

Remove proven inert coordinates and reduce validated spherical hinges.

Parameters:
  • remove_inert (tuple[str, ...]) – Requested scalar subhinge names to remove.

  • reduce_ball (tuple[str, ...]) – Requested spherical subhinge names to reduce.

  • reduce_spherical (tuple[str, ...]) – Requested spherical subhinge names to reduce in any parent hinge.

Returns:

Reloaded model, applied geometry changes, and mobility changes.

Return type:

tuple[LoadedModel, tuple[str, …], tuple[str, …]]

transform(optimize_mobility: bool, requests: tuple[MobilityRequest, Ellipsis]) → tuple[Karana.KUtils.kdpy_model_io.LoadedModel, tuple[GeometryChange, Ellipsis], tuple[MobilityChange, Ellipsis]][source]#

Optimize loop geometry and apply requested mobility additions.

Parameters:
  • optimize_mobility (bool) – Whether to optimize loop-frame geometry first.

  • requests (tuple[MobilityRequest, ...]) – Explicit mobility additions to apply.

Returns:

Reloaded model, accepted geometry changes, and accepted mobility changes.

Return type:

tuple[LoadedModel, tuple[GeometryChange, …], tuple[MobilityChange, …]]