embodichain.lab.sim.motion.workspace.visualizers

Contents

embodichain.lab.sim.motion.workspace.visualizers#

Workspace result visualizers deriving from BaseVisualizer.

Built-in visualizers: point-cloud, voxel, sphere, axis, and manipulability, plus a VisualizerFactory and create_visualizer helper.

The manipulability path additionally exports its pure mapping helpers (align_manipulability_scores(), normalize_manipulability(), map_manipulability_colors(), select_inspection_indices(), inspect_points(), translational_manipulability_ellipsoid()) so score mapping can be reused and tested without a renderer.

Classes:

AxisVisualizer

Visualizer for coordinate axes/frames at specified poses.

BaseVisualizer

Abstract base class for all visualizers.

IVisualizer

Interface for all visualizers.

InspectionSelection

Indices chosen for detailed (ellipsoid) inspection.

ManipulabilityColorCfg

Colors and normalization for manipulability visualization.

ManipulabilityColorMapping

Colors, sizes and normalization metadata for a point set.

ManipulabilityNormalization

Outcome of robust manipulability normalization.

ManipulabilityPointSet

Per-point scores aligned with the points of an analysis result.

ManipulabilityVisualizer

Render workspace points colored by manipulability.

PointCloudVisualizer

Point cloud visualizer using SimulationManager, Viser, or local tools.

PointInspection

Detail record for a single inspected workspace point.

SphereVisualizer

Sphere-based visualizer using Open3D or matplotlib.

VisualizationType

VisualizerFactory

Factory class for creating visualizers (Singleton pattern).

VoxelVisualizer

Voxel grid visualizer using Open3D or matplotlib.

Functions:

align_manipulability_scores(results[, ...])

Align a manipulability score vector with the points of an analysis result.

create_visualizer([viz_type])

Convenience function to create a visualizer.

ellipsoid_surface(radii, axes[, center, ...])

Tessellate one ellipsoid for surface plotting.

inspect_points(selection, *, points, scores)

Build detail records for the selected points only.

map_manipulability_colors(scores, *[, ...])

Map manipulability scores to RGBA colors and marker sizes.

normalize_manipulability(scores, *[, ...])

Normalize manipulability scores to [0, 1] with percentile clipping.

select_inspection_indices(scores, *[, ...])

Choose the few points that deserve a detailed inspection.

translational_manipulability_ellipsoid(jacobian)

Derive translational manipulability ellipsoids from spatial Jacobians.

class embodichain.lab.sim.motion.workspace.visualizers.AxisVisualizer[source]#

Bases: BaseVisualizer

Visualizer for coordinate axes/frames at specified poses.

This visualizer creates coordinate axes (X, Y, Z) at given transformation matrices, useful for visualizing robot end-effector poses, workspace reference frames, etc.

Supports multiple backends: - ‘sim_manager’: Uses SimulationManager.draw_marker() with MarkerCfg - ‘open3d’: Creates coordinate frames using Open3D - ‘matplotlib’: Draws axis lines in 3D matplotlib plot - ‘data’: Returns axis data without visualization

Methods:

__init__([backend, axis_length, axis_size, ...])

Initialize the axis visualizer.

get_type_name()

Return the type name for this visualizer.

visualize(poses[, colors])

Visualize coordinate axes at specified poses or points.

__init__(backend='sim_manager', axis_length=0.15, axis_size=0.005, config=None, sim_manager=None, control_part_name=None, reference_pose=None, arena_index=0)[source]#

Initialize the axis visualizer.

Parameters:
  • backend (str) – Visualization backend (‘sim_manager’, ‘open3d’, ‘matplotlib’, or ‘data’). Defaults to ‘sim_manager’.

  • axis_length (float) – Length of each axis. Defaults to 0.15.

  • axis_size (float) – Thickness/size of axes. Defaults to 0.005.

  • config (Optional[Dict[str, Any]]) – Optional configuration dictionary. Defaults to None.

  • sim_manager (Any | None) – SimulationManager instance for ‘sim_manager’ backend. Defaults to None.

  • control_part_name (str | None) – Control part name for naming (compatibility). Defaults to None.

  • reference_pose (Union[ndarray, Tensor, None]) – Reference pose (4x4 matrix) for orientation. Defaults to None.

  • arena_index (int) – Arena index for sim_manager markers. Defaults to 0.

get_type_name()[source]#

Return the type name for this visualizer.

Return type:

str

visualize(poses, colors=None, **kwargs)[source]#

Visualize coordinate axes at specified poses or points.

Parameters:
  • poses (Tensor | ndarray) – Either transformation matrices of shape (4, 4) or (N, 4, 4), or point coordinates of shape (N, 3) which will be converted to poses.

  • colors (Tensor | ndarray | None) – Optional colors (not used for axes but kept for interface compatibility).

  • **kwargs (Any) – Additional visualization parameters: - axis_length: Override default axis length - axis_size: Override default axis size - name_prefix: Prefix for axis names (default: “axis”) - arena_index: Arena index for sim_manager (default: 0)

Return type:

Any

Returns:

Backend-specific axis representation.

Examples

