dhb-xr 0.2.1__py3-none-any.whl
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.
- dhb_xr/__init__.py +61 -0
- dhb_xr/cli.py +206 -0
- dhb_xr/core/__init__.py +28 -0
- dhb_xr/core/geometry.py +167 -0
- dhb_xr/core/geometry_torch.py +77 -0
- dhb_xr/core/types.py +113 -0
- dhb_xr/database/__init__.py +10 -0
- dhb_xr/database/motion_db.py +79 -0
- dhb_xr/database/retrieval.py +6 -0
- dhb_xr/database/similarity.py +71 -0
- dhb_xr/decoder/__init__.py +13 -0
- dhb_xr/decoder/decoder_torch.py +52 -0
- dhb_xr/decoder/dhb_dr.py +261 -0
- dhb_xr/decoder/dhb_qr.py +89 -0
- dhb_xr/encoder/__init__.py +27 -0
- dhb_xr/encoder/dhb_dr.py +418 -0
- dhb_xr/encoder/dhb_qr.py +129 -0
- dhb_xr/encoder/dhb_ti.py +204 -0
- dhb_xr/encoder/encoder_torch.py +54 -0
- dhb_xr/encoder/padding.py +82 -0
- dhb_xr/generative/__init__.py +78 -0
- dhb_xr/generative/flow_matching.py +705 -0
- dhb_xr/generative/latent_encoder.py +536 -0
- dhb_xr/generative/sampling.py +203 -0
- dhb_xr/generative/training.py +475 -0
- dhb_xr/generative/vfm_tokenizer.py +485 -0
- dhb_xr/integration/__init__.py +13 -0
- dhb_xr/integration/vla/__init__.py +11 -0
- dhb_xr/integration/vla/libero.py +132 -0
- dhb_xr/integration/vla/pipeline.py +85 -0
- dhb_xr/integration/vla/robocasa.py +85 -0
- dhb_xr/losses/__init__.py +16 -0
- dhb_xr/losses/geodesic_loss.py +91 -0
- dhb_xr/losses/hybrid_loss.py +36 -0
- dhb_xr/losses/invariant_loss.py +73 -0
- dhb_xr/optimization/__init__.py +72 -0
- dhb_xr/optimization/casadi_solver.py +342 -0
- dhb_xr/optimization/constraints.py +32 -0
- dhb_xr/optimization/cusadi_solver.py +311 -0
- dhb_xr/optimization/export_casadi_decode.py +111 -0
- dhb_xr/optimization/fatrop_solver.py +477 -0
- dhb_xr/optimization/torch_solver.py +85 -0
- dhb_xr/preprocessing/__init__.py +42 -0
- dhb_xr/preprocessing/diagnostics.py +330 -0
- dhb_xr/preprocessing/trajectory_cleaner.py +485 -0
- dhb_xr/tokenization/__init__.py +56 -0
- dhb_xr/tokenization/causal_encoder.py +54 -0
- dhb_xr/tokenization/compression.py +749 -0
- dhb_xr/tokenization/hierarchical.py +359 -0
- dhb_xr/tokenization/rvq.py +178 -0
- dhb_xr/tokenization/vqvae.py +155 -0
- dhb_xr/utils/__init__.py +24 -0
- dhb_xr/utils/io.py +59 -0
- dhb_xr/utils/resampling.py +66 -0
- dhb_xr/utils/xdof_loader.py +89 -0
- dhb_xr/visualization/__init__.py +5 -0
- dhb_xr/visualization/plot.py +242 -0
- dhb_xr-0.2.1.dist-info/METADATA +784 -0
- dhb_xr-0.2.1.dist-info/RECORD +82 -0
- dhb_xr-0.2.1.dist-info/WHEEL +5 -0
- dhb_xr-0.2.1.dist-info/entry_points.txt +2 -0
- dhb_xr-0.2.1.dist-info/top_level.txt +3 -0
- examples/__init__.py +54 -0
- examples/basic_encoding.py +82 -0
- examples/benchmark_backends.py +37 -0
- examples/dhb_qr_comparison.py +79 -0
- examples/dhb_ti_time_invariant.py +72 -0
- examples/gpu_batch_optimization.py +102 -0
- examples/imitation_learning.py +53 -0
- examples/integration/__init__.py +19 -0
- examples/integration/libero_full_demo.py +692 -0
- examples/integration/libero_pro_dhb_demo.py +1063 -0
- examples/integration/libero_simulation_demo.py +286 -0
- examples/integration/libero_swap_demo.py +534 -0
- examples/integration/robocasa_libero_dhb_pipeline.py +56 -0
- examples/integration/test_libero_adapter.py +47 -0
- examples/integration/test_libero_encoding.py +75 -0
- examples/integration/test_libero_retrieval.py +105 -0
- examples/motion_database.py +88 -0
- examples/trajectory_adaptation.py +85 -0
- examples/vla_tokenization.py +107 -0
- notebooks/__init__.py +24 -0
|
@@ -0,0 +1,286 @@
|
|
|
1
|
+
#!/usr/bin/env python
|
|
2
|
+
"""LIBERO Simulation Demo with DHB-XR.
|
|
3
|
+
|
|
4
|
+
This script demonstrates:
|
|
5
|
+
1. Setting up a LIBERO environment
|
|
6
|
+
2. Loading a demo trajectory from HDF5
|
|
7
|
+
3. Encoding/decoding with DHB invariants
|
|
8
|
+
4. Replaying the trajectory in simulation
|
|
9
|
+
|
|
10
|
+
Requirements:
|
|
11
|
+
conda create -n libero python=3.10
|
|
12
|
+
conda activate libero
|
|
13
|
+
pip install robosuite mujoco h5py numpy
|
|
14
|
+
git clone https://github.com/Lifelong-Robot-Learning/LIBERO.git
|
|
15
|
+
cd LIBERO && pip install -e .
|
|
16
|
+
pip install dhb_xr
|
|
17
|
+
|
|
18
|
+
Usage:
|
|
19
|
+
python examples/integration/libero_simulation_demo.py --task_id 0 --render
|
|
20
|
+
|
|
21
|
+
Author: Andy Park
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
import argparse
|
|
25
|
+
import os
|
|
26
|
+
import sys
|
|
27
|
+
from pathlib import Path
|
|
28
|
+
|
|
29
|
+
# Add src to path for development
|
|
30
|
+
sys.path.insert(0, str(Path(__file__).parent.parent.parent / "src"))
|
|
31
|
+
|
|
32
|
+
import numpy as np
|
|
33
|
+
|
|
34
|
+
# Check for LIBERO installation
|
|
35
|
+
try:
|
|
36
|
+
from libero.libero import benchmark, get_libero_path
|
|
37
|
+
from libero.libero.envs import OffScreenRenderEnv
|
|
38
|
+
HAS_LIBERO = True
|
|
39
|
+
except ImportError:
|
|
40
|
+
HAS_LIBERO = False
|
|
41
|
+
print("LIBERO not installed. Install with:")
|
|
42
|
+
print(" git clone https://github.com/Lifelong-Robot-Learning/LIBERO.git")
|
|
43
|
+
print(" cd LIBERO && pip install -e .")
|
|
44
|
+
|
|
45
|
+
# Check for robosuite
|
|
46
|
+
try:
|
|
47
|
+
import robosuite
|
|
48
|
+
HAS_ROBOSUITE = True
|
|
49
|
+
except ImportError:
|
|
50
|
+
HAS_ROBOSUITE = False
|
|
51
|
+
print("robosuite not installed. Install with: pip install robosuite mujoco")
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
def load_demo_from_hdf5(dataset_path: str, demo_id: int = 0):
|
|
55
|
+
"""Load a demo trajectory from LIBERO HDF5 dataset."""
|
|
56
|
+
import h5py
|
|
57
|
+
|
|
58
|
+
with h5py.File(dataset_path, "r") as f:
|
|
59
|
+
demo_key = f"demo_{demo_id}"
|
|
60
|
+
if demo_key not in f["data"]:
|
|
61
|
+
raise ValueError(f"Demo {demo_id} not found in {dataset_path}")
|
|
62
|
+
|
|
63
|
+
demo = f["data"][demo_key]
|
|
64
|
+
|
|
65
|
+
# Extract actions
|
|
66
|
+
actions = np.array(demo["actions"])
|
|
67
|
+
|
|
68
|
+
# Extract end-effector pose from robot_states
|
|
69
|
+
robot_states = np.array(demo["robot_states"])
|
|
70
|
+
ee_pos = robot_states[:, 2:5] # columns 2-4
|
|
71
|
+
ee_quat_wxyz = robot_states[:, 5:9] # columns 5-8 (w, x, y, z)
|
|
72
|
+
|
|
73
|
+
# Convert to (x, y, z, w) format
|
|
74
|
+
ee_quat = ee_quat_wxyz[:, [1, 2, 3, 0]]
|
|
75
|
+
|
|
76
|
+
return {
|
|
77
|
+
"actions": actions,
|
|
78
|
+
"positions": ee_pos,
|
|
79
|
+
"quaternions": ee_quat,
|
|
80
|
+
"num_frames": len(actions),
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
|
|
84
|
+
def encode_demo_with_dhb(positions: np.ndarray, quaternions: np.ndarray):
|
|
85
|
+
"""Encode trajectory with DHB-DR."""
|
|
86
|
+
from dhb_xr.encoder.dhb_dr import encode_dhb_dr
|
|
87
|
+
from dhb_xr.core.types import EncodingMethod, DHBMethod
|
|
88
|
+
|
|
89
|
+
result = encode_dhb_dr(
|
|
90
|
+
positions, quaternions,
|
|
91
|
+
method=EncodingMethod.POSITION,
|
|
92
|
+
dhb_method=DHBMethod.DOUBLE_REFLECTION,
|
|
93
|
+
)
|
|
94
|
+
|
|
95
|
+
return {
|
|
96
|
+
"linear_invariants": result["linear_motion_invariants"],
|
|
97
|
+
"angular_invariants": result["angular_motion_invariants"],
|
|
98
|
+
"initial_pose": result["initial_pose"],
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
def decode_demo_with_dhb(
|
|
103
|
+
linear_inv: np.ndarray,
|
|
104
|
+
angular_inv: np.ndarray,
|
|
105
|
+
initial_pose: dict,
|
|
106
|
+
):
|
|
107
|
+
"""Decode DHB invariants back to trajectory."""
|
|
108
|
+
from dhb_xr.decoder.dhb_dr import decode_dhb_dr
|
|
109
|
+
from dhb_xr.core.types import EncodingMethod, DHBMethod
|
|
110
|
+
|
|
111
|
+
result = decode_dhb_dr(
|
|
112
|
+
linear_inv, angular_inv,
|
|
113
|
+
initial_pose,
|
|
114
|
+
method=EncodingMethod.POSITION,
|
|
115
|
+
dhb_method=DHBMethod.DOUBLE_REFLECTION,
|
|
116
|
+
drop_padded=True,
|
|
117
|
+
)
|
|
118
|
+
|
|
119
|
+
return {
|
|
120
|
+
"positions": result["positions"],
|
|
121
|
+
"quaternions": result["quaternions"],
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
|
|
125
|
+
def run_libero_demo(task_id: int = 0, demo_id: int = 0, render: bool = False):
|
|
126
|
+
"""Run a LIBERO task with a demo trajectory."""
|
|
127
|
+
|
|
128
|
+
if not HAS_LIBERO or not HAS_ROBOSUITE:
|
|
129
|
+
print("\nCannot run simulation without LIBERO and robosuite.")
|
|
130
|
+
print("Running DHB encoding/decoding demo only...\n")
|
|
131
|
+
|
|
132
|
+
# Use our downloaded dataset for DHB demo
|
|
133
|
+
dataset_dir = Path(os.environ.get(
|
|
134
|
+
"LIBERO_DATA_DIR",
|
|
135
|
+
"/home/andypark/Projects/data/libero/libero_spatial"
|
|
136
|
+
))
|
|
137
|
+
|
|
138
|
+
if not dataset_dir.exists():
|
|
139
|
+
print(f"Dataset not found at {dataset_dir}")
|
|
140
|
+
print("Download with:")
|
|
141
|
+
print(" wget -O libero_spatial.zip 'https://utexas.box.com/shared/static/04k94hyizn4huhbv5sz4ev9p2h1p6s7f.zip'")
|
|
142
|
+
return
|
|
143
|
+
|
|
144
|
+
# Find first HDF5 file
|
|
145
|
+
hdf5_files = list(dataset_dir.glob("*.hdf5"))
|
|
146
|
+
if not hdf5_files:
|
|
147
|
+
print(f"No HDF5 files found in {dataset_dir}")
|
|
148
|
+
return
|
|
149
|
+
|
|
150
|
+
dataset_path = str(hdf5_files[0])
|
|
151
|
+
print(f"Loading demo from: {dataset_path}")
|
|
152
|
+
|
|
153
|
+
demo = load_demo_from_hdf5(dataset_path, demo_id)
|
|
154
|
+
print(f"Loaded demo with {demo['num_frames']} frames")
|
|
155
|
+
print(f" Positions shape: {demo['positions'].shape}")
|
|
156
|
+
print(f" Quaternions shape: {demo['quaternions'].shape}")
|
|
157
|
+
|
|
158
|
+
# Encode with DHB
|
|
159
|
+
print("\nEncoding with DHB-DR...")
|
|
160
|
+
encoded = encode_demo_with_dhb(demo["positions"], demo["quaternions"])
|
|
161
|
+
print(f" Linear invariants: {encoded['linear_invariants'].shape}")
|
|
162
|
+
print(f" Angular invariants: {encoded['angular_invariants'].shape}")
|
|
163
|
+
|
|
164
|
+
# Decode back
|
|
165
|
+
print("\nDecoding back to trajectory...")
|
|
166
|
+
decoded = decode_demo_with_dhb(
|
|
167
|
+
encoded["linear_invariants"],
|
|
168
|
+
encoded["angular_invariants"],
|
|
169
|
+
encoded["initial_pose"],
|
|
170
|
+
)
|
|
171
|
+
print(f" Decoded positions: {decoded['positions'].shape}")
|
|
172
|
+
print(f" Decoded quaternions: {decoded['quaternions'].shape}")
|
|
173
|
+
|
|
174
|
+
# Compute reconstruction error
|
|
175
|
+
pos_error = np.linalg.norm(demo["positions"] - decoded["positions"][:len(demo["positions"])], axis=1)
|
|
176
|
+
print(f"\nReconstruction error:")
|
|
177
|
+
print(f" Position: mean={pos_error.mean():.6f}m, max={pos_error.max():.6f}m")
|
|
178
|
+
|
|
179
|
+
print("\n=== DHB encoding/decoding successful! ===")
|
|
180
|
+
print("\nTo run full simulation, install LIBERO:")
|
|
181
|
+
print(" conda create -n libero python=3.10")
|
|
182
|
+
print(" conda activate libero")
|
|
183
|
+
print(" pip install robosuite mujoco")
|
|
184
|
+
print(" git clone https://github.com/Lifelong-Robot-Learning/LIBERO.git")
|
|
185
|
+
print(" cd LIBERO && pip install -e .")
|
|
186
|
+
return
|
|
187
|
+
|
|
188
|
+
# ========== Full LIBERO simulation ==========
|
|
189
|
+
print(f"Setting up LIBERO task {task_id}...")
|
|
190
|
+
|
|
191
|
+
# Get benchmark and task
|
|
192
|
+
benchmark_dict = benchmark.get_benchmark_dict()
|
|
193
|
+
task_suite = benchmark_dict["libero_spatial"]()
|
|
194
|
+
|
|
195
|
+
task = task_suite.get_task(task_id)
|
|
196
|
+
print(f"Task: {task.name}")
|
|
197
|
+
print(f"Description: {task.language}")
|
|
198
|
+
|
|
199
|
+
# Get BDDL file for environment setup
|
|
200
|
+
task_bddl_file = os.path.join(
|
|
201
|
+
get_libero_path("bddl_files"),
|
|
202
|
+
task.problem_folder,
|
|
203
|
+
task.bddl_file
|
|
204
|
+
)
|
|
205
|
+
|
|
206
|
+
# Create environment
|
|
207
|
+
env_args = {
|
|
208
|
+
"bddl_file_name": task_bddl_file,
|
|
209
|
+
"camera_heights": 128,
|
|
210
|
+
"camera_widths": 128,
|
|
211
|
+
}
|
|
212
|
+
|
|
213
|
+
if render:
|
|
214
|
+
env_args["has_renderer"] = True
|
|
215
|
+
env_args["has_offscreen_renderer"] = False
|
|
216
|
+
|
|
217
|
+
env = OffScreenRenderEnv(**env_args)
|
|
218
|
+
env.seed(0)
|
|
219
|
+
|
|
220
|
+
# Get initial states for benchmarking
|
|
221
|
+
init_states = task_suite.get_task_init_states(task_id)
|
|
222
|
+
init_state_id = 0
|
|
223
|
+
|
|
224
|
+
# Reset and set initial state
|
|
225
|
+
env.reset()
|
|
226
|
+
env.set_init_state(init_states[init_state_id])
|
|
227
|
+
|
|
228
|
+
# Load demo actions from dataset
|
|
229
|
+
dataset_path = os.path.join(
|
|
230
|
+
get_libero_path("datasets"),
|
|
231
|
+
"libero_spatial",
|
|
232
|
+
f"{task.name}_demo.hdf5"
|
|
233
|
+
)
|
|
234
|
+
|
|
235
|
+
print(f"Loading demo from: {dataset_path}")
|
|
236
|
+
demo = load_demo_from_hdf5(dataset_path, demo_id)
|
|
237
|
+
|
|
238
|
+
# Encode with DHB
|
|
239
|
+
print("Encoding demo with DHB-DR...")
|
|
240
|
+
encoded = encode_demo_with_dhb(demo["positions"], demo["quaternions"])
|
|
241
|
+
|
|
242
|
+
print(f"Running {demo['num_frames']} steps in simulation...")
|
|
243
|
+
|
|
244
|
+
# Execute demo actions
|
|
245
|
+
for step in range(demo["num_frames"]):
|
|
246
|
+
action = demo["actions"][step]
|
|
247
|
+
obs, reward, done, info = env.step(action)
|
|
248
|
+
|
|
249
|
+
if render:
|
|
250
|
+
env.render()
|
|
251
|
+
|
|
252
|
+
if done:
|
|
253
|
+
print(f"Task completed at step {step}!")
|
|
254
|
+
break
|
|
255
|
+
|
|
256
|
+
# Check final reward
|
|
257
|
+
if reward > 0:
|
|
258
|
+
print("SUCCESS: Task completed!")
|
|
259
|
+
else:
|
|
260
|
+
print("Task not completed within demo length.")
|
|
261
|
+
|
|
262
|
+
env.close()
|
|
263
|
+
print("\nSimulation finished.")
|
|
264
|
+
|
|
265
|
+
|
|
266
|
+
def main():
|
|
267
|
+
parser = argparse.ArgumentParser(description="LIBERO + DHB-XR Demo")
|
|
268
|
+
parser.add_argument("--task_id", type=int, default=0, help="LIBERO task ID")
|
|
269
|
+
parser.add_argument("--demo_id", type=int, default=0, help="Demo ID within task")
|
|
270
|
+
parser.add_argument("--render", action="store_true", help="Render simulation")
|
|
271
|
+
args = parser.parse_args()
|
|
272
|
+
|
|
273
|
+
print("=" * 60)
|
|
274
|
+
print("LIBERO Simulation Demo with DHB-XR")
|
|
275
|
+
print("=" * 60)
|
|
276
|
+
print()
|
|
277
|
+
|
|
278
|
+
run_libero_demo(
|
|
279
|
+
task_id=args.task_id,
|
|
280
|
+
demo_id=args.demo_id,
|
|
281
|
+
render=args.render,
|
|
282
|
+
)
|
|
283
|
+
|
|
284
|
+
|
|
285
|
+
if __name__ == "__main__":
|
|
286
|
+
main()
|