Visualization#
Visualization helpers for rendering skeletons and meshes.
G1 robot rig: mesh loading, joint mapping, and viser scene setup for G1 skeleton.
- kimodo.viz.g1_rig.get_g1_joint_f2q_data(skeleton)[source]#
Return per-hinge-joint f2q data for correct 1-DoF + limits in offset space.
- Each entry is for a G1 hinge joint (by name) and contains:
“offset_f2q”: (3, 3) matrix such that R_f2q = offset_f2q @ R_local (kimodo).
“axis_f2q”: (3,) unit axis in f2q space; angle = dot(axis_angle(R_f2q), axis_f2q).
“rest_dof_axis_angle”: angle (rad) at T-pose in f2q space; MuJoCo q = angle_f2q - this.
Limits from the XML apply to q = angle_f2q - rest_dof_axis_angle.
- class kimodo.viz.g1_rig.G1MeshRig(name, server, skeleton, mesh_dir, color)[source]#
Bases:
objectRig for G1 STL meshes.
Each instance has its own scene meshes (so clear() only removes one character). Loading is shared: STL files and g1.xml are cached per mesh_dir via _load_g1_mesh_data() and the class- level _mesh_*_cache dicts.
SMPL-X skinning and joint mapping for visualization.
- class kimodo.viz.smplx_skin.SMPLXSkin(skeleton, use_mean_hands=True)[source]#
Bases:
object- skin(joint_rotmat, joint_pos, rot_is_global=False)[source]#
joint_rotmat: [T, J, 3, 3] local or global joint rotation matrices joint_pos: [T, J, 3] global joint positions rot_is_global: bool, if True, joint_rotmat is global rotation matrices, otherwise it is local rotation matrices and FK is performed internally
Viser-based 3D viz: re-exports from viz submodules for backward compatibility.
- class kimodo.viz.viser_utils.Character(
- name,
- server,
- skeleton,
- create_skeleton_mesh=True,
- create_skinned_mesh=True,
- visible_skeleton=False,
- visible_skinned_mesh=True,
- skinned_mesh_opacity=1.0,
- show_foot_contacts=True,
- dark_mode=False,
- mesh_mode=None,
- gui_use_soma_layer_checkbox=None,
Bases:
object- __init__(
- name,
- server,
- skeleton,
- create_skeleton_mesh=True,
- create_skinned_mesh=True,
- visible_skeleton=False,
- visible_skinned_mesh=True,
- skinned_mesh_opacity=1.0,
- show_foot_contacts=True,
- dark_mode=False,
- mesh_mode=None,
- gui_use_soma_layer_checkbox=None,
- precompute_skinning(joints_pos, joints_rot)[source]#
Precompute skinning for all frames.
joints_pos: [T, J, 3], joints_rot: [T, J, 3, 3].
- class kimodo.viz.viser_utils.CharacterMotion(character, joints_pos, joints_rot, foot_contacts=None)[source]#
Bases:
object- update_pose_at_frame(
- frame_idx,
- joints_pos=None,
- joints_rot=None,
- joints_local_rot=None,
- foot_contacts=None,
Overwrites one or more of the pose components at the given frame.
If only a subset of joints_pos, joints_rot, or joints_local_rot are provided, the other components will be updated with FK.
- get_current_projected_root_pos()[source]#
Get the projected root position on the ground at the current frame.
- get_projected_root_pos(
- start_frame_idx,
- end_frame_idx=None,
If requested frames are out of range, simply pads with the last frame to get expected length.
- set_projected_root_pos_path(
- root_pos_path,
- min_frame_idx=None,
- max_frame_idx=None,
Sets the projected root position path for the character motion. Can set only a subset of the path by providing min_frame_idx and max_frame_idx. If not provided, will set the full path.
- Parameters:
root_pos_path – torch.Tensor, [T, 2] projected root positions
min_frame_idx – int, optional, minimum frame index to set the path at
max_frame_idx – int, optional, maximum frame index to set the path at
- get_joints_pos(start_frame_idx, end_frame_idx=None)[source]#
If requested frames are out of range, simply pads with the last frame to get expected length.
- get_joints_rot(start_frame_idx, end_frame_idx=None)[source]#
If requested frames are out of range, simply pads with the last frame to get expected length.
- add_root_translation_gizmo(
- constraints,
- on_2d_root_drag_end=None,
- on_drag_start=None,
Create and initialize gizmo to control the root translation.
When the user drags the root 2D gizmo, path updates are skipped until release. Optional on_2d_root_drag_end is called when the drag ends (e.g. to refresh dense path). on_drag_start is called when the drag begins (e.g. to snapshot state for undo).
- class kimodo.viz.viser_utils.ConstraintSet(name, server, skeleton, display_name=None)[source]#
Bases:
object- set_overlay_visibility(only_frame=None)[source]#
Show all overlay elements, or only those at the given frame.
- Parameters:
only_frame – If None, show all overlays. If int, show only overlays at that frame.
- add_keyframe(keyframe_id, frame_idx, pose_data)[source]#
Adds a single keyframe at the given frame with the given pose data.
- Parameters:
keyframe_id – str, id for the keyframe. Must be unique within the given frame_idx.
frame_idx – int, frame index to add the keyframe at
pose_data – torch.Tensor, e.g. full-body pose, EE pose, 2D root pose, etc.
- add_interval(
- interval_id,
- start_frame_idx,
- end_frame_idx,
- pose_seq_data,
Adds a keyframe interval between the given start and end frames with the given pose data.
- Parameters:
interval_id – str, id for the interval. Must be unique within the given start_frame_idx and end_frame_idx.
start_frame_idx – int, start frame index of the interval
end_frame_idx – int, end frame index of the interval
pose_seq_data – torch.Tensor, data for constrained interval, e.g. full-body poses, EE poses, 2D root poses, etc.
- remove_keyframe(keyframe_id, frame_idx)[source]#
Removes a keyframe at the given frame :param keyframe_id: str, id for the keyframe to remove :param frame_idx: int, frame index to remove the keyframe at
- remove_interval(
- interval_id,
- start_frame_idx,
- end_frame_idx,
Removes an interval between the given start and end frames :param interval_id: str, id for the interval to remove :param start_frame_idx: int, start frame index of the interval :param end_frame_idx: int, end frame index of the interval
- class kimodo.viz.viser_utils.EEJointsKeyframeSet(name, server, skeleton, display_name=None)[source]#
Bases:
ConstraintSet- add_keyframe(
- keyframe_id,
- frame_idx,
- joints_pos,
- joints_rot,
- joint_names,
- end_effector_type,
- viz_label=True,
- exists_ok=False,
Adds a single EE keyframe at the given frame or updates the existing one at this frame.
- Parameters:
keyframe_id – str, id for the keyframe. Must be unique within the given frame_idx.
frame_idx – int, frame index to add the keyframe at
joints_pos – torch.Tensor, [J, 3] joints positions to add the keyframe at
joints_rot – torch.Tensor, [J, 3, 3] joints rotation matrices to add the keyframe at
joint_names – List[str], names of the joints to add the keyframe at
- add_interval(
- interval_id,
- start_frame_idx,
- end_frame_idx,
- joints_pos,
- joints_rot,
- joint_names,
- end_effector_type,
Adds an interval of EE keyframes at the given frame or updates the existing one at this frame.
- Parameters:
interval_id – str, id for the interval. Must be unique within the given start_frame_idx and end_frame_idx.
start_frame_idx – int, start frame index to add the interval at
end_frame_idx – int, end frame index to add the interval at
joints_pos – torch.Tensor, [T, J, 3] joints positions to add the interval at
joints_rot – torch.Tensor, [T, J, 3, 3] joints rotation matrices to add the interval at
joint_names – List[str], names of the joints to add for the entire interval
- remove_keyframe(keyframe_id, frame_idx)[source]#
Removes a keyframe at the given frame or updates the existing one at this frame by removing the specified joints.
- Parameters:
keyframe_id – str, id for the keyframe to remove. This determines which joints to remove.
frame_idx – int, frame index to remove the keyframe at
- remove_interval(
- interval_id,
- start_frame_idx,
- end_frame_idx,
Removes an interval between the given start and end frames :param interval_id: str, id for the interval to remove :param start_frame_idx: int, start frame index of the interval :param end_frame_idx: int, end frame index of the interval
- get_constraint_info(device=None)[source]#
Returns constraint information for generation (torch) or UI (numpy).
- class kimodo.viz.viser_utils.FullbodyKeyframeSet(name, server, skeleton, display_name=None)[source]#
Bases:
ConstraintSet- add_keyframe(
- keyframe_id,
- frame_idx,
- joints_pos,
- joints_rot,
- viz_label=True,
- exists_ok=False,
Adds a single full-body keyframe at the given frame or updates the existing one at this frame. Note if a keyframe already exists at this frame, it will be updated to the given pose.
- Parameters:
keyframe_id – str, id for the keyframe. Must be unique within the given frame_idx.
frame_idx – int, frame index to add the keyframe at
joints_pos – torch.Tensor, [J, 3] joints positions to add the keyframe at
- add_interval(
- interval_id,
- start_frame_idx,
- end_frame_idx,
- joints_pos,
- joints_rot,
Adds a full-body keyframe interval between the given start and end frames.
- Parameters:
start_frame_idx – int, start frame index of the interval
end_frame_idx – int, end frame index of the interval
joints_pos – torch.Tensor, [T, J, 3] joints positions within the interval
- remove_keyframe(keyframe_id, frame_idx)[source]#
Removes a keyframe at the given frame :param keyframe_id: str, id for the keyframe to remove :param frame_idx: int, frame index to remove the keyframe at
- remove_interval(
- interval_id,
- start_frame_idx,
- end_frame_idx,
Removes an interval between the given start and end frames :param interval_id: str, id for the interval to remove :param start_frame_idx: int, start frame index of the interval :param end_frame_idx: int, end frame index of the interval
- get_constraint_info(device=None)[source]#
Returns constraint information for generation (torch) or UI (numpy).
- class kimodo.viz.viser_utils.GuiElements(
- gui_play_pause_button: viser._gui_handles.GuiInputHandle,
- gui_next_frame_button: viser._gui_handles.GuiInputHandle,
- gui_prev_frame_button: viser._gui_handles.GuiInputHandle,
- gui_generate_button: viser._gui_handles.GuiInputHandle,
- gui_model_fps: viser._gui_handles.GuiInputHandle[int],
- gui_timeline: viser._gui_handles.GuiInputHandle[int],
- gui_viz_skeleton_checkbox: viser._gui_handles.GuiInputHandle[bool],
- gui_viz_foot_contacts_checkbox: viser._gui_handles.GuiInputHandle[bool],
- gui_viz_skinned_mesh_checkbox: viser._gui_handles.GuiInputHandle[bool],
- gui_viz_skinned_mesh_opacity_slider: viser._gui_handles.GuiInputHandle[float],
- gui_camera_fov_slider: viser._gui_handles.GuiInputHandle[float],
- gui_duration_slider: viser._gui_handles.GuiInputHandle[float],
- gui_num_samples_slider: viser._gui_handles.GuiInputHandle[int],
- gui_cfg_checkbox: viser._gui_handles.GuiCheckboxHandle,
- gui_cfg_text_weight_slider: viser._gui_handles.GuiInputHandle[float],
- gui_cfg_constraint_weight_slider: viser._gui_handles.GuiInputHandle[float],
- gui_diffusion_steps_slider: viser._gui_handles.GuiInputHandle[int],
- gui_seed: viser._gui_handles.GuiInputHandle[int],
- gui_postprocess_checkbox: viser._gui_handles.GuiCheckboxHandle,
- gui_root_margin: viser._gui_handles.GuiInputHandle[float],
- gui_real_robot_rotations_checkbox: viser._gui_handles.GuiInputHandle[bool],
- gui_dark_mode_checkbox: viser._gui_handles.GuiCheckboxHandle,
- gui_use_soma_layer_checkbox: viser._gui_handles.GuiCheckboxHandle,
Bases:
object- gui_play_pause_button#
- gui_next_frame_button#
- gui_prev_frame_button#
- gui_generate_button#
- gui_model_fps#
- gui_timeline#
- gui_viz_skeleton_checkbox#
- gui_viz_foot_contacts_checkbox#
- gui_viz_skinned_mesh_checkbox#
- gui_viz_skinned_mesh_opacity_slider#
- gui_camera_fov_slider#
- gui_duration_slider#
- gui_num_samples_slider#
- gui_cfg_checkbox#
- gui_cfg_text_weight_slider#
- gui_cfg_constraint_weight_slider#
- gui_diffusion_steps_slider#
- gui_seed#
- gui_postprocess_checkbox#
- gui_root_margin#
- gui_real_robot_rotations_checkbox#
- gui_dark_mode_checkbox#
- gui_use_soma_layer_checkbox#
- __init__(
- gui_play_pause_button,
- gui_next_frame_button,
- gui_prev_frame_button,
- gui_generate_button,
- gui_model_fps,
- gui_timeline,
- gui_viz_skeleton_checkbox,
- gui_viz_foot_contacts_checkbox,
- gui_viz_skinned_mesh_checkbox,
- gui_viz_skinned_mesh_opacity_slider,
- gui_camera_fov_slider,
- gui_duration_slider,
- gui_num_samples_slider,
- gui_cfg_checkbox,
- gui_cfg_text_weight_slider,
- gui_cfg_constraint_weight_slider,
- gui_diffusion_steps_slider,
- gui_seed,
- gui_postprocess_checkbox,
- gui_root_margin,
- gui_real_robot_rotations_checkbox,
- gui_dark_mode_checkbox,
- gui_use_soma_layer_checkbox,
- class kimodo.viz.viser_utils.RootKeyframe2DSet(name, server, skeleton, display_name=None)[source]#
Bases:
ConstraintSet- add_keyframe(
- keyframe_id,
- frame_idx,
- root_pos,
- viz_label=True,
- update_path=True,
- viz_waypoint=True,
- exists_ok=False,
Adds a single 2D root keyframe at the given frame or updates the existing one at this frame.
- Parameters:
keyframe_id – str, id for the keyframe. Must be unique within the given frame_idx.
frame_idx – int, frame index to add the keyframe at
root_pos – torch.Tensor, [3] root position to add the keyframe at, y entry (index 1) should be 0
viz_label – bool, whether to visualize the label for the keyframe
- add_interval(
- interval_id,
- start_frame_idx,
- end_frame_idx,
- root_pos,
Adds an interval of 2D root keyframes between the given start and end frames.
- Parameters:
interval_id – str, id for the interval. Must be unique within the given start_frame_idx and end_frame_idx.
start_frame_idx – int, start frame index to add the interval at
end_frame_idx – int, end frame index to add the interval at
root_pos – torch.Tensor, [T, 3] root positions to add the interval at
- set_dense_path(dense_path)[source]#
If dense_path is True, will make the path dense by interpolated between added keyframes.
- Parameters:
dense_path – bool, whether to make the path dense
- interpolate_path(t)[source]#
Interpolates the path between the given frame indices.
- Parameters:
t – np.ndarray, frame indices to interpolate at
- remove_keyframe(keyframe_id, frame_idx)[source]#
Removes a keyframe at the given frame :param keyframe_id: str, id for the keyframe to remove :param frame_idx: int, frame index to remove the keyframe at
- remove_interval(
- interval_id,
- start_frame_idx,
- end_frame_idx,
Removes an interval between the given start and end frames :param interval_id: str, id for the interval to remove :param start_frame_idx: int, start frame index of the interval :param end_frame_idx: int, end frame index of the interval
- get_constraint_info(device=None)[source]#
Returns constraint information for generation (torch) or UI (numpy).
- class kimodo.viz.viser_utils.SkeletonMesh(
- name,
- server,
- skeleton,
- joint_color=(255, 235, 0),
- bone_color=(27, 106, 0),
- starting_joints_pos=None,
Bases:
object- __init__(
- name,
- server,
- skeleton,
- joint_color=(255, 235, 0),
- bone_color=(27, 106, 0),
- starting_joints_pos=None,
name: str, name of the skeleton mesh server: viser.ViserServer, server to add the skeleton mesh to skeleton: SkeletonBase, skeleton to visualize joint_color: Optional[Tuple[float, float, float] | np.ndarray], color of the joints bone_color: Optional[Tuple[float, float, float] | np.ndarray], color of the bones starting_joints_pos: Optional[torch.Tensor], starting joint positions
- compute_single_pose(joints_pos)[source]#
Compute the mesh for a single frame.
joints_pos: [J, 3] global joint positions.
- precompute_mesh_info(joints_pos)[source]#
Precompute the meshes for all frames at once.
joints_pos: [T, J, 3].
- update_mesh_info_cache(joints_pos, frame_idx)[source]#
Update the mesh info cache for the given frame.
- class kimodo.viz.viser_utils.WaypointMesh(name, server, position, heading=None, color=(255, 0, 0))[source]#
Bases:
object