>>> import numpy as np
>>> visualizer = AxisVisualizer(backend='sim_manager', sim_manager=sim)
>>> # Using transformation matrix
>>> pose = np.eye(4)
>>> pose[:3, 3] = [1.0, 0.5, 1.2]  # Set position
>>> result = visualizer.visualize(pose)
>>>
>>> # Using point coordinates
>>> points = np.array([[1.0, 0.5, 1.2], [2.0, 1.0, 0.8]])
>>> result = visualizer.visualize(points)
>>> visualizer.show()
class embodichain.lab.sim.motion.workspace.visualizers.BaseVisualizer[source]#

Bases: ABC

Abstract base class for all visualizers.

This class provides common functionality and enforces the implementation of the visualization method in all derived classes.

backend#

Visualization backend (‘open3d’, ‘matplotlib’, etc.).

config#

Configuration dictionary for visualization parameters.

Methods:

__init__([backend, config])

Initialize the base visualizer.

clear()

Clear the current visualization.

from_config(config[, backend])

Create a visualizer instance from a VisualizationConfig.

get_type_name()

Get the name of the visualization type.

save(filepath, **kwargs)

Save the last visualization to file.

show(**kwargs)

Display the visualization interactively.

visualize(points[, colors])

Visualize the workspace data.

__init__(backend='open3d', config=None)[source]#

Initialize the base visualizer.

Parameters:
  • backend (str) – Visualization backend to use. Defaults to “open3d”.

  • config (Optional[Dict[str, Any]]) – Optional configuration dictionary. Defaults to None.

clear()[source]#

Clear the current visualization.

Return type:

None

classmethod from_config(config, backend='open3d')[source]#

Create a visualizer instance from a VisualizationConfig.

Parameters:
  • config (VisualizationConfig) – VisualizationConfig instance with visualization settings.

  • backend (str) – Visualization backend to use.

Returns:

Configured visualizer instance.

abstract get_type_name()[source]#

Get the name of the visualization type.

Return type:

str

Returns:

String identifier for the visualization type.

save(filepath, **kwargs)[source]#

Save the last visualization to file.

Parameters:
  • filepath (Union[str, Path]) – Path to save the visualization.

  • **kwargs (Any) – Additional save parameters.

Raises:

RuntimeError – If no visualization has been created yet.

Return type:

None

show(**kwargs)[source]#

Display the visualization interactively.

Parameters:

**kwargs (Any) – Backend-specific display parameters.

Raises:

RuntimeError – If no visualization has been created yet.

Return type:

None

abstract visualize(points, colors=None, **kwargs)[source]#

Visualize the workspace data.

This method must be implemented by all derived classes.

Parameters:
  • points (Tensor | ndarray) – Array of shape (N, 3) containing point positions.

  • colors (Tensor | ndarray | None) – Optional array of shape (N, 3) or (N, 4) containing colors.

  • **kwargs (Any) – Additional visualization parameters.

Return type:

Any

Returns:

Visualization object.

Raises:

NotImplementedError – If the method is not implemented in the derived class.

class embodichain.lab.sim.motion.workspace.visualizers.IVisualizer[source]#

Bases: Protocol

Interface for all visualizers.

This protocol defines the contract that all visualizers must follow.

Methods:

__init__(*args, **kwargs)

get_type_name()

Get the name of the visualization type.

save(filepath, **kwargs)

Save visualization to file.

visualize(points[, colors])

Visualize the workspace data.

__init__(*args, **kwargs)#
get_type_name()[source]#

Get the name of the visualization type.

Return type:

str

Returns:

String identifier for the visualization type.

save(filepath, **kwargs)[source]#

Save visualization to file.

Parameters:
  • filepath (Union[str, Path]) – Path to save the visualization.

  • **kwargs (Any) – Additional save parameters.

Return type:

None

visualize(points, colors=None, **kwargs)[source]#

Visualize the workspace data.

Parameters:
  • points (Tensor | ndarray) – Array of shape (N, 3) containing point positions.

  • colors (Tensor | ndarray | None) – Optional array of shape (N, 3) or (N, 4) containing colors.

  • **kwargs (Any) – Additional visualization parameters.

Return type:

Any

Returns:

Visualization object (e.g., Open3D geometry, matplotlib figure).

class embodichain.lab.sim.motion.workspace.visualizers.InspectionSelection[source]#

Bases: object

Indices chosen for detailed (ellipsoid) inspection.

indices#

Point indices, shape (K,); ordered explicit selection first, then descending-w picks, then ascending-w picks.

labels#

Per-index origin, one of "selected", "top", "bottom".

Methods:

__init__(indices, labels)

Attributes:

__init__(indices, labels)#
indices: ndarray#
labels: tuple[str, ...]#
class embodichain.lab.sim.motion.workspace.visualizers.ManipulabilityColorCfg[source]#

Bases: object

Colors and normalization for manipulability visualization.

Methods:

__init__([colormap, percentile_clip, ...])

copy(**kwargs)

Return a new object replacing specified fields with new values.

replace(**kwargs)

Return a new object replacing specified fields with new values.

to_dict()

Convert an object into dictionary recursively.

validate([prefix])

Check the validity of configclass object.

Attributes:

colormap

Matplotlib colormap name used for reachable points.

