robot-keyframe-kit 0.3.0__tar.gz → 0.3.2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {robot_keyframe_kit-0.3.0/src/robot_keyframe_kit.egg-info → robot_keyframe_kit-0.3.2}/PKG-INFO +1 -1
- {robot_keyframe_kit-0.3.0 → robot_keyframe_kit-0.3.2}/pyproject.toml +4 -4
- {robot_keyframe_kit-0.3.0 → robot_keyframe_kit-0.3.2}/src/robot_keyframe_kit/__init__.py +0 -6
- {robot_keyframe_kit-0.3.0 → robot_keyframe_kit-0.3.2}/src/robot_keyframe_kit/config.py +10 -30
- {robot_keyframe_kit-0.3.0 → robot_keyframe_kit-0.3.2}/src/robot_keyframe_kit/editor.py +160 -543
- {robot_keyframe_kit-0.3.0 → robot_keyframe_kit-0.3.2}/src/robot_keyframe_kit/keyframe.py +2 -7
- robot_keyframe_kit-0.3.2/src/robot_keyframe_kit/math_utils.py +196 -0
- {robot_keyframe_kit-0.3.0 → robot_keyframe_kit-0.3.2}/src/robot_keyframe_kit/sim_worker.py +46 -108
- {robot_keyframe_kit-0.3.0 → robot_keyframe_kit-0.3.2/src/robot_keyframe_kit.egg-info}/PKG-INFO +1 -1
- robot_keyframe_kit-0.3.0/src/robot_keyframe_kit/math_utils.py +0 -111
- {robot_keyframe_kit-0.3.0 → robot_keyframe_kit-0.3.2}/LICENSE +0 -0
- {robot_keyframe_kit-0.3.0 → robot_keyframe_kit-0.3.2}/MANIFEST.in +0 -0
- {robot_keyframe_kit-0.3.0 → robot_keyframe_kit-0.3.2}/README.md +0 -0
- {robot_keyframe_kit-0.3.0 → robot_keyframe_kit-0.3.2}/setup.cfg +0 -0
- {robot_keyframe_kit-0.3.0 → robot_keyframe_kit-0.3.2}/src/robot_keyframe_kit.egg-info/SOURCES.txt +0 -0
- {robot_keyframe_kit-0.3.0 → robot_keyframe_kit-0.3.2}/src/robot_keyframe_kit.egg-info/dependency_links.txt +0 -0
- {robot_keyframe_kit-0.3.0 → robot_keyframe_kit-0.3.2}/src/robot_keyframe_kit.egg-info/entry_points.txt +0 -0
- {robot_keyframe_kit-0.3.0 → robot_keyframe_kit-0.3.2}/src/robot_keyframe_kit.egg-info/requires.txt +0 -0
- {robot_keyframe_kit-0.3.0 → robot_keyframe_kit-0.3.2}/src/robot_keyframe_kit.egg-info/top_level.txt +0 -0
{robot_keyframe_kit-0.3.0/src/robot_keyframe_kit.egg-info → robot_keyframe_kit-0.3.2}/PKG-INFO
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: robot-keyframe-kit
|
|
3
|
-
Version: 0.3.
|
|
3
|
+
Version: 0.3.2
|
|
4
4
|
Summary: A generalizable Viser-based keyframe editor for any MuJoCo robot
|
|
5
5
|
Author-email: Stanford TML <yuming29@stanford.edu>
|
|
6
6
|
Maintainer-email: Stanford TML <yuming29@stanford.edu>
|
|
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
|
|
|
4
4
|
|
|
5
5
|
[project]
|
|
6
6
|
name = "robot-keyframe-kit"
|
|
7
|
-
version = "0.3.
|
|
7
|
+
version = "0.3.2"
|
|
8
8
|
description = "A generalizable Viser-based keyframe editor for any MuJoCo robot"
|
|
9
9
|
readme = "README.md"
|
|
10
10
|
license = "MIT"
|
|
@@ -64,9 +64,9 @@ robot_keyframe_kit = ["py.typed"]
|
|
|
64
64
|
"*" = ["examples/*", "keyframes/*", "*.lz4", "*.stl", "*.dae"]
|
|
65
65
|
|
|
66
66
|
[tool.black]
|
|
67
|
-
line-length =
|
|
67
|
+
line-length = 120
|
|
68
68
|
target-version = ["py310"]
|
|
69
69
|
|
|
70
70
|
[tool.ruff]
|
|
71
|
-
line-length =
|
|
72
|
-
select = ["E", "F", "I"]
|
|
71
|
+
line-length = 120
|
|
72
|
+
lint.select = ["E", "F", "I"]
|
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
5
|
import os
|
|
6
|
-
from dataclasses import dataclass
|
|
6
|
+
from dataclasses import dataclass
|
|
7
7
|
from typing import Dict, List, Optional
|
|
8
8
|
|
|
9
9
|
try:
|
|
@@ -48,9 +48,7 @@ class EditorConfig:
|
|
|
48
48
|
# Note: Position-type actuators (like Unitree G1) use MuJoCo's built-in PD.
|
|
49
49
|
kp: float = 12.0 # Position gain (proportional) - matches typical Dynamixel motors
|
|
50
50
|
kd: float = 0.5 # Velocity gain (derivative) - light damping
|
|
51
|
-
motor_tau_limit: float =
|
|
52
|
-
1.0 # Fallback |tau| clamp for torque actuators without model limits
|
|
53
|
-
)
|
|
51
|
+
motor_tau_limit: float = 1.0 # Fallback |tau| clamp for torque actuators without model limits
|
|
54
52
|
|
|
55
53
|
# UI settings
|
|
56
54
|
show_com: bool = True # Show center of mass marker
|
|
@@ -59,12 +57,8 @@ class EditorConfig:
|
|
|
59
57
|
root_pose_gizmo_scale: float = 0.35 # Base scale for root pose transform gizmo
|
|
60
58
|
ik_target_gizmo_scale: float = 0.18 # Base scale for IK target transform gizmos
|
|
61
59
|
auto_scale_gizmos: bool = True # Scale gizmos based on robot model size
|
|
62
|
-
gizmo_scale_ratio: float =
|
|
63
|
-
|
|
64
|
-
)
|
|
65
|
-
gizmo_reference_height: float = (
|
|
66
|
-
1.28 # Height (m) where base gizmo scales are unchanged
|
|
67
|
-
)
|
|
60
|
+
gizmo_scale_ratio: float = 1.0 # Optional global multiplier applied after auto-scaling
|
|
61
|
+
gizmo_reference_height: float = 1.28 # Height (m) where base gizmo scales are unchanged
|
|
68
62
|
|
|
69
63
|
# Scene generation settings
|
|
70
64
|
auto_inject_floor: bool = True # Whether to auto-inject floor for robot-only XMLs
|
|
@@ -85,10 +79,7 @@ class EditorConfig:
|
|
|
85
79
|
FileNotFoundError: If the config file doesn't exist.
|
|
86
80
|
"""
|
|
87
81
|
if yaml is None:
|
|
88
|
-
raise ImportError(
|
|
89
|
-
"PyYAML is required to load YAML config files. "
|
|
90
|
-
"Install with: pip install pyyaml"
|
|
91
|
-
)
|
|
82
|
+
raise ImportError("PyYAML is required to load YAML config files. Install with: pip install pyyaml")
|
|
92
83
|
|
|
93
84
|
if not os.path.exists(path):
|
|
94
85
|
raise FileNotFoundError(f"Config file not found: {path}")
|
|
@@ -174,10 +165,7 @@ class EditorConfig:
|
|
|
174
165
|
ImportError: If PyYAML is not installed.
|
|
175
166
|
"""
|
|
176
167
|
if yaml is None:
|
|
177
|
-
raise ImportError(
|
|
178
|
-
"PyYAML is required to save YAML config files. "
|
|
179
|
-
"Install with: pip install pyyaml"
|
|
180
|
-
)
|
|
168
|
+
raise ImportError("PyYAML is required to save YAML config files. Install with: pip install pyyaml")
|
|
181
169
|
|
|
182
170
|
data = {
|
|
183
171
|
"name": self.name,
|
|
@@ -212,16 +200,12 @@ class EditorConfig:
|
|
|
212
200
|
# Remove None values
|
|
213
201
|
data = {k: v for k, v in data.items() if v is not None}
|
|
214
202
|
|
|
215
|
-
os.makedirs(
|
|
216
|
-
os.path.dirname(path) if os.path.dirname(path) else ".", exist_ok=True
|
|
217
|
-
)
|
|
203
|
+
os.makedirs(os.path.dirname(path) if os.path.dirname(path) else ".", exist_ok=True)
|
|
218
204
|
with open(path, "w") as f:
|
|
219
205
|
yaml.dump(data, f, default_flow_style=False, sort_keys=False)
|
|
220
206
|
|
|
221
207
|
@classmethod
|
|
222
|
-
def generate_from_model(
|
|
223
|
-
cls, xml_path: str, name: Optional[str] = None
|
|
224
|
-
) -> "EditorConfig":
|
|
208
|
+
def generate_from_model(cls, xml_path: str, name: Optional[str] = None) -> "EditorConfig":
|
|
225
209
|
"""Generate a configuration file from a MuJoCo model by auto-detecting settings.
|
|
226
210
|
|
|
227
211
|
This creates a config with auto-detected values that can be manually edited.
|
|
@@ -262,9 +246,7 @@ class EditorConfig:
|
|
|
262
246
|
for body_id in leaf_body_ids:
|
|
263
247
|
for site_id in range(model.nsite):
|
|
264
248
|
if model.site_bodyid[site_id] == body_id:
|
|
265
|
-
site_name = mujoco.mj_id2name(
|
|
266
|
-
model, mujoco.mjtObj.mjOBJ_SITE, site_id
|
|
267
|
-
)
|
|
249
|
+
site_name = mujoco.mj_id2name(model, mujoco.mjtObj.mjOBJ_SITE, site_id)
|
|
268
250
|
if site_name:
|
|
269
251
|
end_effectors.append(site_name)
|
|
270
252
|
|
|
@@ -289,9 +271,7 @@ class EditorConfig:
|
|
|
289
271
|
for joint_name in joint_names:
|
|
290
272
|
if "left" in joint_name.lower() or "_l_" in joint_name.lower():
|
|
291
273
|
# Try to find corresponding right joint
|
|
292
|
-
right_name = joint_name.replace("left", "right").replace(
|
|
293
|
-
"Left", "Right"
|
|
294
|
-
)
|
|
274
|
+
right_name = joint_name.replace("left", "right").replace("Left", "Right")
|
|
295
275
|
right_name_alt = joint_name.replace("_l_", "_r_").replace("_L_", "_R_")
|
|
296
276
|
|
|
297
277
|
if right_name in joint_names:
|