log_epsilon

Lower clamp applied before log10 so exact zeros stay finite.

log_scale

Normalize log10(w) instead of w.

percentile_clip

Lower/upper percentile used as color-scale bounds.

point_size

Marker size for reachable points.

reachable_alpha

Alpha applied to colormap output for reachable points.

unreachable_color

RGBA for unreachable points; deliberately desaturated and translucent.

unreachable_point_size

Marker size for unreachable points; smaller so they recede visually.

__init__(colormap=<factory>, percentile_clip=<factory>, log_scale=<factory>, log_epsilon=<factory>, unreachable_color=<factory>, reachable_alpha=<factory>, point_size=<factory>, unreachable_point_size=<factory>)#
colormap: str#

Matplotlib colormap name used for reachable points.

copy(**kwargs)#

Return a new object replacing specified fields with new values.

This is especially useful for frozen classes. Example usage:

@configclass(frozen=True)
class C:
    x: int
    y: int

c = C(1, 2)
c1 = c.replace(x=3)
assert c1.x == 3 and c1.y == 2
Parameters:
  • obj (object) – The object to replace.

  • **kwargs – The fields to replace and their new values.

Return type:

object

Returns:

The new object.

log_epsilon: float#

Lower clamp applied before log10 so exact zeros stay finite.

log_scale: bool#

Normalize log10(w) instead of w.

Manipulability spans orders of magnitude near singularities; the log scale keeps the interior of the workspace from saturating to a single color.

percentile_clip: tuple[float, float]#

Lower/upper percentile used as color-scale bounds.

Robust against the heavy tails of manipulability distributions: a handful of near-singular (w close to zero) or exceptionally well-conditioned points would otherwise flatten the whole color range. Use (0.0, 100.0) for a plain min/max scale.

point_size: float#

Marker size for reachable points.

reachable_alpha: float#

Alpha applied to colormap output for reachable points.

replace(**kwargs)#

Return a new object replacing specified fields with new values.

This is especially useful for frozen classes. Example usage:

@configclass(frozen=True)
class C:
    x: int
    y: int

c = C(1, 2)
c1 = c.replace(x=3)
assert c1.x == 3 and c1.y == 2
Parameters:
  • obj (object) – The object to replace.

  • **kwargs – The fields to replace and their new values.

Return type:

object

Returns:

The new object.

to_dict()#

Convert an object into dictionary recursively.

Note

Ignores all names starting with “__” (i.e. built-in methods).

Parameters:

obj (object) – An instance of a class to convert.

Raises:

ValueError – When input argument is not an object.

Return type:

dict[str, Any]

Returns:

Converted dictionary mapping.

unreachable_color: tuple[float, float, float, float]#

RGBA for unreachable points; deliberately desaturated and translucent.

unreachable_point_size: float#

Marker size for unreachable points; smaller so they recede visually.

validate(prefix='')#

Check the validity of configclass object.

This function checks if the object is a valid configclass object. A valid configclass object contains no MISSING entries.

Parameters:
  • obj (object) – The object to check.

  • prefix (str) – The prefix to add to the missing fields. Defaults to ‘’.

Return type:

list[str]

Returns:

A list of missing fields.

Raises:

TypeError – When the object is not a valid configuration object.

class embodichain.lab.sim.motion.workspace.visualizers.ManipulabilityColorMapping[source]#

Bases: object

Colors, sizes and normalization metadata for a point set.

colors#

RGBA colors, shape (N, 4).

sizes#

Marker sizes, shape (N,).

reachable_mask#

Boolean mask, shape (N,).

normalization#

The normalization that produced colors.

colormap#

Colormap name used for reachable points.

Methods:

__init__(colors, sizes, reachable_mask, ...)

Attributes:

clip_range

Color-scale bounds in raw units, forwarded from normalization.

colormap

colors

normalization

raw_range

Raw score range, forwarded from normalization.

reachable_mask

rgb

RGB view of colors, shape (N, 3).

sizes

__init__(colors, sizes, reachable_mask, normalization, colormap)#
property clip_range: tuple[float, float]#

Color-scale bounds in raw units, forwarded from normalization.

colormap: str#
colors: ndarray#
normalization: ManipulabilityNormalization#
property raw_range: tuple[float, float]#

Raw score range, forwarded from normalization.

reachable_mask: ndarray#
property rgb: ndarray#

RGB view of colors, shape (N, 3).

sizes: ndarray#
class embodichain.lab.sim.motion.workspace.visualizers.ManipulabilityNormalization[source]#

Bases: object

Outcome of robust manipulability normalization.

normalized#

Values in [0, 1], shape (N,); NaN for entries that carry no score.

raw_range#

(min, max) of the raw scores over valid entries, before any clipping or log transform. (nan, nan) when nothing is valid.

clip_range#

(low, high) color-scale bounds expressed in raw score units, i.e. the values that map to normalized 0 and 1.

log_scale#

Whether the normalization ran on log10(w).

num_valid#

Number of entries that contributed to the statistics.

num_clipped#

Number of valid entries that fell outside clip_range.

Methods:

__init__(normalized, raw_range, clip_range, ...)

Attributes:

__init__(normalized, raw_range, clip_range, log_scale, num_valid, num_clipped)#
clip_range: tuple[float, float]#
log_scale: bool#
normalized: ndarray#
num_clipped: int#
num_valid: int#
raw_range: tuple[float, float]#
class embodichain.lab.sim.motion.workspace.visualizers.ManipulabilityPointSet[source]#

Bases: object

Per-point scores aligned with the points of an analysis result.

points#

Point positions, shape (P, 3).

scores#

Per-point manipulability, shape (P,). NaN where the point is unreachable and therefore has no joint configuration.

reachable_mask#

Boolean mask, shape (P,).

score_indices#

Row of the raw score vector each point maps to, shape (P,); -1 for unreachable points. Use it to index joint_configurations.

joint_configurations#

Joint configurations of the scored points, shape (M, DOF) with M = reachable_mask.sum(), or None.

mode#

Analysis mode string the alignment was derived from.

Methods:

__init__(points, scores, reachable_mask, ...)

Attributes:

joint_configurations

mode

num_reachable

Number of reachable (scored) points.

num_unreachable

Number of points shown but not scored.

points

reachable_mask

score_indices

scores

__init__(points, scores, reachable_mask, score_indices, joint_configurations=None, mode='')#
joint_configurations: ndarray | None = None#
mode: str = ''#
property num_reachable: int#

Number of reachable (scored) points.

property num_unreachable: int#

Number of points shown but not scored.

points: ndarray#
reachable_mask: ndarray#
score_indices: ndarray#
scores: ndarray#
class embodichain.lab.sim.motion.workspace.visualizers.ManipulabilityVisualizer[source]#

Bases: BaseVisualizer

Render workspace points colored by manipulability.

The visualizer owns no numerics of its own: it calls map_manipulability_colors() and then either draws a Matplotlib figure with a visible color bar, forwards the colors to a point-cloud backend, or returns the mapping arrays.

color_cfg#

Color and normalization configuration.

sim_manager#

Simulation manager used by the forwarding backends.

control_part_name#

Control part name used to name forwarded point clouds.

scores#

Default score vector used when visualize is called without one, so generic callers such as WorkspaceAnalyzer.visualize can supply the scores at construction time.

reachable_mask#

Default reachability mask paired with scores.

Methods:

__init__([backend, color_cfg, config, ...])

Initialize the manipulability visualizer.

get_type_name()

Return the registered visualization type name.

map_colors(scores[, reachable_mask])

Map scores to colors using this visualizer's configuration.

visualize(points[, colors])

Visualize points colored by manipulability.

visualize_inspection(inspections, **kwargs)

Draw the detail view for inspected points.

__init__(backend='matplotlib', color_cfg=None, config=None, sim_manager=None, control_part_name=None, scores=None, reachable_mask=None)[source]#

Initialize the manipulability visualizer.

Parameters:
  • backend (str) – One of 'matplotlib', 'data', 'open3d', 'viser' or 'sim_manager'. Defaults to 'matplotlib' because the color bar is the point of this visualization.

  • color_cfg (ManipulabilityColorCfg | None) – Color and normalization configuration.

  • config (Optional[Dict[str, Any]]) – Optional generic visualizer configuration dictionary.

  • sim_manager (Any | None) – SimulationManager for the forwarding backends.

  • control_part_name (str | None) – Control part name used when forwarding.

  • scores (Tensor | ndarray | None) – Default per-point manipulability scores.

  • reachable_mask (Tensor | ndarray | None) – Default reachability mask for scores.

get_type_name()[source]#

Return the registered visualization type name.

Return type:

str

map_colors(scores, reachable_mask=None)[source]#

Map scores to colors using this visualizer’s configuration.

Parameters:
  • scores (Tensor | ndarray) – Per-point scores, shape (N,).

  • reachable_mask (ndarray | None) – Optional reachability mask, shape (N,).

Return type:

ManipulabilityColorMapping

Returns:

The ManipulabilityColorMapping.

visualize(points, colors=None, **kwargs)[source]#

Visualize points colored by manipulability.

Scores win over colors: this visualizer exists to color by manipulability, so a generic caller that also passes reachability colors (as WorkspaceAnalyzer.visualize does) still gets the manipulability mapping. colors is used only when no scores are available.

Parameters:
  • points (Tensor | ndarray) – Point positions, shape (N, 3).

  • colors (Tensor | ndarray | None) – Precomputed colors, used only as a fallback when no scores are available.

  • **kwargs (Any) –

    Additional parameters:

    • scores: per-point manipulability, shape (N,) or (M,) together with a (N,) reachable_mask selecting M points. Defaults to scores.

    • reachable_mask: boolean mask, shape (N,).

    • point_set: a ManipulabilityPointSet providing points/scores/reachable_mask in one object.

    • title: figure title (Matplotlib backend).

    • highlight: indices to mark with a cross (Matplotlib).

    • elev / azim: 3D view angles (Matplotlib).

Return type:

Any

Returns:

A Matplotlib figure, a backend-specific handle, or the mapping data dictionary for the data backend.

Raises:

ValueError – If no scores are supplied and no colors are given, or the backend is unsupported.

visualize_inspection(inspections, **kwargs)[source]#

Draw the detail view for inspected points.

Each inspected point gets a translational manipulability ellipsoid plus its w, condition number and joint configuration.

Parameters:
  • inspections (Sequence[PointInspection]) – Records from inspect_points().

  • **kwargs (Any) –

    Additional parameters:

    • title: figure title.

    • log_scale: annotate w on a log scale (cosmetic only).

    • elev / azim: 3D view angles.

Return type:

Any

Returns:

The Matplotlib figure.

Raises:

ValueError – If inspections is empty, or the backend cannot draw.

class embodichain.lab.sim.motion.workspace.visualizers.PointCloudVisualizer[source]#

Bases: BaseVisualizer

Point cloud visualizer using SimulationManager, Viser, or local tools.

point_size#

Size of points in visualization.

Methods:

__init__([backend, point_size, config, ...])

Initialize the point cloud visualizer.

get_type_name()

Get the name of the visualization type.

visualize(points[, colors])

Visualize points as a point cloud.

__init__(backend='sim_manager', point_size=2.0, config=None, sim_manager=None, control_part_name=None)[source]#

Initialize the point cloud visualizer.

Parameters:
  • backend (str) – Visualization backend (‘sim_manager’, ‘viser’, ‘open3d’, ‘matplotlib’, or ‘data’). Defaults to ‘sim_manager’. The ‘data’ backend returns raw data without visualization.

  • point_size (float) – Size of points in visualization. Defaults to 2.0.

  • config (Optional[Dict[str, Any]]) – Optional configuration dictionary. Defaults to None.

  • sim_manager (Any | None) – SimulationManager instance for the ‘sim_manager’ or ‘viser’ backend. Defaults to None.

  • control_part_name (str | None) – Control part name used to name the point cloud. Defaults to None.

get_type_name()[source]#

Get the name of the visualization type.

Return type:

str

Returns:

String identifier for the visualization type.

visualize(points, colors=None, **kwargs)[source]#

Visualize points as a point cloud.

Parameters:
  • points (Tensor | ndarray) – Array of shape (N, 3) containing point positions.

  • colors (Tensor | ndarray | None) – Optional array of shape (N, 3) or (N, 4) containing colors.

  • **kwargs (Any) – Additional visualization parameters: - point_size: Override default point size

Return type:

Any

Returns:

Backend-specific point-cloud handle, Viser overlay, geometry, or matplotlib figure.

Examples

>>> visualizer = PointCloudVisualizer()
>>> points = np.random.rand(1000, 3)
>>> colors = np.random.rand(1000, 3)
>>> pcd = visualizer.visualize(points, colors)
>>> visualizer.show()
class embodichain.lab.sim.motion.workspace.visualizers.PointInspection[source]#

Bases: object

Detail record for a single inspected workspace point.

index#

Index into the visualized point set.

label#

Selection origin ("selected", "top" or "bottom").

position#

Cartesian position, shape (3,).

manipulability#

Yoshikawa index w at this point.

condition_number#

Jacobian condition number, or None when not requested.

joint_configuration#

Joint configuration, shape (DOF,), or None.

ellipsoid_radii#

Translational ellipsoid semi-axis lengths in descending order, shape (3,), or None.

ellipsoid_axes#

Principal directions as columns, shape (3, 3), or None.

Methods:

__init__(index, label, position, manipulability)

summary_lines()

Render the inspection as human-readable lines.

Attributes:

__init__(index, label, position, manipulability, condition_number=None, joint_configuration=None, ellipsoid_radii=None, ellipsoid_axes=None)#
property anisotropy: float | None#

Ratio of longest to shortest ellipsoid semi-axis, or None.

condition_number: float | None = None#
ellipsoid_axes: ndarray | None = None#
ellipsoid_radii: ndarray | None = None#
index: int#
joint_configuration: ndarray | None = None#
label: str#
manipulability: float#
position: ndarray#
summary_lines()[source]#

Render the inspection as human-readable lines.

Return type:

list[str]

class embodichain.lab.sim.motion.workspace.visualizers.SphereVisualizer[source]#

Bases: BaseVisualizer

Sphere-based visualizer using Open3D or matplotlib.

sphere_radius#

Radius of each sphere.

sphere_resolution#

Resolution of sphere mesh (higher = smoother).

Methods:

__init__([backend, sphere_radius, ...])

Initialize the sphere visualizer.

get_type_name()

Get the name of the visualization type.

visualize(points[, colors])

Visualize points as spheres.

__init__(backend='sim_manager', sphere_radius=0.005, sphere_resolution=10, config=None, sim_manager=None, control_part_name=None)[source]#

Initialize the sphere visualizer.

Parameters:
  • backend (str) – Visualization backend (‘sim_manager’, ‘open3d’, ‘matplotlib’, or ‘data’). Defaults to ‘sim_manager’. ‘data’ backend returns sphere data without visualization.

  • sphere_radius (float) – Radius of each sphere. Defaults to 0.005.

  • sphere_resolution (int) – Sphere mesh resolution. Defaults to 10.

  • config (Optional[Dict[str, Any]]) – Optional configuration dictionary. Defaults to None.

  • sim_manager (Any | None) – SimulationManager instance for ‘sim_manager’ backend. Defaults to None.

  • control_part_name (str | None) – Control part name for naming. Defaults to None.

get_type_name()[source]#

Get the name of the visualization type.

Return type:

str

Returns:

String identifier for the visualization type.

visualize(points, colors=None, **kwargs)[source]#

Visualize points as spheres.

Parameters:
  • points (Tensor | ndarray) – Array of shape (N, 3) containing point positions.

  • colors (Tensor | ndarray | None) – Optional array of shape (N, 3) or (N, 4) containing colors.

  • **kwargs (Any) – Additional visualization parameters: - sphere_radius: Override default sphere radius - sphere_resolution: Override sphere resolution - max_spheres: Maximum number of spheres to render (for performance)

Return type:

Any

Returns:

Open3D TriangleMesh or matplotlib figure.

Examples

>>> visualizer = SphereVisualizer(sphere_radius=0.01)
>>> points = np.random.rand(100, 3)
>>> colors = np.random.rand(100, 3)
>>> mesh = visualizer.visualize(points, colors)
>>> visualizer.show()
class embodichain.lab.sim.motion.workspace.visualizers.VisualizationType[source]#

Bases: Enum

Attributes:

AXIS = 'axis'#
MANIPULABILITY = 'manipulability'#
POINT_CLOUD = 'point_cloud'#
SPHERE = 'sphere'#
VOXEL = 'voxel'#
class embodichain.lab.sim.motion.workspace.visualizers.VisualizerFactory[source]#

Bases: object

Factory class for creating visualizers (Singleton pattern).

This factory allows registration and creation of visualizers based on the visualization type. It uses the singleton pattern to ensure only one instance exists throughout the application.

The factory comes pre-registered with built-in visualizers:
  • POINT_CLOUD: PointCloudVisualizer

  • VOXEL: VoxelVisualizer

  • SPHERE: SphereVisualizer

Additional visualizers can be registered using register_visualizer().

Examples

>>> factory = VisualizerFactory()
>>> visualizer = factory.create_visualizer(
...     VisualizationType.POINT_CLOUD,
...     backend='open3d'
... )
>>> isinstance(visualizer, PointCloudVisualizer)
True
>>> # Register custom visualizer
>>> factory.register_visualizer("custom", CustomVisualizer)
>>> custom_viz = factory.create_visualizer("custom")

Methods:

__init__()

Initialize the factory with built-in visualizers.

__new__(cls)

Create or return the singleton instance.

create_visualizer([viz_type])

Create a visualizer instance based on the type.

is_registered(viz_type)

Check if a visualization type is registered.

list_available_types()

List all registered visualization types.

register_visualizer(name, visualizer_class)

Register a new visualizer class.

reset_instance()

Reset the singleton instance (mainly for testing).

__init__()[source]#

Initialize the factory with built-in visualizers.

This method only runs once due to the singleton pattern.

static __new__(cls)[source]#

Create or return the singleton instance.

Returns:

The singleton VisualizerFactory instance.

create_visualizer(viz_type=None, **kwargs)[source]#

Create a visualizer instance based on the type.

Parameters:
  • viz_type (VisualizationType | str | None) – The visualization type to use. Can be a VisualizationType enum or a string identifier. If None, defaults to POINT_CLOUD.

  • **kwargs (Any) – Additional keyword arguments to pass to the visualizer constructor. Common options include backend, voxel_size for VoxelVisualizer, sphere_radius for SphereVisualizer, and point_size for PointCloudVisualizer.

Return type:

BaseVisualizer

Returns:

An instance of the requested visualizer.

Raises:

ValueError – If the visualization type is not registered.

Examples

>>> factory = VisualizerFactory()
>>> viz = factory.create_visualizer(
...     VisualizationType.POINT_CLOUD,
...     backend='open3d'
... )
>>> viz = factory.create_visualizer("voxel", voxel_size=0.02)
>>> viz = factory.create_visualizer()  # Uses default (POINT_CLOUD)
is_registered(viz_type)[source]#

Check if a visualization type is registered.

Parameters:

viz_type (VisualizationType | str) – The visualization type to check.

Return type:

bool

Returns:

True if the type is registered, False otherwise.

list_available_types()[source]#

List all registered visualization types.

Return type:

list[str]

Returns:

List of registered type names.

register_visualizer(name, visualizer_class)[source]#

Register a new visualizer class.

Parameters:
  • name (str) – String identifier for the visualizer type.

  • visualizer_class (Type[BaseVisualizer]) – The visualizer class to register. Must inherit from BaseVisualizer.

Raises:

TypeError – If visualizer_class is not a subclass of BaseVisualizer.

Return type:

None

Examples

>>> factory = VisualizerFactory()
>>> factory.register_visualizer("my_viz", MyVisualizerClass)
classmethod reset_instance()[source]#

Reset the singleton instance (mainly for testing). :rtype: None

Warning

This should only be used in testing scenarios.

class embodichain.lab.sim.motion.workspace.visualizers.VoxelVisualizer[source]#

Bases: BaseVisualizer

Voxel grid visualizer using Open3D or matplotlib.

voxel_size#

Size of each voxel cube.

Methods:

__init__([backend, voxel_size, config, ...])

Initialize the voxel visualizer.

get_type_name()

Get the name of the visualization type.

visualize(points[, colors])

Visualize points as a voxel grid.

__init__(backend='sim_manager', voxel_size=0.01, config=None, sim_manager=None, control_part_name=None)[source]#

Initialize the voxel visualizer.

Parameters:
  • backend (str) – Visualization backend (‘sim_manager’, ‘open3d’, ‘matplotlib’, or ‘data’). Defaults to ‘sim_manager’. ‘data’ backend returns voxelized data without visualization.

  • voxel_size (float) – Size of each voxel. Defaults to 0.01.

  • config (Optional[Dict[str, Any]]) – Optional configuration dictionary. Defaults to None.

  • sim_manager (Any | None) – SimulationManager instance for ‘sim_manager’ backend. Defaults to None.

  • control_part_name (str | None) – Control part name for naming. Defaults to None.

get_type_name()[source]#

Get the name of the visualization type.

Return type:

str

Returns:

String identifier for the visualization type.

visualize(points, colors=None, **kwargs)[source]#

Visualize points as a voxel grid.

Parameters:
  • points (Tensor | ndarray) – Array of shape (N, 3) containing point positions.

  • colors (Tensor | ndarray | None) – Optional array of shape (N, 3) or (N, 4) containing colors.

  • **kwargs (Any) – Additional visualization parameters: - voxel_size: Override default voxel size

Return type:

Any

Returns:

Open3D VoxelGrid geometry or matplotlib figure.

Examples

>>> visualizer = VoxelVisualizer(voxel_size=0.02)
>>> points = np.random.rand(1000, 3)
>>> voxel_grid = visualizer.visualize(points)
>>> visualizer.show()
embodichain.lab.sim.motion.workspace.visualizers.align_manipulability_scores(results, scores=None, *, include_unreachable=True, verify_positions=True, position_atol=1e-05)[source]#

Align a manipulability score vector with the points of an analysis result.

WorkspaceAnalyzer computes one score per stored joint configuration, so the score at row i belongs to:

  • joint-space results: workspace_points[i] — every sampled point is reachable by construction;

  • Cartesian / plane results: reachable_points[i] — the joint configurations are the IK solutions collected in ascending sample order, so all_points[reachability_mask][i] == reachable_points[i].

When diagnostics were retained (all_points and reachability_mask present), the scores are scattered back onto the full sample set so unreachable points can be drawn alongside, with NaN scores. Otherwise only the reachable points are returned.

Parameters:
  • results (Dict[str, Any]) – Analysis dictionary returned by WorkspaceAnalyzer.analyze.

  • scores (Tensor | ndarray | None) – Score vector to align. Defaults to results["manipulability_scores"].

  • include_unreachable (bool) – Scatter scores onto all_points when the result retains them. When False, only reachable points are returned.

  • verify_positions (bool) – Cross-check that all_points[mask] equals reachable_points before scattering, so a silently reordered result is rejected instead of mis-colored.

  • position_atol (float) – Absolute tolerance for that cross-check.

Return type:

ManipulabilityPointSet

Returns:

The aligned ManipulabilityPointSet.

Raises:

ValueError – If no scores are available, if the result carries no points, or if any length / ordering invariant is violated.

embodichain.lab.sim.motion.workspace.visualizers.create_visualizer(viz_type=None, **kwargs)[source]#

Convenience function to create a visualizer.

This is a shorthand for VisualizerFactory().create_visualizer().

Parameters:
  • viz_type (VisualizationType | str | None) – The visualization type to use.

  • **kwargs (Any) – Additional keyword arguments to pass to the visualizer constructor.

Return type:

BaseVisualizer

Returns:

An instance of the requested visualizer.

Examples

>>> viz = create_visualizer(VisualizationType.POINT_CLOUD, backend='open3d')
>>> viz = create_visualizer("voxel", voxel_size=0.02)
embodichain.lab.sim.motion.workspace.visualizers.ellipsoid_surface(radii, axes, center=None, resolution=24)[source]#

Tessellate one ellipsoid for surface plotting.

Parameters:
  • radii (ndarray) – Semi-axis lengths, shape (3,).

  • axes (ndarray) – Principal directions as columns, shape (3, 3).

  • center (ndarray | None) – Optional ellipsoid center, shape (3,). Defaults to origin.

  • resolution (int) – Number of samples per angular direction.

Return type:

tuple[ndarray, ndarray, ndarray]

Returns:

(x, y, z) grids of shape (resolution, resolution).

embodichain.lab.sim.motion.workspace.visualizers.inspect_points(selection, *, points, scores, jacobian_fn=None, joint_configurations=None, score_indices=None, with_ellipsoid=True, with_condition_number=True)[source]#

Build detail records for the selected points only.

jacobian_fn is invoked exactly once with the joint configurations of the selected points, so the number of Jacobians (and therefore ellipsoids) computed is len(selection) regardless of how many points are drawn.

Parameters:
  • selection (Union[InspectionSelection, Sequence[int]]) – Selection returned by select_inspection_indices(), or a plain sequence of point indices.

  • points (Tensor | ndarray) – Point positions, shape (P, 3).

  • scores (Tensor | ndarray) – Per-point scores, shape (P,).

  • jacobian_fn (Optional[Callable[[ndarray], Any]]) – Callable mapping joint configurations (K, DOF) to spatial Jacobians (K, 6, DOF). Required for ellipsoids and condition numbers.

  • joint_configurations (Tensor | ndarray | None) – Joint configurations of the scored points, shape (M, DOF).

  • score_indices (ndarray | None) – Mapping from point index to score/joint row, shape (P,), as produced by align_manipulability_scores(). Defaults to identity.

  • with_ellipsoid (bool) – Compute translational ellipsoids.

  • with_condition_number (bool) – Compute Jacobian condition numbers.

Return type:

list[PointInspection]

Returns:

One PointInspection per selected index, in selection order.

Raises:

ValueError – If an index has no joint configuration while Jacobians were requested, or jacobian_fn returns the wrong number of Jacobians.

embodichain.lab.sim.motion.workspace.visualizers.map_manipulability_colors(scores, *, reachable_mask=None, cfg=None)[source]#

Map manipulability scores to RGBA colors and marker sizes.

Reachable points take the configured colormap over the robustly normalized score; unreachable points take cfg.unreachable_color and a smaller marker so they stay visible but visually subordinate.

Parameters:
  • scores (Union[Tensor, ndarray, Sequence[float]]) – Score vector, shape (N,). NaN marks an unscored point.

  • reachable_mask (ndarray | None) – Optional boolean mask, shape (N,). Defaults to the finite entries of scores. Entries that are masked reachable but carry a non-finite score are treated as unreachable.

  • cfg (ManipulabilityColorCfg | None) – Color configuration. Defaults to ManipulabilityColorCfg.

Return type:

ManipulabilityColorMapping

Returns:

The ManipulabilityColorMapping.

Raises:
  • ImportError – If Matplotlib (the colormap source) is unavailable.

  • ValueError – If reachable_mask length does not match scores.

embodichain.lab.sim.motion.workspace.visualizers.normalize_manipulability(scores, *, percentile_clip=(2.0, 98.0), log_scale=False, log_epsilon=1e-12, valid_mask=None)[source]#

Normalize manipulability scores to [0, 1] with percentile clipping.

NaN entries (unreachable points) never contribute to the statistics and stay NaN in the output. The raw score range is reported untouched so a caller can always show the true magnitudes next to the color bar.

Degenerate inputs are handled explicitly: an empty or fully invalid input yields an all-NaN result with NaN ranges, and a constant input (a single point, or all-equal scores) maps to a flat 0.5 instead of dividing by a zero span.

Parameters:
  • scores (Union[Tensor, ndarray, Sequence[float]]) – Score vector, shape (N,).

  • percentile_clip (tuple[float, float]) – (low, high) percentiles in [0, 100] with low < high, evaluated on the transformed values.

  • log_scale (bool) – Normalize log10(max(w, log_epsilon)) instead of w.

  • log_epsilon (float) – Lower clamp applied before log10.

  • valid_mask (ndarray | None) – Optional additional mask of entries to consider valid.

Return type:

ManipulabilityNormalization

Returns:

The ManipulabilityNormalization record.

Raises:

ValueError – If percentile_clip is not an increasing pair inside [0, 100], or log_epsilon is not positive.

embodichain.lab.sim.motion.workspace.visualizers.select_inspection_indices(scores, *, selected=(), top_k=1, bottom_k=1, valid_mask=None)[source]#

Choose the few points that deserve a detailed inspection.

Ellipsoids are expensive and unreadable in bulk, so only an explicit selection plus the best and worst conditioned points are returned. Ties are broken by ascending index so the selection is deterministic.

Parameters:
  • scores (Union[Tensor, ndarray, Sequence[float]]) – Per-point scores, shape (N,); NaN marks unscored points.

  • selected (Sequence[int]) – Explicit point indices to always include, highest priority.

  • top_k (int) – Number of highest-w points to add.

  • bottom_k (int) – Number of lowest-w points to add.

  • valid_mask (ndarray | None) – Optional additional validity mask, shape (N,).

Return type:

InspectionSelection

Returns:

The deduplicated InspectionSelection.

Raises:

ValueError – If top_k or bottom_k is negative, or an explicitly selected index is out of range or carries no score.

embodichain.lab.sim.motion.workspace.visualizers.translational_manipulability_ellipsoid(jacobian)[source]#

Derive translational manipulability ellipsoids from spatial Jacobians.

The ellipsoid {J_t q : ||q|| <= 1} has semi-axes sqrt(eig(J_t J_t^T)) along the corresponding eigenvectors, where J_t is the translational row block selected with embodichain.compute.kinematics.select_jacobian_rows().

Parameters:

jacobian (Tensor | ndarray) – Batched spatial Jacobian, shape (N, 6, DOF).

Return type:

tuple[ndarray, ndarray]

Returns:

Tuple of semi-axis lengths (N, 3) in descending order and the matching principal directions (N, 3, 3) stored as columns.

Raises:

ValueError – If jacobian is not batched 3D or lacks translational rows.