lsnu commited on
Commit
d93804e
·
verified ·
1 Parent(s): f0cc55f

Upload folder using huggingface_hub

Browse files
Files changed (49) hide show
  1. .gitattributes +13 -0
  2. bundle/artifacts/env/hf_env.txt +35 -0
  3. bundle/artifacts/env/nvidia_smi.txt +20 -0
  4. bundle/artifacts/env/pip_freeze.txt +241 -0
  5. bundle/artifacts/env/python_version.txt +1 -0
  6. bundle/artifacts/env/uv_version.txt +1 -0
  7. bundle/artifacts/logs/hf_archive.log +183 -0
  8. bundle/artifacts/logs/hf_archived_steps.txt +4 -0
  9. bundle/artifacts/logs/stop_at_4000.log +4 -0
  10. bundle/artifacts/logs/teddybear_train.log +0 -0
  11. bundle/artifacts/sim/background_inpaint.png +3 -0
  12. bundle/artifacts/sim/box_mask_overlay.png +3 -0
  13. bundle/artifacts/sim/box_world_outline.png +3 -0
  14. bundle/artifacts/sim/pi_actions_3500.json +162 -0
  15. bundle/artifacts/sim/pi_policy_preview_3500.gif +3 -0
  16. bundle/artifacts/sim/pi_policy_preview_3500_strip.png +3 -0
  17. bundle/artifacts/sim/pi_rollout_3500.json +3967 -0
  18. bundle/artifacts/sim/pi_rollout_preview_3500.gif +3 -0
  19. bundle/artifacts/sim/pi_rollout_preview_3500_strip.png +3 -0
  20. bundle/artifacts/sim/real_start.png +3 -0
  21. bundle/artifacts/sim/real_vs_scene_start.png +3 -0
  22. bundle/artifacts/sim/recorded_motion.gif +3 -0
  23. bundle/artifacts/sim/scene_motion_fit.png +3 -0
  24. bundle/artifacts/sim/scene_start_render.png +3 -0
  25. bundle/artifacts/sim/session_20260327_165944_bear_scene_fit.json +123 -0
  26. bundle/artifacts/sim/teddy_mask_overlay.png +3 -0
  27. bundle/code/openpi/pyproject.toml +137 -0
  28. bundle/code/openpi/scripts/archive_teddybear_checkpoints_to_hf.sh +89 -0
  29. bundle/code/openpi/scripts/bench_first_kinova_batch.py +28 -0
  30. bundle/code/openpi/scripts/bench_kinova_loader.py +39 -0
  31. bundle/code/openpi/scripts/compute_norm_stats_kinova_teddybear.py +58 -0
  32. bundle/code/openpi/scripts/serve_policy.py +122 -0
  33. bundle/code/openpi/scripts/stop_train_at_checkpoint.sh +44 -0
  34. bundle/code/openpi/scripts/train.py +280 -0
  35. bundle/code/openpi/scripts/watch_teddybear_train.sh +49 -0
  36. bundle/code/openpi/src/openpi/training/config.py +1036 -0
  37. bundle/code/openpi/src/openpi/training/data_loader.py +550 -0
  38. bundle/code/openpi/src/openpi/training/kinova_lerobot_v3_dataset.py +169 -0
  39. bundle/code/openpi/uv.lock +0 -0
  40. bundle/run_rollout_preview.sh +22 -0
  41. bundle/setup_same_a100.sh +32 -0
  42. bundle/sim/build_scene.py +103 -0
  43. bundle/sim/export_pi_actions.py +84 -0
  44. bundle/sim/render_pose_sequence.py +108 -0
  45. bundle/sim/rollout_pi_policy.py +97 -0
  46. bundle/sim/run_policy_preview.py +136 -0
  47. bundle/sim/run_policy_rollout_preview.py +120 -0
  48. bundle/sim/scene_tools.py +392 -0
  49. bundle/train_teddybear_pi05.sh +13 -0
.gitattributes CHANGED
@@ -142,3 +142,16 @@ saved_model/**/* filter=lfs diff=lfs merge=lfs -text
142
  4000/train_state/ocdbt.process_0/d/fb76fcb92bd6e30088fcfe25956ab8c7 filter=lfs diff=lfs merge=lfs -text
143
  4000/train_state/ocdbt.process_0/d/9a60defbddc71aadce3ed5d3eb7cc4ad filter=lfs diff=lfs merge=lfs -text
144
  4000/train_state/ocdbt.process_0/d/b4a126dd14bfad0863317f2f3966e36d filter=lfs diff=lfs merge=lfs -text
 
 
 
 
 
 
 
 
 
 
 
 
 
 
142
  4000/train_state/ocdbt.process_0/d/fb76fcb92bd6e30088fcfe25956ab8c7 filter=lfs diff=lfs merge=lfs -text
143
  4000/train_state/ocdbt.process_0/d/9a60defbddc71aadce3ed5d3eb7cc4ad filter=lfs diff=lfs merge=lfs -text
144
  4000/train_state/ocdbt.process_0/d/b4a126dd14bfad0863317f2f3966e36d filter=lfs diff=lfs merge=lfs -text
145
+ bundle/artifacts/sim/background_inpaint.png filter=lfs diff=lfs merge=lfs -text
146
+ bundle/artifacts/sim/box_mask_overlay.png filter=lfs diff=lfs merge=lfs -text
147
+ bundle/artifacts/sim/box_world_outline.png filter=lfs diff=lfs merge=lfs -text
148
+ bundle/artifacts/sim/pi_policy_preview_3500.gif filter=lfs diff=lfs merge=lfs -text
149
+ bundle/artifacts/sim/pi_policy_preview_3500_strip.png filter=lfs diff=lfs merge=lfs -text
150
+ bundle/artifacts/sim/pi_rollout_preview_3500.gif filter=lfs diff=lfs merge=lfs -text
151
+ bundle/artifacts/sim/pi_rollout_preview_3500_strip.png filter=lfs diff=lfs merge=lfs -text
152
+ bundle/artifacts/sim/real_start.png filter=lfs diff=lfs merge=lfs -text
153
+ bundle/artifacts/sim/real_vs_scene_start.png filter=lfs diff=lfs merge=lfs -text
154
+ bundle/artifacts/sim/recorded_motion.gif filter=lfs diff=lfs merge=lfs -text
155
+ bundle/artifacts/sim/scene_motion_fit.png filter=lfs diff=lfs merge=lfs -text
156
+ bundle/artifacts/sim/scene_start_render.png filter=lfs diff=lfs merge=lfs -text
157
+ bundle/artifacts/sim/teddy_mask_overlay.png filter=lfs diff=lfs merge=lfs -text
bundle/artifacts/env/hf_env.txt ADDED
@@ -0,0 +1,35 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+
2
+ Copy-and-paste the text below in your GitHub issue.
3
+
4
+ - huggingface_hub version: 1.8.0
5
+ - Platform: Linux-6.8.0-59-generic-x86_64-with-glibc2.35
6
+ - Python version: 3.11.10
7
+ - Running in iPython ?: No
8
+ - Running in notebook ?: No
9
+ - Running in Google Colab ?: No
10
+ - Running in Google Colab Enterprise ?: No
11
+ - Token path ?: /workspace/.cache/huggingface/token
12
+ - Has saved token ?: True
13
+ - Who am I ?: lsnu
14
+ - Configured git credential helpers:
15
+ - Installation method: unknown
16
+ - httpx: 0.27.2
17
+ - hf_xet: 1.4.2
18
+ - gradio: N/A
19
+ - tensorboard: N/A
20
+ - ENDPOINT: https://huggingface.co
21
+ - HF_HUB_CACHE: /workspace/.cache/huggingface/hub
22
+ - HF_ASSETS_CACHE: /workspace/.cache/huggingface/assets
23
+ - HF_TOKEN_PATH: /workspace/.cache/huggingface/token
24
+ - HF_STORED_TOKENS_PATH: /workspace/.cache/huggingface/stored_tokens
25
+ - HF_HUB_OFFLINE: False
26
+ - HF_HUB_DISABLE_TELEMETRY: False
27
+ - HF_HUB_DISABLE_PROGRESS_BARS: None
28
+ - HF_HUB_DISABLE_SYMLINKS_WARNING: False
29
+ - HF_HUB_DISABLE_EXPERIMENTAL_WARNING: False
30
+ - HF_HUB_DISABLE_IMPLICIT_TOKEN: False
31
+ - HF_HUB_DISABLE_XET: False
32
+ - HF_HUB_ETAG_TIMEOUT: 10
33
+ - HF_HUB_DOWNLOAD_TIMEOUT: 10
34
+ - HF_XET_HIGH_PERFORMANCE: False
35
+
bundle/artifacts/env/nvidia_smi.txt ADDED
@@ -0,0 +1,20 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ Sun Mar 29 02:13:09 2026
2
+ +-----------------------------------------------------------------------------------------+
3
+ | NVIDIA-SMI 570.133.20 Driver Version: 570.133.20 CUDA Version: 12.8 |
4
+ |-----------------------------------------+------------------------+----------------------+
5
+ | GPU Name Persistence-M | Bus-Id Disp.A | Volatile Uncorr. ECC |
6
+ | Fan Temp Perf Pwr:Usage/Cap | Memory-Usage | GPU-Util Compute M. |
7
+ | | | MIG M. |
8
+ |=========================================+========================+======================|
9
+ | 0 NVIDIA A100-SXM4-80GB On | 00000000:90:00.0 Off | 0 |
10
+ | N/A 43C P0 66W / 400W | 0MiB / 81920MiB | 0% Default |
11
+ | | | Disabled |
12
+ +-----------------------------------------+------------------------+----------------------+
13
+
14
+ +-----------------------------------------------------------------------------------------+
15
+ | Processes: |
16
+ | GPU GI CI PID Type Process name GPU Memory |
17
+ | ID ID Usage |
18
+ |=========================================================================================|
19
+ | No running processes found |
20
+ +-----------------------------------------------------------------------------------------+
bundle/artifacts/env/pip_freeze.txt ADDED
@@ -0,0 +1,241 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ absl-py==2.3.0
2
+ aiohappyeyeballs==2.6.1
3
+ aiohttp==3.12.4
4
+ aiosignal==1.3.2
5
+ annotated-types==0.7.0
6
+ antlr4-python3-runtime==4.9.3
7
+ asttokens==3.0.0
8
+ attrs==25.3.0
9
+ augmax==0.4.1
10
+ av==14.4.0
11
+ beartype==0.19.0
12
+ beautifulsoup4==4.13.4
13
+ blinker==1.9.0
14
+ cachetools==5.5.2
15
+ certifi==2025.4.26
16
+ cffi==1.17.1
17
+ cfgv==3.4.0
18
+ charset-normalizer==3.4.2
19
+ chex==0.1.89
20
+ click==8.2.1
21
+ cloudpickle==3.1.1
22
+ cmake==4.0.2
23
+ comm==0.2.2
24
+ contourpy==1.3.2
25
+ crc32c==2.7.1
26
+ cycler==0.12.1
27
+ datasets==3.6.0
28
+ debugpy==1.8.14
29
+ decorator==5.2.1
30
+ deepdiff==8.5.0
31
+ diffusers==0.33.1
32
+ dill==0.3.8
33
+ distlib==0.3.9
34
+ dm-control==1.0.14
35
+ dm-env==1.6
36
+ dm-tree==0.1.9
37
+ docker-pycreds==0.4.0
38
+ docstring_parser==0.16
39
+ donfig==0.8.1.post1
40
+ draccus==0.10.0
41
+ einops==0.8.1
42
+ equinox==0.12.2
43
+ etils==1.12.2
44
+ evdev==1.9.2
45
+ executing==2.2.0
46
+ Farama-Notifications==0.0.4
47
+ filelock==3.18.0
48
+ Flask==3.1.1
49
+ flatbuffers==25.2.10
50
+ flax==0.10.2
51
+ fonttools==4.58.1
52
+ frozenlist==1.6.0
53
+ fsspec==2025.3.0
54
+ gcsfs==2025.3.0
55
+ gdown==5.2.0
56
+ gitdb==4.0.12
57
+ GitPython==3.1.44
58
+ glfw==2.9.0
59
+ google-api-core==2.24.2
60
+ google-auth==2.40.2
61
+ google-auth-oauthlib==1.2.2
62
+ google-cloud-core==2.4.3
63
+ google-cloud-storage==3.1.0
64
+ google-crc32c==1.7.1
65
+ google-resumable-media==2.7.2
66
+ googleapis-common-protos==1.70.0
67
+ gym-aloha==0.1.1
68
+ gymnasium==0.29.1
69
+ h5py==3.13.0
70
+ hf-xet==1.1.2
71
+ hf_transfer==0.1.9
72
+ huggingface-hub==0.32.3
73
+ humanize==4.12.3
74
+ identify==2.6.12
75
+ idna==3.10
76
+ imageio==2.37.0
77
+ imageio-ffmpeg==0.6.0
78
+ importlib_metadata==8.7.0
79
+ importlib_resources==6.5.2
80
+ iniconfig==2.1.0
81
+ inquirerpy==0.3.4
82
+ ipykernel==6.29.5
83
+ ipython==9.2.0
84
+ ipython_pygments_lexers==1.1.1
85
+ ipywidgets==8.1.7
86
+ itsdangerous==2.2.0
87
+ jax==0.5.3
88
+ jax-cuda12-pjrt==0.5.3
89
+ jax-cuda12-plugin==0.5.3
90
+ jaxlib==0.5.3
91
+ jaxtyping==0.2.36
92
+ jedi==0.19.2
93
+ Jinja2==3.1.6
94
+ jsonlines==4.0.0
95
+ jupyter_client==8.6.3
96
+ jupyter_core==5.8.1
97
+ jupyterlab_widgets==3.0.15
98
+ kiwisolver==1.4.8
99
+ labmaze==1.0.6
100
+ lerobot @ git+https://github.com/huggingface/lerobot@0cf864870cf29f4738d3ade893e6fd13fbd7cdb5
101
+ llvmlite==0.44.0
102
+ lxml==5.4.0
103
+ markdown-it-py==3.0.0
104
+ MarkupSafe==3.0.2
105
+ matplotlib==3.10.3
106
+ matplotlib-inline==0.1.7
107
+ mdurl==0.1.2
108
+ mergedeep==1.3.4
109
+ ml-dtypes==0.4.1
110
+ ml_collections==1.0.0
111
+ mpmath==1.3.0
112
+ msgpack==1.1.0
113
+ mujoco==2.3.7
114
+ multidict==6.4.4
115
+ multiprocess==0.70.16
116
+ mypy_extensions==1.1.0
117
+ nest-asyncio==1.6.0
118
+ networkx==3.5
119
+ nodeenv==1.9.1
120
+ numba==0.61.2
121
+ numcodecs==0.16.1
122
+ numpy==1.26.4
123
+ numpydantic==1.6.9
124
+ nvidia-cublas-cu12==12.6.4.1
125
+ nvidia-cuda-cupti-cu12==12.6.80
126
+ nvidia-cuda-nvcc-cu12==12.9.41
127
+ nvidia-cuda-nvrtc-cu12==12.6.77
128
+ nvidia-cuda-runtime-cu12==12.6.77
129
+ nvidia-cudnn-cu12==9.5.1.17
130
+ nvidia-cufft-cu12==11.3.0.4
131
+ nvidia-cufile-cu12==1.11.1.6
132
+ nvidia-curand-cu12==10.3.7.77
133
+ nvidia-cusolver-cu12==11.7.1.2
134
+ nvidia-cusparse-cu12==12.5.4.2
135
+ nvidia-cusparselt-cu12==0.6.3
136
+ nvidia-ml-py==12.575.51
137
+ nvidia-nccl-cu12==2.26.2
138
+ nvidia-nvjitlink-cu12==12.6.85
139
+ nvidia-nvtx-cu12==12.6.77
140
+ oauthlib==3.2.2
141
+ omegaconf==2.3.0
142
+ opencv-python==4.11.0.86
143
+ opencv-python-headless==4.11.0.86
144
+ -e git+https://github.com/Physical-Intelligence/openpi.git@54cbaee6ae0c010a1ed431871cdaa8f4684ac709#egg=openpi
145
+ -e git+https://github.com/Physical-Intelligence/openpi.git@54cbaee6ae0c010a1ed431871cdaa8f4684ac709#egg=openpi_client&subdirectory=packages/openpi-client
146
+ opt_einsum==3.4.0
147
+ optax==0.2.4
148
+ orbax-checkpoint==0.11.13
149
+ orderly-set==5.4.1
150
+ packaging==25.0
151
+ pandas==2.2.3
152
+ parso==0.8.4
153
+ pexpect==4.9.0
154
+ pfzy==0.3.4
155
+ pillow==11.2.1
156
+ platformdirs==4.3.8
157
+ pluggy==1.6.0
158
+ polars==1.30.0
159
+ pre_commit==4.2.0
160
+ prompt_toolkit==3.0.51
161
+ propcache==0.3.1
162
+ proto-plus==1.26.1
163
+ protobuf==4.25.8
164
+ psutil==7.0.0
165
+ ptyprocess==0.7.0
166
+ pure_eval==0.2.3
167
+ pyarrow==20.0.0
168
+ pyasn1==0.6.1
169
+ pyasn1_modules==0.4.2
170
+ pycparser==2.22
171
+ pydantic==2.11.5
172
+ pydantic_core==2.33.2
173
+ Pygments==2.19.1
174
+ pymunk==7.0.0
175
+ pynput==1.8.1
176
+ pynvml==12.0.0
177
+ PyOpenGL==3.1.9
178
+ pyparsing==3.2.3
179
+ PySocks==1.7.1
180
+ pytest==8.3.5
181
+ python-dateutil==2.9.0.post0
182
+ python-xlib==0.33
183
+ pytz==2025.2
184
+ PyYAML==6.0.2
185
+ pyyaml-include==1.4.1
186
+ pyzmq==26.4.0
187
+ regex==2024.11.6
188
+ requests==2.32.3
189
+ requests-oauthlib==2.0.0
190
+ rerun-sdk==0.23.1
191
+ rich==14.0.0
192
+ rsa==4.9.1
193
+ ruff==0.11.12
194
+ safetensors==0.5.3
195
+ scipy==1.15.3
196
+ sentencepiece==0.2.0
197
+ sentry-sdk==2.29.1
198
+ setproctitle==1.3.6
199
+ shtab==1.7.2
200
+ simplejson==3.20.1
201
+ six==1.17.0
202
+ smmap==5.0.2
203
+ soupsieve==2.7
204
+ stack-data==0.6.3
205
+ svgwrite==1.4.3
206
+ sympy==1.14.0
207
+ tensorstore==0.1.74
208
+ termcolor==3.1.0
209
+ tokenizers==0.21.1
210
+ toml==0.10.2
211
+ toolz==1.0.0
212
+ torch==2.7.1
213
+ torchcodec==0.4.0
214
+ torchvision==0.22.1
215
+ tornado==6.5.1
216
+ tqdm==4.67.1
217
+ tqdm-loggable==0.2
218
+ traitlets==5.14.3
219
+ transformers==4.53.2
220
+ Tree==0.2.4
221
+ treescope==0.1.9
222
+ triton==3.3.1
223
+ typeguard==4.4.2
224
+ typing-inspect==0.9.0
225
+ typing-inspection==0.4.1
226
+ typing_extensions==4.13.2
227
+ tyro==0.9.22
228
+ tzdata==2025.2
229
+ urllib3==2.4.0
230
+ virtualenv==20.31.2
231
+ wadler_lindig==0.1.6
232
+ wandb==0.19.11
233
+ wcwidth==0.2.13
234
+ websockets==15.0.1
235
+ Werkzeug==3.1.3
236
+ widgetsnbextension==4.0.14
237
+ wrapt==1.14.1
238
+ xxhash==3.5.0
239
+ yarl==1.20.0
240
+ zarr==3.0.8
241
+ zipp==3.22.0
bundle/artifacts/env/python_version.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ Python 3.11.10
bundle/artifacts/env/uv_version.txt ADDED
@@ -0,0 +1 @@
 
 
1
+ uv 0.11.2 (x86_64-unknown-linux-gnu)
bundle/artifacts/logs/hf_archive.log ADDED
@@ -0,0 +1,183 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ 2026-03-28T22:31:38Z | archiver_start repo=lsnu/TeddyBearKinova root=/workspace/openpi/checkpoints/pi05_kinova_teddybear/teddybear_kinova_ft_v4_b24_w12_fork
2
+ 2026-03-28T23:21:41Z | upload_start step=2000
3
+ Repo created: https://huggingface.co/lsnu/TeddyBearKinova
4
+ Found 48 candidate files to upload
5
+ Running validation checks on files to upload...
6
+ Validation checks complete.
7
+ Starting upload...
8
+ You are about to upload a large folder to the Hub using `hf upload-large-folder`. This is a new feature so feedback is very welcome!
9
+
10
+ A few things to keep in mind:
11
+ - Repository limits still apply: https://huggingface.co/docs/hub/repositories-recommendations
12
+ - Do not start several processes in parallel.
13
+ - You can interrupt and resume the process at any time. The script will pick up where it left off except for partially uploaded files that would have to be entirely reuploaded.
14
+ - Do not upload the same folder to several repositories. If you need to do so, you must delete the `./.cache/huggingface/` folder first.
15
+
16
+ Some temporary metadata will be stored under `/workspace/hf_stage_2000/.cache/huggingface`.
17
+ - You must not modify those files manually.
18
+ - You must not delete the `./.cache/huggingface/` folder while a process is running.
19
+ - You can delete the `./.cache/huggingface/` folder to reinitialize the upload state when process is not running. Files will have to be hashed and preuploaded again, except for already committed files.
20
+
21
+ If the process output is too verbose, you can disable the progress bars with `--no-bars`. You can also entirely disable the status report with `--no-report`.
22
+
23
+ For more details, run `hf upload-large-folder --help` or check the documentation at https://huggingface.co/docs/huggingface_hub/guides/upload#upload-a-large-folder.
24
+
25
+
26
+
27
+ ---------- 2026-03-28 23:21:44 (0:00:00) ----------
28
+ Files: hashed 0/48 (0.0/44.8G) | pre-uploaded: 0/0 (0.0/44.8G) (+48 unsure) | committed: 0/48 (0.0/44.8G) | ignored: 0
29
+ Workers: hashing: 8 | get upload mode: 0 | pre-uploading: 0 | committing: 0 | waiting: 0
30
+ ---------------------------------------------------
31
+
32
+ ---------- 2026-03-28 23:22:44 (0:01:00) ----------
33
+ Files: hashed 48/48 (44.8G/44.8G) | pre-uploaded: 0/24 (0.0/44.8G) | committed: 0/48 (0.0/44.8G) | ignored: 0
34
+ Workers: hashing: 0 | get upload mode: 0 | pre-uploading: 8 | committing: 0 | waiting: 0
35
+ ---------------------------------------------------
36
+
37
+ ---------- 2026-03-28 23:23:44 (0:02:00) ----------
38
+ Files: hashed 48/48 (44.8G/44.8G) | pre-uploaded: 6/24 (11.5G/44.8G) | committed: 0/48 (0.0/44.8G) | ignored: 0
39
+ Workers: hashing: 0 | get upload mode: 0 | pre-uploading: 2 | committing: 0 | waiting: 6
40
+ ---------------------------------------------------
41
+
42
+ ---------- 2026-03-28 23:24:44 (0:03:00) ----------
43
+ Files: hashed 48/48 (44.8G/44.8G) | pre-uploaded: 24/24 (44.8G/44.8G) | committed: 0/48 (0.0/44.8G) | ignored: 0
44
+ Workers: hashing: 0 | get upload mode: 0 | pre-uploading: 0 | committing: 1 | waiting: 7
45
+ ---------------------------------------------------
46
+ All files have been processed! Exiting worker.
47
+ All files have been processed! Exiting worker.
48
+ Is done: exiting main loop
49
+ All files have been processed! Exiting worker.
50
+ All files have been processed! Exiting worker.
51
+ All files have been processed! Exiting worker.
52
+ All files have been processed! Exiting worker.
53
+ All files have been processed! Exiting worker.
54
+ All files have been processed! Exiting worker.
55
+
56
+ ---------- 2026-03-28 23:25:03 (0:03:19) ----------
57
+ Files: hashed 48/48 (44.8G/44.8G) | pre-uploaded: 24/24 (44.8G/44.8G) | committed: 48/48 (44.8G/44.8G) | ignored: 0
58
+ Workers: hashing: 0 | get upload mode: 0 | pre-uploading: 0 | committing: 0 | waiting: 0
59
+ ---------------------------------------------------
60
+ Upload is complete!
61
+ 2026-03-28T23:25:10Z | upload_done step=2000
62
+ 2026-03-28T23:34:12Z | archiver_start repo=lsnu/TeddyBearKinova root=/workspace/openpi/checkpoints/pi05_kinova_teddybear/teddybear_kinova_ft_v4_b24_w12_fork
63
+ 2026-03-28T23:34:32Z | archiver_start repo=lsnu/TeddyBearKinova root=/workspace/openpi/checkpoints/pi05_kinova_teddybear/teddybear_kinova_ft_v4_b24_w12_fork
64
+ 2026-03-28T23:56:33Z | upload_start step=2500
65
+ Repo created: https://huggingface.co/lsnu/TeddyBearKinova
66
+ Found 42 candidate files to upload
67
+ Running validation checks on files to upload...
68
+ Validation checks complete.
69
+ Starting upload...
70
+ You are about to upload a large folder to the Hub using `hf upload-large-folder`. This is a new feature so feedback is very welcome!
71
+
72
+ A few things to keep in mind:
73
+ - Repository limits still apply: https://huggingface.co/docs/hub/repositories-recommendations
74
+ - Do not start several processes in parallel.
75
+ - You can interrupt and resume the process at any time. The script will pick up where it left off except for partially uploaded files that would have to be entirely reuploaded.
76
+ - Do not upload the same folder to several repositories. If you need to do so, you must delete the `./.cache/huggingface/` folder first.
77
+
78
+ Some temporary metadata will be stored under `/workspace/hf_stage_2500/.cache/huggingface`.
79
+ - You must not modify those files manually.
80
+ - You must not delete the `./.cache/huggingface/` folder while a process is running.
81
+ - You can delete the `./.cache/huggingface/` folder to reinitialize the upload state when process is not running. Files will have to be hashed and preuploaded again, except for already committed files.
82
+
83
+ If the process output is too verbose, you can disable the progress bars with `--no-bars`. You can also entirely disable the status report with `--no-report`.
84
+
85
+ For more details, run `hf upload-large-folder --help` or check the documentation at https://huggingface.co/docs/huggingface_hub/guides/upload#upload-a-large-folder.
86
+
87
+
88
+
89
+ ---------- 2026-03-28 23:56:34 (0:00:00) ----------
90
+ Files: hashed 0/42 (0.0/44.8G) | pre-uploaded: 0/0 (0.0/44.8G) (+42 unsure) | committed: 0/42 (0.0/44.8G) | ignored: 0
91
+ Workers: hashing: 8 | get upload mode: 0 | pre-uploading: 0 | committing: 0 | waiting: 0
92
+ ---------------------------------------------------
93
+
94
+ ---------- 2026-03-28 23:57:34 (0:01:00) ----------
95
+ Files: hashed 42/42 (44.8G/44.8G) | pre-uploaded: 0/21 (0.0/44.8G) | committed: 0/42 (0.0/44.8G) | ignored: 0
96
+ Workers: hashing: 0 | get upload mode: 0 | pre-uploading: 7 | committing: 0 | waiting: 1
97
+ ---------------------------------------------------
98
+
99
+ ---------- 2026-03-28 23:58:34 (0:02:00) ----------
100
+ Files: hashed 42/42 (44.8G/44.8G) | pre-uploaded: 0/21 (0.0/44.8G) | committed: 0/42 (0.0/44.8G) | ignored: 0
101
+ Workers: hashing: 0 | get upload mode: 0 | pre-uploading: 7 | committing: 0 | waiting: 1
102
+ ---------------------------------------------------
103
+
104
+ ---------- 2026-03-28 23:59:35 (0:03:00) ----------
105
+ Files: hashed 42/42 (44.8G/44.8G) | pre-uploaded: 21/21 (44.8G/44.8G) | committed: 0/42 (0.0/44.8G) | ignored: 0
106
+ Workers: hashing: 0 | get upload mode: 0 | pre-uploading: 0 | committing: 1 | waiting: 7
107
+ ---------------------------------------------------
108
+ All files have been processed! Exiting worker.
109
+ Is done: exiting main loop
110
+ All files have been processed! Exiting worker.
111
+ All files have been processed! Exiting worker.
112
+ All files have been processed! Exiting worker.
113
+ All files have been processed! Exiting worker.
114
+ All files have been processed! Exiting worker.
115
+ All files have been processed! Exiting worker.
116
+ All files have been processed! Exiting worker.
117
+
118
+ ---------- 2026-03-28 23:59:58 (0:03:24) ----------
119
+ Files: hashed 42/42 (44.8G/44.8G) | pre-uploaded: 21/21 (44.8G/44.8G) | committed: 42/42 (44.8G/44.8G) | ignored: 0
120
+ Workers: hashing: 0 | get upload mode: 0 | pre-uploading: 0 | committing: 0 | waiting: 0
121
+ ---------------------------------------------------
122
+ Upload is complete!
123
+ 2026-03-29T00:00:05Z | upload_done step=2500
124
+ 2026-03-29T00:22:06Z | upload_start step=3000
125
+ Repo created: https://huggingface.co/lsnu/TeddyBearKinova
126
+ Found 42 candidate files to upload
127
+ Running validation checks on files to upload...
128
+ Validation checks complete.
129
+ Starting upload...
130
+ You are about to upload a large folder to the Hub using `hf upload-large-folder`. This is a new feature so feedback is very welcome!
131
+
132
+ A few things to keep in mind:
133
+ - Repository limits still apply: https://huggingface.co/docs/hub/repositories-recommendations
134
+ - Do not start several processes in parallel.
135
+ - You can interrupt and resume the process at any time. The script will pick up where it left off except for partially uploaded files that would have to be entirely reuploaded.
136
+ - Do not upload the same folder to several repositories. If you need to do so, you must delete the `./.cache/huggingface/` folder first.
137
+
138
+ Some temporary metadata will be stored under `/workspace/hf_stage_3000/.cache/huggingface`.
139
+ - You must not modify those files manually.
140
+ - You must not delete the `./.cache/huggingface/` folder while a process is running.
141
+ - You can delete the `./.cache/huggingface/` folder to reinitialize the upload state when process is not running. Files will have to be hashed and preuploaded again, except for already committed files.
142
+
143
+ If the process output is too verbose, you can disable the progress bars with `--no-bars`. You can also entirely disable the status report with `--no-report`.
144
+
145
+ For more details, run `hf upload-large-folder --help` or check the documentation at https://huggingface.co/docs/huggingface_hub/guides/upload#upload-a-large-folder.
146
+
147
+
148
+
149
+ ---------- 2026-03-29 00:22:07 (0:00:00) ----------
150
+ Files: hashed 2/42 (544.0/44.8G) | pre-uploaded: 0/0 (0.0/44.8G) (+42 unsure) | committed: 0/42 (0.0/44.8G) | ignored: 0
151
+ Workers: hashing: 8 | get upload mode: 0 | pre-uploading: 0 | committing: 0 | waiting: 0
152
+ ---------------------------------------------------
153
+
154
+ ---------- 2026-03-29 00:23:07 (0:01:00) ----------
155
+ Files: hashed 42/42 (44.8G/44.8G) | pre-uploaded: 0/20 (0.0/44.8G) | committed: 0/42 (0.0/44.8G) | ignored: 0
156
+ Workers: hashing: 0 | get upload mode: 0 | pre-uploading: 6 | committing: 0 | waiting: 2
157
+ ---------------------------------------------------
158
+
159
+ ---------- 2026-03-29 00:24:07 (0:02:00) ----------
160
+ Files: hashed 42/42 (44.8G/44.8G) | pre-uploaded: 6/20 (11.5G/44.8G) | committed: 0/42 (0.0/44.8G) | ignored: 0
161
+ Workers: hashing: 0 | get upload mode: 0 | pre-uploading: 2 | committing: 0 | waiting: 6
162
+ ---------------------------------------------------
163
+
164
+ ---------- 2026-03-29 00:25:07 (0:03:00) ----------
165
+ Files: hashed 42/42 (44.8G/44.8G) | pre-uploaded: 20/20 (44.8G/44.8G) | committed: 0/42 (0.0/44.8G) | ignored: 0
166
+ Workers: hashing: 0 | get upload mode: 0 | pre-uploading: 0 | committing: 1 | waiting: 7
167
+ ---------------------------------------------------
168
+ All files have been processed! Exiting worker.
169
+ All files have been processed! Exiting worker.
170
+ All files have been processed! Exiting worker.
171
+ Is done: exiting main loop
172
+ All files have been processed! Exiting worker.
173
+ All files have been processed! Exiting worker.
174
+ All files have been processed! Exiting worker.
175
+ All files have been processed! Exiting worker.
176
+ All files have been processed! Exiting worker.
177
+
178
+ ---------- 2026-03-29 00:25:28 (0:03:20) ----------
179
+ Files: hashed 42/42 (44.8G/44.8G) | pre-uploaded: 20/20 (44.8G/44.8G) | committed: 42/42 (44.8G/44.8G) | ignored: 0
180
+ Workers: hashing: 0 | get upload mode: 0 | pre-uploading: 0 | committing: 0 | waiting: 0
181
+ ---------------------------------------------------
182
+ Upload is complete!
183
+ 2026-03-29T00:25:35Z | upload_done step=3000
bundle/artifacts/logs/hf_archived_steps.txt ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ 1000
2
+ 2000
3
+ 2500
4
+ 3000
bundle/artifacts/logs/stop_at_4000.log ADDED
@@ -0,0 +1,4 @@
 
 
 
 
 
1
+ 2026-03-29T01:29:49Z | watch_start pid=1221991 target_step=4000 checkpoint_root=/workspace/openpi/checkpoints/pi05_kinova_teddybear/teddybear_kinova_ft_v4_b24_w12_fork
2
+ 2026-03-29T01:51:22Z | checkpoint_ready step=4000
3
+ 2026-03-29T01:51:22Z | signal_sent signal=TERM pid=1221991
4
+ 2026-03-29T01:51:28Z | signal_sent signal=INT pid=1221991
bundle/artifacts/logs/teddybear_train.log ADDED
The diff for this file is too large to render. See raw diff
 
bundle/artifacts/sim/background_inpaint.png ADDED

Git LFS Details

  • SHA256: 6c2af4c2a6d8025bae28cb5f1d4249f3ebd6aa4bcd6e4db85f44d3ade29a19c8
  • Pointer size: 132 Bytes
  • Size of remote file: 1.84 MB
bundle/artifacts/sim/box_mask_overlay.png ADDED

Git LFS Details

  • SHA256: fec721e05fa1227ad88cd341e0ed3b6be0fa3fa1db9641e4d15b808024912988
  • Pointer size: 132 Bytes
  • Size of remote file: 1.71 MB
bundle/artifacts/sim/box_world_outline.png ADDED

Git LFS Details

  • SHA256: 4e2aa5d9f95d20152c933af6dcb8bbbe92452f62345c5e078ef6db95e4b91748
  • Pointer size: 132 Bytes
  • Size of remote file: 1.74 MB
bundle/artifacts/sim/pi_actions_3500.json ADDED
@@ -0,0 +1,162 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "checkpoint_dir": "/workspace/kinova_scene_sim/staged_checkpoints_3500/3500",
3
+ "session_root": "/workspace/data/teddybear_raw/session_20260327_165944_bear",
4
+ "sync_row_index": 0,
5
+ "azure_rgb_file": "azure_rgb/000010.jpg",
6
+ "wrist_rgb_file": "rgb/000000.jpg",
7
+ "state": [
8
+ 0.13042281568050385,
9
+ 0.0013459887122735381,
10
+ 0.2086409330368042,
11
+ 176.00607299804688,
12
+ -0.0013248149771243334,
13
+ 89.99845886230469,
14
+ 4.80349588394165
15
+ ],
16
+ "actions": [
17
+ [
18
+ 0.13038688898086548,
19
+ 0.0014187133638188243,
20
+ 0.20857597887516022,
21
+ 176.00660705566406,
22
+ -0.0010383824119344354,
23
+ 89.99771881103516,
24
+ 3.870360851287842
25
+ ],
26
+ [
27
+ 0.1302502304315567,
28
+ 0.0013153755571693182,
29
+ 0.20861351490020752,
30
+ 176.0064697265625,
31
+ -0.0011160902213305235,
32
+ 89.99806213378906,
33
+ 3.690521240234375
34
+ ],
35
+ [
36
+ 0.13023793697357178,
37
+ 0.0012819102266803384,
38
+ 0.20857881009578705,
39
+ 176.0062713623047,
40
+ -0.0012181210331618786,
41
+ 89.99817657470703,
42
+ 3.651444911956787
43
+ ],
44
+ [
45
+ 0.13030986487865448,
46
+ 0.0013734204694628716,
47
+ 0.20860803127288818,
48
+ 176.0064239501953,
49
+ -0.0014578866539523005,
50
+ 89.99809265136719,
51
+ 3.6906394958496094
52
+ ],
53
+ [
54
+ 0.1302148997783661,
55
+ 0.0013296795077621937,
56
+ 0.20862483978271484,
57
+ 176.0063934326172,
58
+ -0.0012297590728849173,
59
+ 89.9979476928711,
60
+ 3.66821551322937
61
+ ],
62
+ [
63
+ 0.13030855357646942,
64
+ 0.0012651914730668068,
65
+ 0.20867392420768738,
66
+ 176.00656127929688,
67
+ -0.001598228933289647,
68
+ 89.99803161621094,
69
+ 3.754732847213745
70
+ ],
71
+ [
72
+ 0.13031162321567535,
73
+ 0.0012794281356036663,
74
+ 0.20865340530872345,
75
+ 176.00653076171875,
76
+ -0.0015227764379233122,
77
+ 89.99803924560547,
78
+ 3.8800547122955322
79
+ ],
80
+ [
81
+ 0.13022325932979584,
82
+ 0.0012262801174074411,
83
+ 0.20850715041160583,
84
+ 176.006103515625,
85
+ -0.0012301492970436811,
86
+ 89.99808502197266,
87
+ 4.038285732269287
88
+ ],
89
+ [
90
+ 0.13038043677806854,
91
+ 0.001231524394825101,
92
+ 0.20850330591201782,
93
+ 176.00624084472656,
94
+ -0.0012325852876529098,
95
+ 89.9980697631836,
96
+ 4.302825927734375
97
+ ],
98
+ [
99
+ 0.13038581609725952,
100
+ 0.001150989904999733,
101
+ 0.20857061445713043,
102
+ 176.0060577392578,
103
+ -0.0012798609677702188,
104
+ 89.9980239868164,
105
+ 4.259771347045898
106
+ ],
107
+ [
108
+ 0.13041627407073975,
109
+ 0.0011642909375950694,
110
+ 0.20851978659629822,
111
+ 176.006103515625,
112
+ -0.0012036851840093732,
113
+ 89.99813842773438,
114
+ 4.265687465667725
115
+ ],
116
+ [
117
+ 0.13035060465335846,
118
+ 0.0012715674238279462,
119
+ 0.20847438275814056,
120
+ 176.00587463378906,
121
+ -0.0015258120838552713,
122
+ 89.99850463867188,
123
+ 4.377945423126221
124
+ ],
125
+ [
126
+ 0.1303417980670929,
127
+ 0.0012600033078342676,
128
+ 0.2084597498178482,
129
+ 176.0060272216797,
130
+ -0.0009475614642724395,
131
+ 89.99833679199219,
132
+ 4.183290481567383
133
+ ],
134
+ [
135
+ 0.1304168999195099,
136
+ 0.0011939689284190536,
137
+ 0.20853134989738464,
138
+ 176.0057830810547,
139
+ -0.0013050022535026073,
140
+ 89.99844360351562,
141
+ 4.19566011428833
142
+ ],
143
+ [
144
+ 0.1303562968969345,
145
+ 0.0012072586687281728,
146
+ 0.20855338871479034,
147
+ 176.00575256347656,
148
+ -0.000863268505781889,
149
+ 89.99850463867188,
150
+ 4.2605509757995605
151
+ ],
152
+ [
153
+ 0.1303006112575531,
154
+ 0.0012522602919489145,
155
+ 0.2085985243320465,
156
+ 176.0056915283203,
157
+ -0.0008069146424531937,
158
+ 89.99847412109375,
159
+ 4.497114658355713
160
+ ]
161
+ ]
162
+ }
bundle/artifacts/sim/pi_policy_preview_3500.gif ADDED

Git LFS Details

  • SHA256: 46533d6029cd763d8001d70b3bf47010a8b54cb75f1fbc71105218da687ef484
  • Pointer size: 131 Bytes
  • Size of remote file: 885 kB
bundle/artifacts/sim/pi_policy_preview_3500_strip.png ADDED

Git LFS Details

  • SHA256: 865bbfd12130f984990b5b268c63f3cb68ec6fb7f9f0aa46f8dd8b71900487e7
  • Pointer size: 132 Bytes
  • Size of remote file: 1.46 MB
bundle/artifacts/sim/pi_rollout_3500.json ADDED
@@ -0,0 +1,3967 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "checkpoint_dir": "/workspace/kinova_scene_sim/staged_checkpoints_3500/3500",
3
+ "session_root": "/workspace/data/teddybear_raw/session_20260327_165944_bear",
4
+ "sync_row_index": 0,
5
+ "azure_rgb_file": "azure_rgb/000010.jpg",
6
+ "wrist_rgb_file": "rgb/000000.jpg",
7
+ "initial_state": [
8
+ 0.13042281568050385,
9
+ 0.0013459887122735381,
10
+ 0.2086409330368042,
11
+ 176.00607299804688,
12
+ -0.0013248149771243334,
13
+ 89.99845886230469,
14
+ 4.80349588394165
15
+ ],
16
+ "states": [
17
+ [
18
+ 0.13042281568050385,
19
+ 0.0013459887122735381,
20
+ 0.2086409330368042,
21
+ 176.00607299804688,
22
+ -0.0013248149771243334,
23
+ 89.99845886230469,
24
+ 4.80349588394165
25
+ ],
26
+ [
27
+ 0.13038688898086548,
28
+ 0.0014187133638188243,
29
+ 0.20857597887516022,
30
+ 176.00660705566406,
31
+ -0.0010383824119344354,
32
+ 89.99771881103516,
33
+ 3.870360851287842
34
+ ],
35
+ [
36
+ 0.13043420016765594,
37
+ 0.0016596653731539845,
38
+ 0.20861729979515076,
39
+ 176.0086669921875,
40
+ -0.0006642318912781775,
41
+ 89.99720001220703,
42
+ 3.328033208847046
43
+ ],
44
+ [
45
+ 0.13064095377922058,
46
+ 0.0016947118565440178,
47
+ 0.20848169922828674,
48
+ 176.00949096679688,
49
+ -0.00016581840463913977,
50
+ 89.99673461914062,
51
+ 4.218804359436035
52
+ ],
53
+ [
54
+ 0.13079629838466644,
55
+ 0.0017693787813186646,
56
+ 0.20835432410240173,
57
+ 176.0095672607422,
58
+ -0.0001273146626772359,
59
+ 89.9961166381836,
60
+ 3.5781540870666504
61
+ ],
62
+ [
63
+ 0.1309470683336258,
64
+ 0.0018013687804341316,
65
+ 0.20847514271736145,
66
+ 176.0099639892578,
67
+ -5.566468462347984e-05,
68
+ 89.99688720703125,
69
+ 2.834836006164551
70
+ ],
71
+ [
72
+ 0.13090649247169495,
73
+ 0.001984028145670891,
74
+ 0.2085830420255661,
75
+ 176.0093536376953,
76
+ 9.991625847760588e-05,
77
+ 89.99685668945312,
78
+ 1.941438913345337
79
+ ],
80
+ [
81
+ 0.1310153752565384,
82
+ 0.0020484186243265867,
83
+ 0.20867235958576202,
84
+ 176.0103759765625,
85
+ 7.498337072320282e-05,
86
+ 89.9969482421875,
87
+ 2.07706880569458
88
+ ],
89
+ [
90
+ 0.13114196062088013,
91
+ 0.0021104831248521805,
92
+ 0.20861603319644928,
93
+ 176.01026916503906,
94
+ 0.0004441899945959449,
95
+ 89.99708557128906,
96
+ 1.6497399806976318
97
+ ],
98
+ [
99
+ 0.1310625970363617,
100
+ 0.002262422349303961,
101
+ 0.2089119255542755,
102
+ 176.0103759765625,
103
+ 0.0006257580826058984,
104
+ 89.99360656738281,
105
+ 1.7586634159088135
106
+ ],
107
+ [
108
+ 0.13105656206607819,
109
+ 0.0023602405562996864,
110
+ 0.20898427069187164,
111
+ 176.01063537597656,
112
+ 0.0006020718137733638,
113
+ 89.9943618774414,
114
+ 2.179922342300415
115
+ ],
116
+ [
117
+ 0.1311476230621338,
118
+ 0.0023023055400699377,
119
+ 0.20911815762519836,
120
+ 176.01226806640625,
121
+ 0.00027950218645855784,
122
+ 89.9934310913086,
123
+ 1.5571088790893555
124
+ ],
125
+ [
126
+ 0.13151052594184875,
127
+ 0.002042755950242281,
128
+ 0.20936307311058044,
129
+ 176.01976013183594,
130
+ 0.00022363767493516207,
131
+ 89.9924545288086,
132
+ 1.3097466230392456
133
+ ],
134
+ [
135
+ 0.1314568668603897,
136
+ 0.0019841394387185574,
137
+ 0.20942673087120056,
138
+ 176.0360870361328,
139
+ 0.0015758902300149202,
140
+ 89.99384307861328,
141
+ 1.5428340435028076
142
+ ],
143
+ [
144
+ 0.13194192945957184,
145
+ 0.0020381570793688297,
146
+ 0.20943905413150787,
147
+ 176.05006408691406,
148
+ 0.0034663670230656862,
149
+ 89.99756622314453,
150
+ 1.0901957750320435
151
+ ],
152
+ [
153
+ 0.13395386934280396,
154
+ 0.0022533698938786983,
155
+ 0.2094932496547699,
156
+ 176.0591278076172,
157
+ 0.00533080380409956,
158
+ 90.00312805175781,
159
+ 1.1050819158554077
160
+ ],
161
+ [
162
+ 0.13620370626449585,
163
+ 0.0022139614447951317,
164
+ 0.20934607088565826,
165
+ 176.06236267089844,
166
+ 0.005754353944212198,
167
+ 90.00737762451172,
168
+ 0.46630996465682983
169
+ ],
170
+ [
171
+ 0.1415129005908966,
172
+ 0.0027319975197315216,
173
+ 0.2093348205089569,
174
+ 176.06459045410156,
175
+ 0.0035483501851558685,
176
+ 90.00851440429688,
177
+ 0.9952843189239502
178
+ ],
179
+ [
180
+ 0.1459393948316574,
181
+ 0.0026647618506103754,
182
+ 0.2093164324760437,
183
+ 176.06600952148438,
184
+ 0.00192162801977247,
185
+ 90.01443481445312,
186
+ 0.44950979948043823
187
+ ],
188
+ [
189
+ 0.14900004863739014,
190
+ 0.002921953797340393,
191
+ 0.20949354767799377,
192
+ 176.06668090820312,
193
+ 0.001516735297627747,
194
+ 90.01408386230469,
195
+ 0.3026089072227478
196
+ ],
197
+ [
198
+ 0.15320706367492676,
199
+ 0.003877518232911825,
200
+ 0.2095641791820526,
201
+ 176.0668487548828,
202
+ -0.001166658359579742,
203
+ 90.01170349121094,
204
+ 0.6711252927780151
205
+ ],
206
+ [
207
+ 0.15570738911628723,
208
+ 0.004031960386782885,
209
+ 0.20950137078762054,
210
+ 176.06748962402344,
211
+ 0.0008320023771375418,
212
+ 90.02385711669922,
213
+ 0.26037225127220154
214
+ ],
215
+ [
216
+ 0.15965940058231354,
217
+ 0.0043397825211286545,
218
+ 0.209621861577034,
219
+ 176.0689239501953,
220
+ -0.0011879531666636467,
221
+ 90.02320098876953,
222
+ 0.6312397122383118
223
+ ],
224
+ [
225
+ 0.1627015769481659,
226
+ 0.004767170641571283,
227
+ 0.20974454283714294,
228
+ 176.0701446533203,
229
+ -0.002045096829533577,
230
+ 90.0233154296875,
231
+ 0.7582746148109436
232
+ ],
233
+ [
234
+ 0.1651243418455124,
235
+ 0.004650649148970842,
236
+ 0.2099265307188034,
237
+ 176.0723419189453,
238
+ -0.0020860014483332634,
239
+ 90.02278900146484,
240
+ 0.6095306873321533
241
+ ]
242
+ ],
243
+ "actions": [
244
+ [
245
+ 0.13038688898086548,
246
+ 0.0014187133638188243,
247
+ 0.20857597887516022,
248
+ 176.00660705566406,
249
+ -0.0010383824119344354,
250
+ 89.99771881103516,
251
+ 3.870360851287842
252
+ ],
253
+ [
254
+ 0.13043420016765594,
255
+ 0.0016596653731539845,
256
+ 0.20861729979515076,
257
+ 176.0086669921875,
258
+ -0.0006642318912781775,
259
+ 89.99720001220703,
260
+ 3.328033208847046
261
+ ],
262
+ [
263
+ 0.13064095377922058,
264
+ 0.0016947118565440178,
265
+ 0.20848169922828674,
266
+ 176.00949096679688,
267
+ -0.00016581840463913977,
268
+ 89.99673461914062,
269
+ 4.218804359436035
270
+ ],
271
+ [
272
+ 0.13079629838466644,
273
+ 0.0017693787813186646,
274
+ 0.20835432410240173,
275
+ 176.0095672607422,
276
+ -0.0001273146626772359,
277
+ 89.9961166381836,
278
+ 3.5781540870666504
279
+ ],
280
+ [
281
+ 0.1309470683336258,
282
+ 0.0018013687804341316,
283
+ 0.20847514271736145,
284
+ 176.0099639892578,
285
+ -5.566468462347984e-05,
286
+ 89.99688720703125,
287
+ 2.834836006164551
288
+ ],
289
+ [
290
+ 0.13090649247169495,
291
+ 0.001984028145670891,
292
+ 0.2085830420255661,
293
+ 176.0093536376953,
294
+ 9.991625847760588e-05,
295
+ 89.99685668945312,
296
+ 1.941438913345337
297
+ ],
298
+ [
299
+ 0.1310153752565384,
300
+ 0.0020484186243265867,
301
+ 0.20867235958576202,
302
+ 176.0103759765625,
303
+ 7.498337072320282e-05,
304
+ 89.9969482421875,
305
+ 2.07706880569458
306
+ ],
307
+ [
308
+ 0.13114196062088013,
309
+ 0.0021104831248521805,
310
+ 0.20861603319644928,
311
+ 176.01026916503906,
312
+ 0.0004441899945959449,
313
+ 89.99708557128906,
314
+ 1.6497399806976318
315
+ ],
316
+ [
317
+ 0.1310625970363617,
318
+ 0.002262422349303961,
319
+ 0.2089119255542755,
320
+ 176.0103759765625,
321
+ 0.0006257580826058984,
322
+ 89.99360656738281,
323
+ 1.7586634159088135
324
+ ],
325
+ [
326
+ 0.13105656206607819,
327
+ 0.0023602405562996864,
328
+ 0.20898427069187164,
329
+ 176.01063537597656,
330
+ 0.0006020718137733638,
331
+ 89.9943618774414,
332
+ 2.179922342300415
333
+ ],
334
+ [
335
+ 0.1311476230621338,
336
+ 0.0023023055400699377,
337
+ 0.20911815762519836,
338
+ 176.01226806640625,
339
+ 0.00027950218645855784,
340
+ 89.9934310913086,
341
+ 1.5571088790893555
342
+ ],
343
+ [
344
+ 0.13151052594184875,
345
+ 0.002042755950242281,
346
+ 0.20936307311058044,
347
+ 176.01976013183594,
348
+ 0.00022363767493516207,
349
+ 89.9924545288086,
350
+ 1.3097466230392456
351
+ ],
352
+ [
353
+ 0.1314568668603897,
354
+ 0.0019841394387185574,
355
+ 0.20942673087120056,
356
+ 176.0360870361328,
357
+ 0.0015758902300149202,
358
+ 89.99384307861328,
359
+ 1.5428340435028076
360
+ ],
361
+ [
362
+ 0.13194192945957184,
363
+ 0.0020381570793688297,
364
+ 0.20943905413150787,
365
+ 176.05006408691406,
366
+ 0.0034663670230656862,
367
+ 89.99756622314453,
368
+ 1.0901957750320435
369
+ ],
370
+ [
371
+ 0.13395386934280396,
372
+ 0.0022533698938786983,
373
+ 0.2094932496547699,
374
+ 176.0591278076172,
375
+ 0.00533080380409956,
376
+ 90.00312805175781,
377
+ 1.1050819158554077
378
+ ],
379
+ [
380
+ 0.13620370626449585,
381
+ 0.0022139614447951317,
382
+ 0.20934607088565826,
383
+ 176.06236267089844,
384
+ 0.005754353944212198,
385
+ 90.00737762451172,
386
+ 0.46630996465682983
387
+ ],
388
+ [
389
+ 0.1415129005908966,
390
+ 0.0027319975197315216,
391
+ 0.2093348205089569,
392
+ 176.06459045410156,
393
+ 0.0035483501851558685,
394
+ 90.00851440429688,
395
+ 0.9952843189239502
396
+ ],
397
+ [
398
+ 0.1459393948316574,
399
+ 0.0026647618506103754,
400
+ 0.2093164324760437,
401
+ 176.06600952148438,
402
+ 0.00192162801977247,
403
+ 90.01443481445312,
404
+ 0.44950979948043823
405
+ ],
406
+ [
407
+ 0.14900004863739014,
408
+ 0.002921953797340393,
409
+ 0.20949354767799377,
410
+ 176.06668090820312,
411
+ 0.001516735297627747,
412
+ 90.01408386230469,
413
+ 0.3026089072227478
414
+ ],
415
+ [
416
+ 0.15320706367492676,
417
+ 0.003877518232911825,
418
+ 0.2095641791820526,
419
+ 176.0668487548828,
420
+ -0.001166658359579742,
421
+ 90.01170349121094,
422
+ 0.6711252927780151
423
+ ],
424
+ [
425
+ 0.15570738911628723,
426
+ 0.004031960386782885,
427
+ 0.20950137078762054,
428
+ 176.06748962402344,
429
+ 0.0008320023771375418,
430
+ 90.02385711669922,
431
+ 0.26037225127220154
432
+ ],
433
+ [
434
+ 0.15965940058231354,
435
+ 0.0043397825211286545,
436
+ 0.209621861577034,
437
+ 176.0689239501953,
438
+ -0.0011879531666636467,
439
+ 90.02320098876953,
440
+ 0.6312397122383118
441
+ ],
442
+ [
443
+ 0.1627015769481659,
444
+ 0.004767170641571283,
445
+ 0.20974454283714294,
446
+ 176.0701446533203,
447
+ -0.002045096829533577,
448
+ 90.0233154296875,
449
+ 0.7582746148109436
450
+ ],
451
+ [
452
+ 0.1651243418455124,
453
+ 0.004650649148970842,
454
+ 0.2099265307188034,
455
+ 176.0723419189453,
456
+ -0.0020860014483332634,
457
+ 90.02278900146484,
458
+ 0.6095306873321533
459
+ ]
460
+ ],
461
+ "chunks": [
462
+ [
463
+ [
464
+ 0.13038688898086548,
465
+ 0.0014187133638188243,
466
+ 0.20857597887516022,
467
+ 176.00660705566406,
468
+ -0.0010383824119344354,
469
+ 89.99771881103516,
470
+ 3.870360851287842
471
+ ],
472
+ [
473
+ 0.1302502304315567,
474
+ 0.0013153755571693182,
475
+ 0.20861351490020752,
476
+ 176.0064697265625,
477
+ -0.0011160902213305235,
478
+ 89.99806213378906,
479
+ 3.690521240234375
480
+ ],
481
+ [
482
+ 0.13023793697357178,
483
+ 0.0012819102266803384,
484
+ 0.20857881009578705,
485
+ 176.0062713623047,
486
+ -0.0012181210331618786,
487
+ 89.99817657470703,
488
+ 3.651444911956787
489
+ ],
490
+ [
491
+ 0.13030986487865448,
492
+ 0.0013734204694628716,
493
+ 0.20860803127288818,
494
+ 176.0064239501953,
495
+ -0.0014578866539523005,
496
+ 89.99809265136719,
497
+ 3.6906394958496094
498
+ ],
499
+ [
500
+ 0.1302148997783661,
501
+ 0.0013296795077621937,
502
+ 0.20862483978271484,
503
+ 176.0063934326172,
504
+ -0.0012297590728849173,
505
+ 89.9979476928711,
506
+ 3.66821551322937
507
+ ],
508
+ [
509
+ 0.13030855357646942,
510
+ 0.0012651914730668068,
511
+ 0.20867392420768738,
512
+ 176.00656127929688,
513
+ -0.001598228933289647,
514
+ 89.99803161621094,
515
+ 3.754732847213745
516
+ ],
517
+ [
518
+ 0.13031162321567535,
519
+ 0.0012794281356036663,
520
+ 0.20865340530872345,
521
+ 176.00653076171875,
522
+ -0.0015227764379233122,
523
+ 89.99803924560547,
524
+ 3.8800547122955322
525
+ ],
526
+ [
527
+ 0.13022325932979584,
528
+ 0.0012262801174074411,
529
+ 0.20850715041160583,
530
+ 176.006103515625,
531
+ -0.0012301492970436811,
532
+ 89.99808502197266,
533
+ 4.038285732269287
534
+ ],
535
+ [
536
+ 0.13038043677806854,
537
+ 0.001231524394825101,
538
+ 0.20850330591201782,
539
+ 176.00624084472656,
540
+ -0.0012325852876529098,
541
+ 89.9980697631836,
542
+ 4.302825927734375
543
+ ],
544
+ [
545
+ 0.13038581609725952,
546
+ 0.001150989904999733,
547
+ 0.20857061445713043,
548
+ 176.0060577392578,
549
+ -0.0012798609677702188,
550
+ 89.9980239868164,
551
+ 4.259771347045898
552
+ ],
553
+ [
554
+ 0.13041627407073975,
555
+ 0.0011642909375950694,
556
+ 0.20851978659629822,
557
+ 176.006103515625,
558
+ -0.0012036851840093732,
559
+ 89.99813842773438,
560
+ 4.265687465667725
561
+ ],
562
+ [
563
+ 0.13035060465335846,
564
+ 0.0012715674238279462,
565
+ 0.20847438275814056,
566
+ 176.00587463378906,
567
+ -0.0015258120838552713,
568
+ 89.99850463867188,
569
+ 4.377945423126221
570
+ ],
571
+ [
572
+ 0.1303417980670929,
573
+ 0.0012600033078342676,
574
+ 0.2084597498178482,
575
+ 176.0060272216797,
576
+ -0.0009475614642724395,
577
+ 89.99833679199219,
578
+ 4.183290481567383
579
+ ],
580
+ [
581
+ 0.1304168999195099,
582
+ 0.0011939689284190536,
583
+ 0.20853134989738464,
584
+ 176.0057830810547,
585
+ -0.0013050022535026073,
586
+ 89.99844360351562,
587
+ 4.19566011428833
588
+ ],
589
+ [
590
+ 0.1303562968969345,
591
+ 0.0012072586687281728,
592
+ 0.20855338871479034,
593
+ 176.00575256347656,
594
+ -0.000863268505781889,
595
+ 89.99850463867188,
596
+ 4.2605509757995605
597
+ ],
598
+ [
599
+ 0.1303006112575531,
600
+ 0.0012522602919489145,
601
+ 0.2085985243320465,
602
+ 176.0056915283203,
603
+ -0.0008069146424531937,
604
+ 89.99847412109375,
605
+ 4.497114658355713
606
+ ]
607
+ ],
608
+ [
609
+ [
610
+ 0.13043420016765594,
611
+ 0.0016596653731539845,
612
+ 0.20861729979515076,
613
+ 176.0086669921875,
614
+ -0.0006642318912781775,
615
+ 89.99720001220703,
616
+ 3.328033208847046
617
+ ],
618
+ [
619
+ 0.1304139941930771,
620
+ 0.0017380370991304517,
621
+ 0.20870471000671387,
622
+ 176.00819396972656,
623
+ -0.00017333835421595722,
624
+ 89.99736785888672,
625
+ 3.3828375339508057
626
+ ],
627
+ [
628
+ 0.1303291618824005,
629
+ 0.0016114477766677737,
630
+ 0.20845387876033783,
631
+ 176.0089569091797,
632
+ -0.0009894894901663065,
633
+ 89.99771118164062,
634
+ 3.255220651626587
635
+ ],
636
+ [
637
+ 0.13032270967960358,
638
+ 0.0016015756409615278,
639
+ 0.20840081572532654,
640
+ 176.00868225097656,
641
+ -0.001061268849298358,
642
+ 89.99730682373047,
643
+ 3.231813430786133
644
+ ],
645
+ [
646
+ 0.13036927580833435,
647
+ 0.0014416162157431245,
648
+ 0.20839662849903107,
649
+ 176.00863647460938,
650
+ -0.0007507895934395492,
651
+ 89.99756622314453,
652
+ 3.0640480518341064
653
+ ],
654
+ [
655
+ 0.13038352131843567,
656
+ 0.0017369053093716502,
657
+ 0.20851343870162964,
658
+ 176.0083465576172,
659
+ -0.0008427334250882268,
660
+ 89.9976806640625,
661
+ 2.7776923179626465
662
+ ],
663
+ [
664
+ 0.130374938249588,
665
+ 0.001516032381914556,
666
+ 0.2085302770137787,
667
+ 176.00863647460938,
668
+ -0.0011493967613205314,
669
+ 89.99757385253906,
670
+ 2.808537006378174
671
+ ],
672
+ [
673
+ 0.13043144345283508,
674
+ 0.001582918455824256,
675
+ 0.20852799713611603,
676
+ 176.00869750976562,
677
+ -0.000853752950206399,
678
+ 89.99739074707031,
679
+ 2.620037317276001
680
+ ],
681
+ [
682
+ 0.13045990467071533,
683
+ 0.0014022847171872854,
684
+ 0.20849116146564484,
685
+ 176.0091094970703,
686
+ -0.001233889488503337,
687
+ 89.99779510498047,
688
+ 2.669640302658081
689
+ ],
690
+ [
691
+ 0.1303248256444931,
692
+ 0.0014256987487897277,
693
+ 0.2084859311580658,
694
+ 176.00872802734375,
695
+ -0.0007936973706819117,
696
+ 89.99757385253906,
697
+ 2.7151496410369873
698
+ ],
699
+ [
700
+ 0.13034434616565704,
701
+ 0.0014580099377781153,
702
+ 0.20850197970867157,
703
+ 176.0086212158203,
704
+ -0.0008582730661146343,
705
+ 89.99765014648438,
706
+ 2.4230668544769287
707
+ ],
708
+ [
709
+ 0.13033334910869598,
710
+ 0.001468123053200543,
711
+ 0.20849834382534027,
712
+ 176.00881958007812,
713
+ -0.0007506563561037183,
714
+ 89.99785614013672,
715
+ 2.4433109760284424
716
+ ],
717
+ [
718
+ 0.1304265856742859,
719
+ 0.0015017733676359057,
720
+ 0.2084486335515976,
721
+ 176.00889587402344,
722
+ -0.0007904047961346805,
723
+ 89.99774932861328,
724
+ 2.1915478706359863
725
+ ],
726
+ [
727
+ 0.13039429485797882,
728
+ 0.001430780510418117,
729
+ 0.20852449536323547,
730
+ 176.00917053222656,
731
+ -0.000892863841727376,
732
+ 89.99761199951172,
733
+ 2.408724069595337
734
+ ],
735
+ [
736
+ 0.13038116693496704,
737
+ 0.001403976697474718,
738
+ 0.20847949385643005,
739
+ 176.00889587402344,
740
+ -0.0008508600876666605,
741
+ 89.99790954589844,
742
+ 2.461463689804077
743
+ ],
744
+ [
745
+ 0.13030168414115906,
746
+ 0.0013514338061213493,
747
+ 0.2085845023393631,
748
+ 176.0089569091797,
749
+ -0.0007433861610479653,
750
+ 89.99764251708984,
751
+ 2.468567132949829
752
+ ]
753
+ ],
754
+ [
755
+ [
756
+ 0.13064095377922058,
757
+ 0.0016947118565440178,
758
+ 0.20848169922828674,
759
+ 176.00949096679688,
760
+ -0.00016581840463913977,
761
+ 89.99673461914062,
762
+ 4.218804359436035
763
+ ],
764
+ [
765
+ 0.1306656301021576,
766
+ 0.001803360995836556,
767
+ 0.20845556259155273,
768
+ 176.0099639892578,
769
+ -0.0004244258161634207,
770
+ 89.99695587158203,
771
+ 4.156636714935303
772
+ ],
773
+ [
774
+ 0.13070720434188843,
775
+ 0.0018559599993750453,
776
+ 0.20850147306919098,
777
+ 176.0098419189453,
778
+ -0.0005103364819660783,
779
+ 89.99713134765625,
780
+ 4.380053997039795
781
+ ],
782
+ [
783
+ 0.13052570819854736,
784
+ 0.0018253352027386427,
785
+ 0.20836898684501648,
786
+ 176.0098419189453,
787
+ -0.0006624595844186842,
788
+ 89.99700164794922,
789
+ 4.376288414001465
790
+ ],
791
+ [
792
+ 0.13039222359657288,
793
+ 0.0015040939906612039,
794
+ 0.20878161489963531,
795
+ 176.01002502441406,
796
+ -0.0005345261888578534,
797
+ 89.99716186523438,
798
+ 4.6692986488342285
799
+ ],
800
+ [
801
+ 0.13047470152378082,
802
+ 0.0017413381719961762,
803
+ 0.20889818668365479,
804
+ 176.010498046875,
805
+ -0.0004075253673363477,
806
+ 89.99696350097656,
807
+ 4.750035285949707
808
+ ],
809
+ [
810
+ 0.13063737750053406,
811
+ 0.0015569338575005531,
812
+ 0.20856650173664093,
813
+ 176.01034545898438,
814
+ -0.0009047851199284196,
815
+ 89.99739074707031,
816
+ 4.462838172912598
817
+ ],
818
+ [
819
+ 0.13045653700828552,
820
+ 0.0014287366066128016,
821
+ 0.20865672826766968,
822
+ 176.00982666015625,
823
+ -0.0005488002207130194,
824
+ 89.99681091308594,
825
+ 4.558866024017334
826
+ ],
827
+ [
828
+ 0.1306876540184021,
829
+ 0.001681859022937715,
830
+ 0.20862530171871185,
831
+ 176.0103302001953,
832
+ -0.0005408638389781117,
833
+ 89.99718475341797,
834
+ 4.885012626647949
835
+ ],
836
+ [
837
+ 0.13046996295452118,
838
+ 0.0018679274944588542,
839
+ 0.20882092416286469,
840
+ 176.00994873046875,
841
+ -0.0004903528024442494,
842
+ 89.99720764160156,
843
+ 4.507809638977051
844
+ ],
845
+ [
846
+ 0.13079078495502472,
847
+ 0.0016777466516941786,
848
+ 0.20873045921325684,
849
+ 176.00924682617188,
850
+ 0.00021807696612086147,
851
+ 89.99684143066406,
852
+ 4.9376373291015625
853
+ ],
854
+ [
855
+ 0.130674809217453,
856
+ 0.001853483496233821,
857
+ 0.20840691030025482,
858
+ 176.00921630859375,
859
+ 0.00014381392975337803,
860
+ 89.9966812133789,
861
+ 4.486833095550537
862
+ ],
863
+ [
864
+ 0.13063739240169525,
865
+ 0.001660753390751779,
866
+ 0.20858752727508545,
867
+ 176.0089569091797,
868
+ 1.834879299167369e-06,
869
+ 89.99697875976562,
870
+ 4.827036380767822
871
+ ],
872
+ [
873
+ 0.13051098585128784,
874
+ 0.0016984489047899842,
875
+ 0.208602637052536,
876
+ 176.0093994140625,
877
+ -8.295287989312783e-05,
878
+ 89.9972152709961,
879
+ 4.797352313995361
880
+ ],
881
+ [
882
+ 0.13057023286819458,
883
+ 0.0015257655177265406,
884
+ 0.2086484283208847,
885
+ 176.0095977783203,
886
+ -0.00019454726134426892,
887
+ 89.99728393554688,
888
+ 4.569445610046387
889
+ ],
890
+ [
891
+ 0.13049821555614471,
892
+ 0.001634918968193233,
893
+ 0.20886337757110596,
894
+ 176.00965881347656,
895
+ -0.000377635529730469,
896
+ 89.9977035522461,
897
+ 4.487051486968994
898
+ ]
899
+ ],
900
+ [
901
+ [
902
+ 0.13079629838466644,
903
+ 0.0017693787813186646,
904
+ 0.20835432410240173,
905
+ 176.0095672607422,
906
+ -0.0001273146626772359,
907
+ 89.9961166381836,
908
+ 3.5781540870666504
909
+ ],
910
+ [
911
+ 0.13059517741203308,
912
+ 0.0016042535426095128,
913
+ 0.20844927430152893,
914
+ 176.0094757080078,
915
+ -9.113474516198039e-05,
916
+ 89.99629974365234,
917
+ 3.5728580951690674
918
+ ],
919
+ [
920
+ 0.1305704563856125,
921
+ 0.0016339595895260572,
922
+ 0.20854619145393372,
923
+ 176.0096893310547,
924
+ -0.00019901788618881255,
925
+ 89.99674224853516,
926
+ 3.449205160140991
927
+ ],
928
+ [
929
+ 0.1305752545595169,
930
+ 0.001851420383900404,
931
+ 0.20864161849021912,
932
+ 176.00965881347656,
933
+ -9.652081644162536e-05,
934
+ 89.996826171875,
935
+ 3.4286983013153076
936
+ ],
937
+ [
938
+ 0.13053040206432343,
939
+ 0.0018075169064104557,
940
+ 0.2086752951145172,
941
+ 176.00955200195312,
942
+ -0.00028139809728600085,
943
+ 89.99659729003906,
944
+ 3.219998836517334
945
+ ],
946
+ [
947
+ 0.13060849905014038,
948
+ 0.001731313532218337,
949
+ 0.20848137140274048,
950
+ 176.00904846191406,
951
+ -0.000442685151938349,
952
+ 89.99694061279297,
953
+ 3.2834484577178955
954
+ ],
955
+ [
956
+ 0.13063274323940277,
957
+ 0.0016856620786711574,
958
+ 0.20840498805046082,
959
+ 176.00949096679688,
960
+ -0.0005296520539559424,
961
+ 89.99668884277344,
962
+ 3.234495162963867
963
+ ],
964
+ [
965
+ 0.1308305859565735,
966
+ 0.0017480265814810991,
967
+ 0.2083055078983307,
968
+ 176.0096435546875,
969
+ -0.00025680867838673294,
970
+ 89.99659729003906,
971
+ 3.2613022327423096
972
+ ],
973
+ [
974
+ 0.13056963682174683,
975
+ 0.0017820186913013458,
976
+ 0.20845040678977966,
977
+ 176.00946044921875,
978
+ -0.00040342204738408327,
979
+ 89.9967269897461,
980
+ 3.3895716667175293
981
+ ],
982
+ [
983
+ 0.13065794110298157,
984
+ 0.0015162450727075338,
985
+ 0.20849759876728058,
986
+ 176.00912475585938,
987
+ -0.00039509552880190313,
988
+ 89.99674224853516,
989
+ 3.229161024093628
990
+ ],
991
+ [
992
+ 0.13065195083618164,
993
+ 0.0016540735960006714,
994
+ 0.20853367447853088,
995
+ 176.009033203125,
996
+ -0.0003080239112023264,
997
+ 89.99667358398438,
998
+ 3.134122610092163
999
+ ],
1000
+ [
1001
+ 0.13061147928237915,
1002
+ 0.001768062124028802,
1003
+ 0.2086455225944519,
1004
+ 176.0088348388672,
1005
+ -4.922618609271012e-05,
1006
+ 89.99713134765625,
1007
+ 3.056776285171509
1008
+ ],
1009
+ [
1010
+ 0.13046883046627045,
1011
+ 0.001975113060325384,
1012
+ 0.20840057730674744,
1013
+ 176.00938415527344,
1014
+ -0.00021784058480989188,
1015
+ 89.99690246582031,
1016
+ 3.0827386379241943
1017
+ ],
1018
+ [
1019
+ 0.13062995672225952,
1020
+ 0.001725139212794602,
1021
+ 0.20852205157279968,
1022
+ 176.0091094970703,
1023
+ -0.00044183823047205806,
1024
+ 89.99711608886719,
1025
+ 2.915327787399292
1026
+ ],
1027
+ [
1028
+ 0.13046248257160187,
1029
+ 0.0016581580275669694,
1030
+ 0.20843657851219177,
1031
+ 176.0091094970703,
1032
+ -0.00010100286453962326,
1033
+ 89.99694061279297,
1034
+ 3.080239772796631
1035
+ ],
1036
+ [
1037
+ 0.1306220293045044,
1038
+ 0.0016375004779547453,
1039
+ 0.20845238864421844,
1040
+ 176.00936889648438,
1041
+ -0.00038476113695651293,
1042
+ 89.99683380126953,
1043
+ 3.1575357913970947
1044
+ ]
1045
+ ],
1046
+ [
1047
+ [
1048
+ 0.1309470683336258,
1049
+ 0.0018013687804341316,
1050
+ 0.20847514271736145,
1051
+ 176.0099639892578,
1052
+ -5.566468462347984e-05,
1053
+ 89.99688720703125,
1054
+ 2.834836006164551
1055
+ ],
1056
+ [
1057
+ 0.13086992502212524,
1058
+ 0.0018532057292759418,
1059
+ 0.20829977095127106,
1060
+ 176.0097198486328,
1061
+ 6.503488293674309e-06,
1062
+ 89.99710845947266,
1063
+ 2.8121700286865234
1064
+ ],
1065
+ [
1066
+ 0.1309582144021988,
1067
+ 0.0019378525903448462,
1068
+ 0.20837600529193878,
1069
+ 176.01034545898438,
1070
+ -9.392861102242023e-05,
1071
+ 89.99722290039062,
1072
+ 2.6752877235412598
1073
+ ],
1074
+ [
1075
+ 0.1308731883764267,
1076
+ 0.0018537212163209915,
1077
+ 0.2083592563867569,
1078
+ 176.01026916503906,
1079
+ 2.4707638658583164e-05,
1080
+ 89.99707794189453,
1081
+ 2.7936744689941406
1082
+ ],
1083
+ [
1084
+ 0.13076193630695343,
1085
+ 0.0019365751650184393,
1086
+ 0.20833690464496613,
1087
+ 176.0100555419922,
1088
+ -0.0002790532889775932,
1089
+ 89.99759674072266,
1090
+ 2.7987899780273438
1091
+ ],
1092
+ [
1093
+ 0.13091255724430084,
1094
+ 0.001872793072834611,
1095
+ 0.20840522646903992,
1096
+ 176.010498046875,
1097
+ -0.0003105513460468501,
1098
+ 89.9974365234375,
1099
+ 2.7447566986083984
1100
+ ],
1101
+ [
1102
+ 0.13093999028205872,
1103
+ 0.001893708249554038,
1104
+ 0.20825980603694916,
1105
+ 176.0099334716797,
1106
+ -0.00030471800710074604,
1107
+ 89.99781799316406,
1108
+ 2.7550971508026123
1109
+ ],
1110
+ [
1111
+ 0.13093437254428864,
1112
+ 0.0019456628942862153,
1113
+ 0.20832644402980804,
1114
+ 176.01016235351562,
1115
+ -0.00023496556968893856,
1116
+ 89.99756622314453,
1117
+ 2.7730345726013184
1118
+ ],
1119
+ [
1120
+ 0.13092423975467682,
1121
+ 0.0020397615153342485,
1122
+ 0.2084275335073471,
1123
+ 176.01026916503906,
1124
+ -0.0002566525945439935,
1125
+ 89.9975357055664,
1126
+ 2.5209200382232666
1127
+ ],
1128
+ [
1129
+ 0.13100875914096832,
1130
+ 0.0019944070372730494,
1131
+ 0.2083629071712494,
1132
+ 176.01034545898438,
1133
+ -0.0001990045275306329,
1134
+ 89.99735260009766,
1135
+ 2.650731325149536
1136
+ ],
1137
+ [
1138
+ 0.13095593452453613,
1139
+ 0.002013490069657564,
1140
+ 0.2083655595779419,
1141
+ 176.01016235351562,
1142
+ -0.00017864975961856544,
1143
+ 89.9977035522461,
1144
+ 2.569013833999634
1145
+ ],
1146
+ [
1147
+ 0.13101328909397125,
1148
+ 0.0019990126602351665,
1149
+ 0.20823514461517334,
1150
+ 176.01010131835938,
1151
+ -0.00026424636598676443,
1152
+ 89.99768829345703,
1153
+ 2.4885218143463135
1154
+ ],
1155
+ [
1156
+ 0.13076332211494446,
1157
+ 0.0019358580466359854,
1158
+ 0.20832638442516327,
1159
+ 176.00991821289062,
1160
+ -0.000250067503657192,
1161
+ 89.997802734375,
1162
+ 2.43973708152771
1163
+ ],
1164
+ [
1165
+ 0.13072161376476288,
1166
+ 0.0019465481163933873,
1167
+ 0.2083868682384491,
1168
+ 176.01014709472656,
1169
+ -0.0002342328371014446,
1170
+ 89.99793243408203,
1171
+ 2.4526679515838623
1172
+ ],
1173
+ [
1174
+ 0.1308751255273819,
1175
+ 0.0019334263633936644,
1176
+ 0.20822517573833466,
1177
+ 176.00994873046875,
1178
+ 7.753107638563961e-05,
1179
+ 89.99749755859375,
1180
+ 2.44692325592041
1181
+ ],
1182
+ [
1183
+ 0.13067835569381714,
1184
+ 0.0019546665716916323,
1185
+ 0.20831240713596344,
1186
+ 176.01031494140625,
1187
+ 2.4184257199522108e-05,
1188
+ 89.99747467041016,
1189
+ 2.4973621368408203
1190
+ ]
1191
+ ],
1192
+ [
1193
+ [
1194
+ 0.13090649247169495,
1195
+ 0.001984028145670891,
1196
+ 0.2085830420255661,
1197
+ 176.0093536376953,
1198
+ 9.991625847760588e-05,
1199
+ 89.99685668945312,
1200
+ 1.941438913345337
1201
+ ],
1202
+ [
1203
+ 0.13102982938289642,
1204
+ 0.0018029181519523263,
1205
+ 0.20834685862064362,
1206
+ 176.0104522705078,
1207
+ -4.0416514821117744e-05,
1208
+ 89.99724578857422,
1209
+ 1.6200621128082275
1210
+ ],
1211
+ [
1212
+ 0.13095532357692719,
1213
+ 0.001849398948252201,
1214
+ 0.20848429203033447,
1215
+ 176.00917053222656,
1216
+ -6.39401187072508e-05,
1217
+ 89.99720764160156,
1218
+ 1.4195177555084229
1219
+ ],
1220
+ [
1221
+ 0.13094648718833923,
1222
+ 0.0017738454043865204,
1223
+ 0.208510622382164,
1224
+ 176.009521484375,
1225
+ 0.00015144552162382752,
1226
+ 89.99703979492188,
1227
+ 1.3772574663162231
1228
+ ],
1229
+ [
1230
+ 0.13099123537540436,
1231
+ 0.0018878227565437555,
1232
+ 0.20841747522354126,
1233
+ 176.00897216796875,
1234
+ -3.019630821654573e-05,
1235
+ 89.99641418457031,
1236
+ 1.4022036790847778
1237
+ ],
1238
+ [
1239
+ 0.13093942403793335,
1240
+ 0.0018786005675792694,
1241
+ 0.20844319462776184,
1242
+ 176.00914001464844,
1243
+ -0.00021176200243644416,
1244
+ 89.99645233154297,
1245
+ 1.614084005355835
1246
+ ],
1247
+ [
1248
+ 0.13120214641094208,
1249
+ 0.002075829776003957,
1250
+ 0.20798411965370178,
1251
+ 176.01113891601562,
1252
+ -0.00014000169176142663,
1253
+ 89.99726104736328,
1254
+ 1.4516884088516235
1255
+ ],
1256
+ [
1257
+ 0.1308683156967163,
1258
+ 0.0017220252193510532,
1259
+ 0.20816221833229065,
1260
+ 176.0096435546875,
1261
+ 0.00015574676217511296,
1262
+ 89.9964599609375,
1263
+ 1.5608067512512207
1264
+ ],
1265
+ [
1266
+ 0.1312122941017151,
1267
+ 0.0016933893784880638,
1268
+ 0.20803521573543549,
1269
+ 176.0125274658203,
1270
+ 0.0006242776289582253,
1271
+ 89.99784851074219,
1272
+ 1.6075034141540527
1273
+ ],
1274
+ [
1275
+ 0.13122178614139557,
1276
+ 0.0018606605008244514,
1277
+ 0.2081458568572998,
1278
+ 176.01385498046875,
1279
+ 0.0012434185482561588,
1280
+ 89.99808502197266,
1281
+ 1.813157558441162
1282
+ ],
1283
+ [
1284
+ 0.13137872517108917,
1285
+ 0.0017731842817738652,
1286
+ 0.20800799131393433,
1287
+ 176.01950073242188,
1288
+ 0.00288543663918972,
1289
+ 90.00159454345703,
1290
+ 1.6650338172912598
1291
+ ],
1292
+ [
1293
+ 0.13223792612552643,
1294
+ 0.0018986474024131894,
1295
+ 0.20766764879226685,
1296
+ 176.03329467773438,
1297
+ 0.005975669715553522,
1298
+ 90.0083236694336,
1299
+ 1.5360052585601807
1300
+ ],
1301
+ [
1302
+ 0.13343384861946106,
1303
+ 0.0024412712082266808,
1304
+ 0.20748776197433472,
1305
+ 176.0392608642578,
1306
+ 0.0074739959090948105,
1307
+ 90.01441192626953,
1308
+ 1.66856050491333
1309
+ ],
1310
+ [
1311
+ 0.13599742949008942,
1312
+ 0.0029446028638631105,
1313
+ 0.20740990340709686,
1314
+ 176.04579162597656,
1315
+ 0.008425360545516014,
1316
+ 90.01947021484375,
1317
+ 1.485578179359436
1318
+ ],
1319
+ [
1320
+ 0.13709905743598938,
1321
+ 0.0027356415521353483,
1322
+ 0.20741921663284302,
1323
+ 176.04534912109375,
1324
+ 0.00825597532093525,
1325
+ 90.02092742919922,
1326
+ 1.7326006889343262
1327
+ ],
1328
+ [
1329
+ 0.1390867829322815,
1330
+ 0.0033203703351318836,
1331
+ 0.20680299401283264,
1332
+ 176.04812622070312,
1333
+ 0.008466346189379692,
1334
+ 90.02267456054688,
1335
+ 1.9710044860839844
1336
+ ]
1337
+ ],
1338
+ [
1339
+ [
1340
+ 0.1310153752565384,
1341
+ 0.0020484186243265867,
1342
+ 0.20867235958576202,
1343
+ 176.0103759765625,
1344
+ 7.498337072320282e-05,
1345
+ 89.9969482421875,
1346
+ 2.07706880569458
1347
+ ],
1348
+ [
1349
+ 0.13092337548732758,
1350
+ 0.0018737518694251776,
1351
+ 0.20856735110282898,
1352
+ 176.010009765625,
1353
+ 0.00011865239503094926,
1354
+ 89.99681091308594,
1355
+ 1.917245864868164
1356
+ ],
1357
+ [
1358
+ 0.130991593003273,
1359
+ 0.00198960630223155,
1360
+ 0.2085607498884201,
1361
+ 176.01026916503906,
1362
+ 0.00019225882715545595,
1363
+ 89.99650573730469,
1364
+ 1.9162652492523193
1365
+ ],
1366
+ [
1367
+ 0.1310150921344757,
1368
+ 0.0018965776544064283,
1369
+ 0.208579882979393,
1370
+ 176.0106201171875,
1371
+ -0.00027957410202361643,
1372
+ 89.99689483642578,
1373
+ 1.9838823080062866
1374
+ ],
1375
+ [
1376
+ 0.13119368255138397,
1377
+ 0.0018855177331715822,
1378
+ 0.20855091512203217,
1379
+ 176.010986328125,
1380
+ -0.0001178017191705294,
1381
+ 89.99691772460938,
1382
+ 1.8703395128250122
1383
+ ],
1384
+ [
1385
+ 0.13115344941616058,
1386
+ 0.0018607029924169183,
1387
+ 0.20874591171741486,
1388
+ 176.01052856445312,
1389
+ 0.00029900955269113183,
1390
+ 89.996826171875,
1391
+ 1.8201812505722046
1392
+ ],
1393
+ [
1394
+ 0.13113023340702057,
1395
+ 0.001892806962132454,
1396
+ 0.20860904455184937,
1397
+ 176.0105743408203,
1398
+ 8.683081978233531e-05,
1399
+ 89.99661254882812,
1400
+ 2.000239372253418
1401
+ ],
1402
+ [
1403
+ 0.13118015229701996,
1404
+ 0.0017588331829756498,
1405
+ 0.2086266428232193,
1406
+ 176.010498046875,
1407
+ -2.1451996872201562e-05,
1408
+ 89.99728393554688,
1409
+ 1.9351180791854858
1410
+ ],
1411
+ [
1412
+ 0.1312001347541809,
1413
+ 0.0018659919733181596,
1414
+ 0.20840662717819214,
1415
+ 176.01028442382812,
1416
+ 0.00010130468581337482,
1417
+ 89.99685668945312,
1418
+ 1.8629496097564697
1419
+ ],
1420
+ [
1421
+ 0.1310989409685135,
1422
+ 0.0015936631243675947,
1423
+ 0.2084645926952362,
1424
+ 176.010498046875,
1425
+ 0.0006172824068926275,
1426
+ 89.9972915649414,
1427
+ 2.1598763465881348
1428
+ ],
1429
+ [
1430
+ 0.13108214735984802,
1431
+ 0.0018113537225872278,
1432
+ 0.2086448222398758,
1433
+ 176.01040649414062,
1434
+ 0.0003828266926575452,
1435
+ 89.99705505371094,
1436
+ 2.1688787937164307
1437
+ ],
1438
+ [
1439
+ 0.1310548633337021,
1440
+ 0.0018182842759415507,
1441
+ 0.20859386026859283,
1442
+ 176.00999450683594,
1443
+ 0.0004258961998857558,
1444
+ 89.99716186523438,
1445
+ 2.1696231365203857
1446
+ ],
1447
+ [
1448
+ 0.1311027705669403,
1449
+ 0.001982384128496051,
1450
+ 0.20858445763587952,
1451
+ 176.01034545898438,
1452
+ 0.00016298754781018943,
1453
+ 89.99734497070312,
1454
+ 1.8949785232543945
1455
+ ],
1456
+ [
1457
+ 0.13124389946460724,
1458
+ 0.0017660831799730659,
1459
+ 0.20863954722881317,
1460
+ 176.01083374023438,
1461
+ 0.000130452259327285,
1462
+ 89.99725341796875,
1463
+ 1.879557728767395
1464
+ ],
1465
+ [
1466
+ 0.13118857145309448,
1467
+ 0.0017727112863212824,
1468
+ 0.20860184729099274,
1469
+ 176.01019287109375,
1470
+ 0.0004007643728982657,
1471
+ 89.99736785888672,
1472
+ 1.8223551511764526
1473
+ ],
1474
+ [
1475
+ 0.13120853900909424,
1476
+ 0.0015657893382012844,
1477
+ 0.20854398608207703,
1478
+ 176.0104522705078,
1479
+ 0.00038481553201563656,
1480
+ 89.99765014648438,
1481
+ 1.910325527191162
1482
+ ]
1483
+ ],
1484
+ [
1485
+ [
1486
+ 0.13114196062088013,
1487
+ 0.0021104831248521805,
1488
+ 0.20861603319644928,
1489
+ 176.01026916503906,
1490
+ 0.0004441899945959449,
1491
+ 89.99708557128906,
1492
+ 1.6497399806976318
1493
+ ],
1494
+ [
1495
+ 0.13090406358242035,
1496
+ 0.002218476962298155,
1497
+ 0.20861291885375977,
1498
+ 176.01036071777344,
1499
+ 0.0002968629414681345,
1500
+ 89.99708557128906,
1501
+ 1.4398622512817383
1502
+ ],
1503
+ [
1504
+ 0.1310281753540039,
1505
+ 0.002308339811861515,
1506
+ 0.2088124006986618,
1507
+ 176.0106964111328,
1508
+ 0.00045930143096484244,
1509
+ 89.99696350097656,
1510
+ 1.4085657596588135
1511
+ ],
1512
+ [
1513
+ 0.13102607429027557,
1514
+ 0.002101524267345667,
1515
+ 0.20869089663028717,
1516
+ 176.0106964111328,
1517
+ 0.00022399875160772353,
1518
+ 89.99706268310547,
1519
+ 1.4397765398025513
1520
+ ],
1521
+ [
1522
+ 0.13104389607906342,
1523
+ 0.0021394945215433836,
1524
+ 0.20860609412193298,
1525
+ 176.01100158691406,
1526
+ 0.000244353519519791,
1527
+ 89.99737548828125,
1528
+ 1.3889714479446411
1529
+ ],
1530
+ [
1531
+ 0.131087988615036,
1532
+ 0.002020082203671336,
1533
+ 0.20863638818264008,
1534
+ 176.01051330566406,
1535
+ 0.0002665068313945085,
1536
+ 89.99739074707031,
1537
+ 1.5445796251296997
1538
+ ],
1539
+ [
1540
+ 0.13116620481014252,
1541
+ 0.0020494465716183186,
1542
+ 0.20854100584983826,
1543
+ 176.01097106933594,
1544
+ 0.00017326883971691132,
1545
+ 89.99750518798828,
1546
+ 1.3476030826568604
1547
+ ],
1548
+ [
1549
+ 0.13109587132930756,
1550
+ 0.001901152078062296,
1551
+ 0.20862379670143127,
1552
+ 176.01075744628906,
1553
+ 0.0002977764524985105,
1554
+ 89.9974594116211,
1555
+ 1.5078661441802979
1556
+ ],
1557
+ [
1558
+ 0.13117161393165588,
1559
+ 0.0020071063190698624,
1560
+ 0.20859237015247345,
1561
+ 176.01097106933594,
1562
+ 5.3519212087849155e-05,
1563
+ 89.99737548828125,
1564
+ 1.649208426475525
1565
+ ],
1566
+ [
1567
+ 0.131106436252594,
1568
+ 0.0020802058279514313,
1569
+ 0.20880235731601715,
1570
+ 176.01036071777344,
1571
+ -3.4542055800557137e-05,
1572
+ 89.9973373413086,
1573
+ 1.4160678386688232
1574
+ ],
1575
+ [
1576
+ 0.13109137117862701,
1577
+ 0.0021367210429161787,
1578
+ 0.2086499035358429,
1579
+ 176.0106658935547,
1580
+ 0.0002825793926604092,
1581
+ 89.99723815917969,
1582
+ 1.4032492637634277
1583
+ ],
1584
+ [
1585
+ 0.13108032941818237,
1586
+ 0.0020987510215491056,
1587
+ 0.20869462192058563,
1588
+ 176.01048278808594,
1589
+ 8.914720092434436e-05,
1590
+ 89.99732208251953,
1591
+ 1.4274038076400757
1592
+ ],
1593
+ [
1594
+ 0.1310896873474121,
1595
+ 0.001965466421097517,
1596
+ 0.2085879147052765,
1597
+ 176.0106201171875,
1598
+ 0.00011336547322571278,
1599
+ 89.99744415283203,
1600
+ 1.4202443361282349
1601
+ ],
1602
+ [
1603
+ 0.1309545487165451,
1604
+ 0.0020008983556181192,
1605
+ 0.20851023495197296,
1606
+ 176.01084899902344,
1607
+ 8.181034354493022e-05,
1608
+ 89.99724578857422,
1609
+ 1.3181438446044922
1610
+ ],
1611
+ [
1612
+ 0.13098056614398956,
1613
+ 0.0020052797626703978,
1614
+ 0.20866644382476807,
1615
+ 176.01084899902344,
1616
+ 1.581673313921783e-05,
1617
+ 89.99732208251953,
1618
+ 1.4290106296539307
1619
+ ],
1620
+ [
1621
+ 0.13093963265419006,
1622
+ 0.0019918722100555897,
1623
+ 0.20861992239952087,
1624
+ 176.01107788085938,
1625
+ 0.000114964168460574,
1626
+ 89.9972152709961,
1627
+ 1.5534965991973877
1628
+ ]
1629
+ ],
1630
+ [
1631
+ [
1632
+ 0.1310625970363617,
1633
+ 0.002262422349303961,
1634
+ 0.2089119255542755,
1635
+ 176.0103759765625,
1636
+ 0.0006257580826058984,
1637
+ 89.99360656738281,
1638
+ 1.7586634159088135
1639
+ ],
1640
+ [
1641
+ 0.13103747367858887,
1642
+ 0.0023066673893481493,
1643
+ 0.2088727205991745,
1644
+ 176.01119995117188,
1645
+ 0.0007684793672524393,
1646
+ 89.99567413330078,
1647
+ 1.7465505599975586
1648
+ ],
1649
+ [
1650
+ 0.13107457756996155,
1651
+ 0.0023887536954134703,
1652
+ 0.20881468057632446,
1653
+ 176.01182556152344,
1654
+ 0.0013535339385271072,
1655
+ 90.0029525756836,
1656
+ 1.772923469543457
1657
+ ],
1658
+ [
1659
+ 0.13104654848575592,
1660
+ 0.002411512192338705,
1661
+ 0.20869652926921844,
1662
+ 176.01312255859375,
1663
+ 0.0031110860873013735,
1664
+ 90.01178741455078,
1665
+ 1.9708569049835205
1666
+ ],
1667
+ [
1668
+ 0.131149023771286,
1669
+ 0.002343925880268216,
1670
+ 0.2086239606142044,
1671
+ 176.02142333984375,
1672
+ 0.010187304578721523,
1673
+ 90.04408264160156,
1674
+ 1.754522442817688
1675
+ ],
1676
+ [
1677
+ 0.13132363557815552,
1678
+ 0.0024899793788790703,
1679
+ 0.20870542526245117,
1680
+ 176.02398681640625,
1681
+ 0.013792487792670727,
1682
+ 90.0602035522461,
1683
+ 1.5829174518585205
1684
+ ],
1685
+ [
1686
+ 0.1315920054912567,
1687
+ 0.002792557468637824,
1688
+ 0.2087075561285019,
1689
+ 176.0263671875,
1690
+ 0.014749342575669289,
1691
+ 90.06623077392578,
1692
+ 1.6810896396636963
1693
+ ],
1694
+ [
1695
+ 0.13190563023090363,
1696
+ 0.002925220178440213,
1697
+ 0.20856058597564697,
1698
+ 176.02403259277344,
1699
+ 0.015008483082056046,
1700
+ 90.06809997558594,
1701
+ 1.7869353294372559
1702
+ ],
1703
+ [
1704
+ 0.13277889788150787,
1705
+ 0.0038367649540305138,
1706
+ 0.2084805965423584,
1707
+ 176.0255584716797,
1708
+ 0.014311396516859531,
1709
+ 90.07722473144531,
1710
+ 1.8236664533615112
1711
+ ],
1712
+ [
1713
+ 0.1340513527393341,
1714
+ 0.00496424688026309,
1715
+ 0.20844902098178864,
1716
+ 176.03277587890625,
1717
+ 0.014929043129086494,
1718
+ 90.08575439453125,
1719
+ 1.725683331489563
1720
+ ],
1721
+ [
1722
+ 0.13574852049350739,
1723
+ 0.00646184803918004,
1724
+ 0.20839162170886993,
1725
+ 176.0340576171875,
1726
+ 0.016113463789224625,
1727
+ 90.09547424316406,
1728
+ 1.8272876739501953
1729
+ ],
1730
+ [
1731
+ 0.13738156855106354,
1732
+ 0.00808830838650465,
1733
+ 0.20838771760463715,
1734
+ 176.0395050048828,
1735
+ 0.017198672518134117,
1736
+ 90.10438537597656,
1737
+ 1.5754625797271729
1738
+ ],
1739
+ [
1740
+ 0.13892367482185364,
1741
+ 0.0097963223233819,
1742
+ 0.20848999917507172,
1743
+ 176.0406036376953,
1744
+ 0.01659032143652439,
1745
+ 90.10819244384766,
1746
+ 1.5770574808120728
1747
+ ],
1748
+ [
1749
+ 0.1403716802597046,
1750
+ 0.011274179443717003,
1751
+ 0.20826447010040283,
1752
+ 176.04229736328125,
1753
+ 0.01705697737634182,
1754
+ 90.115966796875,
1755
+ 1.64292311668396
1756
+ ],
1757
+ [
1758
+ 0.1418147087097168,
1759
+ 0.013074633665382862,
1760
+ 0.20814748108386993,
1761
+ 176.04641723632812,
1762
+ 0.016927046701312065,
1763
+ 90.1190414428711,
1764
+ 1.632869005203247
1765
+ ],
1766
+ [
1767
+ 0.1428920179605484,
1768
+ 0.0144652109593153,
1769
+ 0.20800454914569855,
1770
+ 176.04747009277344,
1771
+ 0.018901916220784187,
1772
+ 90.12922668457031,
1773
+ 1.4252182245254517
1774
+ ]
1775
+ ],
1776
+ [
1777
+ [
1778
+ 0.13105656206607819,
1779
+ 0.0023602405562996864,
1780
+ 0.20898427069187164,
1781
+ 176.01063537597656,
1782
+ 0.0006020718137733638,
1783
+ 89.9943618774414,
1784
+ 2.179922342300415
1785
+ ],
1786
+ [
1787
+ 0.13098596036434174,
1788
+ 0.002325172768905759,
1789
+ 0.20916786789894104,
1790
+ 176.01051330566406,
1791
+ 0.0004310974618420005,
1792
+ 89.99432373046875,
1793
+ 2.1195032596588135
1794
+ ],
1795
+ [
1796
+ 0.1309630572795868,
1797
+ 0.0022223670966923237,
1798
+ 0.20889264345169067,
1799
+ 176.01052856445312,
1800
+ 0.0006308387964963913,
1801
+ 89.99467468261719,
1802
+ 2.014186382293701
1803
+ ],
1804
+ [
1805
+ 0.13118304312229156,
1806
+ 0.002115617273375392,
1807
+ 0.20892487466335297,
1808
+ 176.01077270507812,
1809
+ 0.00036812995676882565,
1810
+ 89.99479675292969,
1811
+ 1.9647281169891357
1812
+ ],
1813
+ [
1814
+ 0.13123923540115356,
1815
+ 0.002276036189869046,
1816
+ 0.20901867747306824,
1817
+ 176.01104736328125,
1818
+ 0.0006821491406299174,
1819
+ 89.99464416503906,
1820
+ 2.115300416946411
1821
+ ],
1822
+ [
1823
+ 0.1309644877910614,
1824
+ 0.0024242354556918144,
1825
+ 0.20889374613761902,
1826
+ 176.01104736328125,
1827
+ 0.0007410533144138753,
1828
+ 89.99494934082031,
1829
+ 2.092991590499878
1830
+ ],
1831
+ [
1832
+ 0.1310899704694748,
1833
+ 0.0024881968274712563,
1834
+ 0.2086620181798935,
1835
+ 176.01051330566406,
1836
+ 0.0006960235186852515,
1837
+ 89.99518585205078,
1838
+ 2.0279088020324707
1839
+ ],
1840
+ [
1841
+ 0.13100241124629974,
1842
+ 0.0023330613039433956,
1843
+ 0.20857368409633636,
1844
+ 176.01121520996094,
1845
+ 0.0011248154332861304,
1846
+ 89.99490356445312,
1847
+ 2.076280117034912
1848
+ ],
1849
+ [
1850
+ 0.13133551180362701,
1851
+ 0.002074543386697769,
1852
+ 0.20882956683635712,
1853
+ 176.0106201171875,
1854
+ 0.0007992343162186444,
1855
+ 89.99488830566406,
1856
+ 2.3357579708099365
1857
+ ],
1858
+ [
1859
+ 0.13142457604408264,
1860
+ 0.0023106110747903585,
1861
+ 0.2090350091457367,
1862
+ 176.01181030273438,
1863
+ 0.0017663476755842566,
1864
+ 89.9958724975586,
1865
+ 2.1653404235839844
1866
+ ],
1867
+ [
1868
+ 0.13143305480480194,
1869
+ 0.0022212073672562838,
1870
+ 0.2087664157152176,
1871
+ 176.0148162841797,
1872
+ 0.004349719267338514,
1873
+ 90.00025177001953,
1874
+ 2.082001209259033
1875
+ ],
1876
+ [
1877
+ 0.13188883662223816,
1878
+ 0.0025496985763311386,
1879
+ 0.20867471396923065,
1880
+ 176.02198791503906,
1881
+ 0.008892725221812725,
1882
+ 90.01324462890625,
1883
+ 2.2912440299987793
1884
+ ],
1885
+ [
1886
+ 0.13280987739562988,
1887
+ 0.0028099198825657368,
1888
+ 0.2085939645767212,
1889
+ 176.0329132080078,
1890
+ 0.015903787687420845,
1891
+ 90.03829956054688,
1892
+ 2.3173186779022217
1893
+ ],
1894
+ [
1895
+ 0.134368896484375,
1896
+ 0.0036931594368070364,
1897
+ 0.2086687684059143,
1898
+ 176.04147338867188,
1899
+ 0.019611438736319542,
1900
+ 90.05754089355469,
1901
+ 2.2287545204162598
1902
+ ],
1903
+ [
1904
+ 0.13569042086601257,
1905
+ 0.004773235879838467,
1906
+ 0.20859681069850922,
1907
+ 176.0457000732422,
1908
+ 0.019823826849460602,
1909
+ 90.0657958984375,
1910
+ 2.272202253341675
1911
+ ],
1912
+ [
1913
+ 0.1372840255498886,
1914
+ 0.005555036943405867,
1915
+ 0.20822647213935852,
1916
+ 176.04730224609375,
1917
+ 0.019732844084501266,
1918
+ 90.06982421875,
1919
+ 2.210867404937744
1920
+ ]
1921
+ ],
1922
+ [
1923
+ [
1924
+ 0.1311476230621338,
1925
+ 0.0023023055400699377,
1926
+ 0.20911815762519836,
1927
+ 176.01226806640625,
1928
+ 0.00027950218645855784,
1929
+ 89.9934310913086,
1930
+ 1.5571088790893555
1931
+ ],
1932
+ [
1933
+ 0.13097205758094788,
1934
+ 0.0022247517481446266,
1935
+ 0.20913486182689667,
1936
+ 176.0115203857422,
1937
+ 0.0001242578000528738,
1938
+ 89.99359130859375,
1939
+ 1.5539366006851196
1940
+ ],
1941
+ [
1942
+ 0.13105258345603943,
1943
+ 0.0022721458226442337,
1944
+ 0.20916083455085754,
1945
+ 176.0118865966797,
1946
+ 0.00018107796495314687,
1947
+ 89.99371337890625,
1948
+ 1.5149725675582886
1949
+ ],
1950
+ [
1951
+ 0.1310078203678131,
1952
+ 0.0023006191477179527,
1953
+ 0.20906765758991241,
1954
+ 176.01211547851562,
1955
+ -4.122857262700563e-06,
1956
+ 89.99373626708984,
1957
+ 1.4572826623916626
1958
+ ],
1959
+ [
1960
+ 0.1312715858221054,
1961
+ 0.0022105432581156492,
1962
+ 0.20926624536514282,
1963
+ 176.01239013671875,
1964
+ -5.533808871405199e-05,
1965
+ 89.99380493164062,
1966
+ 1.5611789226531982
1967
+ ],
1968
+ [
1969
+ 0.13128021359443665,
1970
+ 0.002131375949829817,
1971
+ 0.2090412974357605,
1972
+ 176.011962890625,
1973
+ 3.664378164103255e-05,
1974
+ 89.99382019042969,
1975
+ 1.5480589866638184
1976
+ ],
1977
+ [
1978
+ 0.1313270628452301,
1979
+ 0.0021946816705167294,
1980
+ 0.20888619124889374,
1981
+ 176.01206970214844,
1982
+ 8.832529420033097e-05,
1983
+ 89.9942626953125,
1984
+ 1.4475888013839722
1985
+ ],
1986
+ [
1987
+ 0.13130341470241547,
1988
+ 0.0023487750440835953,
1989
+ 0.2091445028781891,
1990
+ 176.0122528076172,
1991
+ 0.0001613702770555392,
1992
+ 89.99378204345703,
1993
+ 1.4258266687393188
1994
+ ],
1995
+ [
1996
+ 0.1312701255083084,
1997
+ 0.0021396568045020103,
1998
+ 0.20899201929569244,
1999
+ 176.01220703125,
2000
+ 0.00018853852816391736,
2001
+ 89.99388885498047,
2002
+ 1.495673656463623
2003
+ ],
2004
+ [
2005
+ 0.13117635250091553,
2006
+ 0.0022341476287692785,
2007
+ 0.20899060368537903,
2008
+ 176.0117950439453,
2009
+ -0.0002515203959774226,
2010
+ 89.9941635131836,
2011
+ 1.4690793752670288
2012
+ ],
2013
+ [
2014
+ 0.13114149868488312,
2015
+ 0.0022697364911437035,
2016
+ 0.20916904509067535,
2017
+ 176.0121307373047,
2018
+ 0.00020011000742670149,
2019
+ 89.99385833740234,
2020
+ 1.5265271663665771
2021
+ ],
2022
+ [
2023
+ 0.13123348355293274,
2024
+ 0.0022597748320549726,
2025
+ 0.20883791148662567,
2026
+ 176.01217651367188,
2027
+ -7.763412577332929e-05,
2028
+ 89.99383544921875,
2029
+ 1.411619782447815
2030
+ ],
2031
+ [
2032
+ 0.13118508458137512,
2033
+ 0.002116534160450101,
2034
+ 0.20905648171901703,
2035
+ 176.01190185546875,
2036
+ 8.678370068082586e-05,
2037
+ 89.99382781982422,
2038
+ 1.3278228044509888
2039
+ ],
2040
+ [
2041
+ 0.13125251233577728,
2042
+ 0.0021482682786881924,
2043
+ 0.2087644338607788,
2044
+ 176.01190185546875,
2045
+ 0.000553049729205668,
2046
+ 89.99381256103516,
2047
+ 1.415297031402588
2048
+ ],
2049
+ [
2050
+ 0.1312207579612732,
2051
+ 0.00210443208925426,
2052
+ 0.20895741879940033,
2053
+ 176.0117950439453,
2054
+ 1.1949703548452817e-05,
2055
+ 89.99390411376953,
2056
+ 1.4966896772384644
2057
+ ],
2058
+ [
2059
+ 0.13124097883701324,
2060
+ 0.002255511237308383,
2061
+ 0.20898395776748657,
2062
+ 176.01194763183594,
2063
+ 0.0004619814280886203,
2064
+ 89.99407958984375,
2065
+ 1.5609248876571655
2066
+ ]
2067
+ ],
2068
+ [
2069
+ [
2070
+ 0.13151052594184875,
2071
+ 0.002042755950242281,
2072
+ 0.20936307311058044,
2073
+ 176.01976013183594,
2074
+ 0.00022363767493516207,
2075
+ 89.9924545288086,
2076
+ 1.3097466230392456
2077
+ ],
2078
+ [
2079
+ 0.13233833014965057,
2080
+ 0.0023028762079775333,
2081
+ 0.20960733294487,
2082
+ 176.0278778076172,
2083
+ 0.0008716406882740557,
2084
+ 89.99310302734375,
2085
+ 1.2867172956466675
2086
+ ],
2087
+ [
2088
+ 0.13352639973163605,
2089
+ 0.0022889645770192146,
2090
+ 0.20966385304927826,
2091
+ 176.03616333007812,
2092
+ 0.001322271884419024,
2093
+ 89.99298095703125,
2094
+ 0.9050455689430237
2095
+ ],
2096
+ [
2097
+ 0.13523758947849274,
2098
+ 0.002218940993770957,
2099
+ 0.20954017341136932,
2100
+ 176.04820251464844,
2101
+ 0.0014007886638864875,
2102
+ 89.99150085449219,
2103
+ 0.9168777465820312
2104
+ ],
2105
+ [
2106
+ 0.1372406929731369,
2107
+ 0.002466500038281083,
2108
+ 0.20978009700775146,
2109
+ 176.0536346435547,
2110
+ 0.0012290149461477995,
2111
+ 89.99015045166016,
2112
+ 0.8074049949645996
2113
+ ],
2114
+ [
2115
+ 0.13988526165485382,
2116
+ 0.002740683266893029,
2117
+ 0.2097521722316742,
2118
+ 176.06417846679688,
2119
+ 0.0014923993730917573,
2120
+ 89.99031829833984,
2121
+ 0.8328002095222473
2122
+ ],
2123
+ [
2124
+ 0.14248020946979523,
2125
+ 0.002650332869961858,
2126
+ 0.20973479747772217,
2127
+ 176.06959533691406,
2128
+ 0.0038100075908005238,
2129
+ 89.99609375,
2130
+ 0.8229233026504517
2131
+ ],
2132
+ [
2133
+ 0.14521433413028717,
2134
+ 0.0031598724890500307,
2135
+ 0.20975175499916077,
2136
+ 176.06761169433594,
2137
+ 0.00578471552580595,
2138
+ 90.00577545166016,
2139
+ 1.0089300870895386
2140
+ ],
2141
+ [
2142
+ 0.14832162857055664,
2143
+ 0.003720385953783989,
2144
+ 0.20975050330162048,
2145
+ 176.07077026367188,
2146
+ 0.008568760938942432,
2147
+ 90.02093505859375,
2148
+ 1.0272070169448853
2149
+ ],
2150
+ [
2151
+ 0.1511543095111847,
2152
+ 0.004450344480574131,
2153
+ 0.20981034636497498,
2154
+ 176.07644653320312,
2155
+ 0.00839082058519125,
2156
+ 90.02198028564453,
2157
+ 1.0196782350540161
2158
+ ],
2159
+ [
2160
+ 0.15441060066223145,
2161
+ 0.005427340976893902,
2162
+ 0.2099592387676239,
2163
+ 176.077880859375,
2164
+ 0.007006715517491102,
2165
+ 90.02384185791016,
2166
+ 1.1112313270568848
2167
+ ],
2168
+ [
2169
+ 0.15761025249958038,
2170
+ 0.00667285080999136,
2171
+ 0.2099599987268448,
2172
+ 176.08236694335938,
2173
+ 0.00703786127269268,
2174
+ 90.03225708007812,
2175
+ 0.9614713788032532
2176
+ ],
2177
+ [
2178
+ 0.1605365127325058,
2179
+ 0.0077243587002158165,
2180
+ 0.20988596975803375,
2181
+ 176.08262634277344,
2182
+ 0.006635352503508329,
2183
+ 90.03717803955078,
2184
+ 0.8564586043357849
2185
+ ],
2186
+ [
2187
+ 0.16319555044174194,
2188
+ 0.009182668291032314,
2189
+ 0.2097242921590805,
2190
+ 176.0826416015625,
2191
+ 0.006157096475362778,
2192
+ 90.04132843017578,
2193
+ 1.0396623611450195
2194
+ ],
2195
+ [
2196
+ 0.16594825685024261,
2197
+ 0.010410971939563751,
2198
+ 0.20984859764575958,
2199
+ 176.0836639404297,
2200
+ 0.005508731584995985,
2201
+ 90.04381561279297,
2202
+ 1.0547109842300415
2203
+ ],
2204
+ [
2205
+ 0.1688094139099121,
2206
+ 0.011989920400083065,
2207
+ 0.21000660955905914,
2208
+ 176.0830078125,
2209
+ 0.004602197557687759,
2210
+ 90.04736328125,
2211
+ 1.071629285812378
2212
+ ]
2213
+ ],
2214
+ [
2215
+ [
2216
+ 0.1314568668603897,
2217
+ 0.0019841394387185574,
2218
+ 0.20942673087120056,
2219
+ 176.0360870361328,
2220
+ 0.0015758902300149202,
2221
+ 89.99384307861328,
2222
+ 1.5428340435028076
2223
+ ],
2224
+ [
2225
+ 0.13215768337249756,
2226
+ 0.0020423580426722765,
2227
+ 0.20930837094783783,
2228
+ 176.0417022705078,
2229
+ 0.002681471174582839,
2230
+ 89.99696350097656,
2231
+ 1.2514009475708008
2232
+ ],
2233
+ [
2234
+ 0.1331777721643448,
2235
+ 0.0021136198192834854,
2236
+ 0.20938844978809357,
2237
+ 176.0500946044922,
2238
+ 0.0039357589557766914,
2239
+ 90.00202941894531,
2240
+ 1.419399619102478
2241
+ ],
2242
+ [
2243
+ 0.13547347486019135,
2244
+ 0.002146233571693301,
2245
+ 0.209134042263031,
2246
+ 176.05746459960938,
2247
+ 0.006314098369330168,
2248
+ 90.01226043701172,
2249
+ 1.4029184579849243
2250
+ ],
2251
+ [
2252
+ 0.1375972330570221,
2253
+ 0.0024197783786803484,
2254
+ 0.20914362370967865,
2255
+ 176.05682373046875,
2256
+ 0.0061169457621872425,
2257
+ 90.01567840576172,
2258
+ 1.5387314558029175
2259
+ ],
2260
+ [
2261
+ 0.14092472195625305,
2262
+ 0.0028871288523077965,
2263
+ 0.20905987918376923,
2264
+ 176.07350158691406,
2265
+ 0.011073993518948555,
2266
+ 90.03189849853516,
2267
+ 1.313731074333191
2268
+ ],
2269
+ [
2270
+ 0.1425974816083908,
2271
+ 0.00293346936814487,
2272
+ 0.209095761179924,
2273
+ 176.07315063476562,
2274
+ 0.010652842931449413,
2275
+ 90.03335571289062,
2276
+ 1.2736269235610962
2277
+ ],
2278
+ [
2279
+ 0.1451222002506256,
2280
+ 0.003264100756496191,
2281
+ 0.20909281075000763,
2282
+ 176.0758514404297,
2283
+ 0.009987112134695053,
2284
+ 90.03465270996094,
2285
+ 1.4777215719223022
2286
+ ],
2287
+ [
2288
+ 0.14776135981082916,
2289
+ 0.0036091539077460766,
2290
+ 0.20909354090690613,
2291
+ 176.0794219970703,
2292
+ 0.010137313045561314,
2293
+ 90.03825378417969,
2294
+ 1.5821022987365723
2295
+ ],
2296
+ [
2297
+ 0.15159934759140015,
2298
+ 0.004544712137430906,
2299
+ 0.20896752178668976,
2300
+ 176.08078002929688,
2301
+ 0.010858617722988129,
2302
+ 90.04562377929688,
2303
+ 1.7882821559906006
2304
+ ],
2305
+ [
2306
+ 0.15516579151153564,
2307
+ 0.0051415711641311646,
2308
+ 0.20919169485569,
2309
+ 176.08465576171875,
2310
+ 0.010859445668756962,
2311
+ 90.0510025024414,
2312
+ 1.5783836841583252
2313
+ ],
2314
+ [
2315
+ 0.15876927971839905,
2316
+ 0.005913090892136097,
2317
+ 0.20912276208400726,
2318
+ 176.0886993408203,
2319
+ 0.011329889297485352,
2320
+ 90.05593872070312,
2321
+ 1.41685950756073
2322
+ ],
2323
+ [
2324
+ 0.16144254803657532,
2325
+ 0.00663384422659874,
2326
+ 0.20931585133075714,
2327
+ 176.089111328125,
2328
+ 0.010171589441597462,
2329
+ 90.06047821044922,
2330
+ 1.4883959293365479
2331
+ ],
2332
+ [
2333
+ 0.16442343592643738,
2334
+ 0.007534189149737358,
2335
+ 0.209103524684906,
2336
+ 176.0906524658203,
2337
+ 0.009833579882979393,
2338
+ 90.0640640258789,
2339
+ 1.38670015335083
2340
+ ],
2341
+ [
2342
+ 0.16815185546875,
2343
+ 0.00848990585654974,
2344
+ 0.20915384590625763,
2345
+ 176.08929443359375,
2346
+ 0.008986596949398518,
2347
+ 90.06449127197266,
2348
+ 1.4265620708465576
2349
+ ],
2350
+ [
2351
+ 0.17166908085346222,
2352
+ 0.008982961997389793,
2353
+ 0.2090887427330017,
2354
+ 176.0904541015625,
2355
+ 0.00895396713167429,
2356
+ 90.06568908691406,
2357
+ 1.471843957901001
2358
+ ]
2359
+ ],
2360
+ [
2361
+ [
2362
+ 0.13194192945957184,
2363
+ 0.0020381570793688297,
2364
+ 0.20943905413150787,
2365
+ 176.05006408691406,
2366
+ 0.0034663670230656862,
2367
+ 89.99756622314453,
2368
+ 1.0901957750320435
2369
+ ],
2370
+ [
2371
+ 0.13351790606975555,
2372
+ 0.0022004081401973963,
2373
+ 0.20926451683044434,
2374
+ 176.05735778808594,
2375
+ 0.0038050992880016565,
2376
+ 90.00048065185547,
2377
+ 1.0187803506851196
2378
+ ],
2379
+ [
2380
+ 0.1356489509344101,
2381
+ 0.0023300061002373695,
2382
+ 0.20923949778079987,
2383
+ 176.0625762939453,
2384
+ 0.0044997213408350945,
2385
+ 90.00433349609375,
2386
+ 1.0298209190368652
2387
+ ],
2388
+ [
2389
+ 0.13781221210956573,
2390
+ 0.0023140942212194204,
2391
+ 0.20946456491947174,
2392
+ 176.06361389160156,
2393
+ 0.00490722618997097,
2394
+ 90.00704193115234,
2395
+ 1.1209251880645752
2396
+ ],
2397
+ [
2398
+ 0.13995090126991272,
2399
+ 0.0025345468893647194,
2400
+ 0.2088715136051178,
2401
+ 176.06448364257812,
2402
+ 0.005834353156387806,
2403
+ 90.0121078491211,
2404
+ 1.0788302421569824
2405
+ ],
2406
+ [
2407
+ 0.14341044425964355,
2408
+ 0.0028224962297827005,
2409
+ 0.2091182917356491,
2410
+ 176.06651306152344,
2411
+ 0.006371770519763231,
2412
+ 90.02145385742188,
2413
+ 0.8218777179718018
2414
+ ],
2415
+ [
2416
+ 0.14526797831058502,
2417
+ 0.003030006540939212,
2418
+ 0.2089725136756897,
2419
+ 176.0680694580078,
2420
+ 0.005698702298104763,
2421
+ 90.01937103271484,
2422
+ 0.8076294660568237
2423
+ ],
2424
+ [
2425
+ 0.14800581336021423,
2426
+ 0.00334921944886446,
2427
+ 0.20885704457759857,
2428
+ 176.068115234375,
2429
+ 0.006393552757799625,
2430
+ 90.02450561523438,
2431
+ 1.0107996463775635
2432
+ ],
2433
+ [
2434
+ 0.15192146599292755,
2435
+ 0.0039702826179564,
2436
+ 0.20883382856845856,
2437
+ 176.06698608398438,
2438
+ 0.006974372547119856,
2439
+ 90.03755187988281,
2440
+ 0.9997147917747498
2441
+ ],
2442
+ [
2443
+ 0.15492726862430573,
2444
+ 0.004420331679284573,
2445
+ 0.2086879462003708,
2446
+ 176.0714111328125,
2447
+ 0.006185361184179783,
2448
+ 90.0416488647461,
2449
+ 0.9014982581138611
2450
+ ],
2451
+ [
2452
+ 0.15756529569625854,
2453
+ 0.004949979484081268,
2454
+ 0.2086573988199234,
2455
+ 176.06944274902344,
2456
+ 0.0053632911294698715,
2457
+ 90.04232788085938,
2458
+ 1.0403151512145996
2459
+ ],
2460
+ [
2461
+ 0.1608741730451584,
2462
+ 0.005672391038388014,
2463
+ 0.20874115824699402,
2464
+ 176.0690460205078,
2465
+ 0.005566648207604885,
2466
+ 90.04853820800781,
2467
+ 0.9512991309165955
2468
+ ],
2469
+ [
2470
+ 0.1636040210723877,
2471
+ 0.006388437934219837,
2472
+ 0.20864614844322205,
2473
+ 176.0677490234375,
2474
+ 0.005087478552013636,
2475
+ 90.05046081542969,
2476
+ 0.9253427982330322
2477
+ ],
2478
+ [
2479
+ 0.16760578751564026,
2480
+ 0.008203347213566303,
2481
+ 0.20850533246994019,
2482
+ 176.06924438476562,
2483
+ 0.0047338251024484634,
2484
+ 90.06475067138672,
2485
+ 0.7220692038536072
2486
+ ],
2487
+ [
2488
+ 0.17042122781276703,
2489
+ 0.009444565512239933,
2490
+ 0.2084595412015915,
2491
+ 176.0691680908203,
2492
+ 0.0033530883956700563,
2493
+ 90.07066345214844,
2494
+ 0.7836520671844482
2495
+ ],
2496
+ [
2497
+ 0.17292018234729767,
2498
+ 0.010384578257799149,
2499
+ 0.208389550447464,
2500
+ 176.06756591796875,
2501
+ 0.0035885432735085487,
2502
+ 90.07406616210938,
2503
+ 0.9000303149223328
2504
+ ]
2505
+ ],
2506
+ [
2507
+ [
2508
+ 0.13395386934280396,
2509
+ 0.0022533698938786983,
2510
+ 0.2094932496547699,
2511
+ 176.0591278076172,
2512
+ 0.00533080380409956,
2513
+ 90.00312805175781,
2514
+ 1.1050819158554077
2515
+ ],
2516
+ [
2517
+ 0.1360653042793274,
2518
+ 0.002572509925812483,
2519
+ 0.20953978598117828,
2520
+ 176.06268310546875,
2521
+ 0.005043677054345608,
2522
+ 90.0066146850586,
2523
+ 1.2796581983566284
2524
+ ],
2525
+ [
2526
+ 0.13883723318576813,
2527
+ 0.0025573207531124353,
2528
+ 0.20933352410793304,
2529
+ 176.06472778320312,
2530
+ 0.005874339956790209,
2531
+ 90.00873565673828,
2532
+ 0.9890167713165283
2533
+ ],
2534
+ [
2535
+ 0.1411985158920288,
2536
+ 0.002616009907796979,
2537
+ 0.2094775289297104,
2538
+ 176.06710815429688,
2539
+ 0.005981623660773039,
2540
+ 90.0102310180664,
2541
+ 1.0719985961914062
2542
+ ],
2543
+ [
2544
+ 0.14446327090263367,
2545
+ 0.0030615264549851418,
2546
+ 0.209388867020607,
2547
+ 176.06854248046875,
2548
+ 0.007215661462396383,
2549
+ 90.01829528808594,
2550
+ 1.1514861583709717
2551
+ ],
2552
+ [
2553
+ 0.14741630852222443,
2554
+ 0.003342954209074378,
2555
+ 0.20955635607242584,
2556
+ 176.06753540039062,
2557
+ 0.007192699238657951,
2558
+ 90.02474975585938,
2559
+ 1.1164416074752808
2560
+ ],
2561
+ [
2562
+ 0.15000857412815094,
2563
+ 0.0037814953830093145,
2564
+ 0.20945404469966888,
2565
+ 176.06771850585938,
2566
+ 0.006663817912340164,
2567
+ 90.02511596679688,
2568
+ 0.9878707528114319
2569
+ ],
2570
+ [
2571
+ 0.1527121216058731,
2572
+ 0.004268007352948189,
2573
+ 0.2095233052968979,
2574
+ 176.0683135986328,
2575
+ 0.006809584330767393,
2576
+ 90.02764129638672,
2577
+ 1.0467628240585327
2578
+ ],
2579
+ [
2580
+ 0.15771082043647766,
2581
+ 0.005399511661380529,
2582
+ 0.20935118198394775,
2583
+ 176.0680694580078,
2584
+ 0.0070977103896439075,
2585
+ 90.03895568847656,
2586
+ 0.9624401926994324
2587
+ ],
2588
+ [
2589
+ 0.1604139506816864,
2590
+ 0.006183587480336428,
2591
+ 0.20949584245681763,
2592
+ 176.06729125976562,
2593
+ 0.007079924922436476,
2594
+ 90.04581451416016,
2595
+ 1.0410269498825073
2596
+ ],
2597
+ [
2598
+ 0.16385667026042938,
2599
+ 0.007031232584267855,
2600
+ 0.20934681594371796,
2601
+ 176.0692901611328,
2602
+ 0.006450592074543238,
2603
+ 90.04928588867188,
2604
+ 1.1203993558883667
2605
+ ],
2606
+ [
2607
+ 0.16690054535865784,
2608
+ 0.007950100116431713,
2609
+ 0.20940165221691132,
2610
+ 176.0672149658203,
2611
+ 0.005291949957609177,
2612
+ 90.05448150634766,
2613
+ 1.1258074045181274
2614
+ ],
2615
+ [
2616
+ 0.1715908795595169,
2617
+ 0.009461349807679653,
2618
+ 0.20933300256729126,
2619
+ 176.06492614746094,
2620
+ 0.005738032516092062,
2621
+ 90.06134033203125,
2622
+ 1.0616520643234253
2623
+ ],
2624
+ [
2625
+ 0.1746007353067398,
2626
+ 0.010603931732475758,
2627
+ 0.20925778150558472,
2628
+ 176.06610107421875,
2629
+ 0.006280864588916302,
2630
+ 90.0672836303711,
2631
+ 0.9891526699066162
2632
+ ],
2633
+ [
2634
+ 0.17728064954280853,
2635
+ 0.011727586388587952,
2636
+ 0.2093227207660675,
2637
+ 176.06336975097656,
2638
+ 0.0034990361891686916,
2639
+ 90.06891632080078,
2640
+ 1.1245964765548706
2641
+ ],
2642
+ [
2643
+ 0.1798211634159088,
2644
+ 0.013041124679148197,
2645
+ 0.2089427411556244,
2646
+ 176.0674591064453,
2647
+ 0.005642501171678305,
2648
+ 90.07917785644531,
2649
+ 0.9584941267967224
2650
+ ]
2651
+ ],
2652
+ [
2653
+ [
2654
+ 0.13620370626449585,
2655
+ 0.0022139614447951317,
2656
+ 0.20934607088565826,
2657
+ 176.06236267089844,
2658
+ 0.005754353944212198,
2659
+ 90.00737762451172,
2660
+ 0.46630996465682983
2661
+ ],
2662
+ [
2663
+ 0.13915377855300903,
2664
+ 0.002330706687644124,
2665
+ 0.20923729240894318,
2666
+ 176.06224060058594,
2667
+ 0.005820975638926029,
2668
+ 90.00996398925781,
2669
+ 0.4506203532218933
2670
+ ],
2671
+ [
2672
+ 0.14203476905822754,
2673
+ 0.0024031787179410458,
2674
+ 0.20937073230743408,
2675
+ 176.06167602539062,
2676
+ 0.005333679262548685,
2677
+ 90.01258087158203,
2678
+ 0.5760780572891235
2679
+ ],
2680
+ [
2681
+ 0.14495201408863068,
2682
+ 0.002607988426461816,
2683
+ 0.2094348967075348,
2684
+ 176.0612335205078,
2685
+ 0.005184772424399853,
2686
+ 90.01567077636719,
2687
+ 0.47035640478134155
2688
+ ],
2689
+ [
2690
+ 0.14804714918136597,
2691
+ 0.002673815470188856,
2692
+ 0.20937857031822205,
2693
+ 176.06309509277344,
2694
+ 0.004686256404966116,
2695
+ 90.01692962646484,
2696
+ 0.4908308684825897
2697
+ ],
2698
+ [
2699
+ 0.15090087056159973,
2700
+ 0.0030027381144464016,
2701
+ 0.20922842621803284,
2702
+ 176.0636444091797,
2703
+ 0.0049302950501441956,
2704
+ 90.01665496826172,
2705
+ 0.5288674831390381
2706
+ ],
2707
+ [
2708
+ 0.15503552556037903,
2709
+ 0.003138835309073329,
2710
+ 0.20920805633068085,
2711
+ 176.0633087158203,
2712
+ 0.0045907823368906975,
2713
+ 90.01863098144531,
2714
+ 0.370364785194397
2715
+ ],
2716
+ [
2717
+ 0.15798354148864746,
2718
+ 0.003427238669246435,
2719
+ 0.20912602543830872,
2720
+ 176.0625,
2721
+ 0.003743237815797329,
2722
+ 90.0203628540039,
2723
+ 0.5804671049118042
2724
+ ],
2725
+ [
2726
+ 0.16167676448822021,
2727
+ 0.0036886923480778933,
2728
+ 0.20919255912303925,
2729
+ 176.05999755859375,
2730
+ 0.002865498885512352,
2731
+ 90.02029418945312,
2732
+ 0.6309384703636169
2733
+ ],
2734
+ [
2735
+ 0.16514182090759277,
2736
+ 0.003945154137909412,
2737
+ 0.2091439813375473,
2738
+ 176.05795288085938,
2739
+ 0.0019318630220368505,
2740
+ 90.02252197265625,
2741
+ 0.27112337946891785
2742
+ ],
2743
+ [
2744
+ 0.1684022694826126,
2745
+ 0.004282447509467602,
2746
+ 0.20895610749721527,
2747
+ 176.05934143066406,
2748
+ 0.002354203024879098,
2749
+ 90.02371978759766,
2750
+ 0.3780146539211273
2751
+ ],
2752
+ [
2753
+ 0.1713954657316208,
2754
+ 0.004515091888606548,
2755
+ 0.2089526355266571,
2756
+ 176.05618286132812,
2757
+ 0.001018472365103662,
2758
+ 90.02404022216797,
2759
+ 0.4196428656578064
2760
+ ],
2761
+ [
2762
+ 0.1747693419456482,
2763
+ 0.004693181719630957,
2764
+ 0.20894064009189606,
2765
+ 176.0546112060547,
2766
+ 0.0001507062988821417,
2767
+ 90.02482604980469,
2768
+ 0.4931110441684723
2769
+ ],
2770
+ [
2771
+ 0.1781192272901535,
2772
+ 0.00513042276725173,
2773
+ 0.20895494520664215,
2774
+ 176.05323791503906,
2775
+ 0.0002644608321134001,
2776
+ 90.0260238647461,
2777
+ 0.54234778881073
2778
+ ],
2779
+ [
2780
+ 0.18171963095664978,
2781
+ 0.0055943503975868225,
2782
+ 0.2089567333459854,
2783
+ 176.0541534423828,
2784
+ -0.0020066758152097464,
2785
+ 90.0269546508789,
2786
+ 0.6478036046028137
2787
+ ],
2788
+ [
2789
+ 0.18347924947738647,
2790
+ 0.005895908921957016,
2791
+ 0.2089943289756775,
2792
+ 176.05252075195312,
2793
+ -0.0012818975374102592,
2794
+ 90.02947998046875,
2795
+ 0.7981542944908142
2796
+ ]
2797
+ ],
2798
+ [
2799
+ [
2800
+ 0.1415129005908966,
2801
+ 0.0027319975197315216,
2802
+ 0.2093348205089569,
2803
+ 176.06459045410156,
2804
+ 0.0035483501851558685,
2805
+ 90.00851440429688,
2806
+ 0.9952843189239502
2807
+ ],
2808
+ [
2809
+ 0.14463184773921967,
2810
+ 0.0034573955927044153,
2811
+ 0.2093559056520462,
2812
+ 176.0646209716797,
2813
+ 0.0034132797736674547,
2814
+ 90.01188659667969,
2815
+ 0.9798665046691895
2816
+ ],
2817
+ [
2818
+ 0.1475665122270584,
2819
+ 0.0038825850933790207,
2820
+ 0.2093151956796646,
2821
+ 176.06668090820312,
2822
+ 0.0023440546356141567,
2823
+ 90.0120620727539,
2824
+ 0.7271140217781067
2825
+ ],
2826
+ [
2827
+ 0.14940232038497925,
2828
+ 0.003983384929597378,
2829
+ 0.20927320420742035,
2830
+ 176.06834411621094,
2831
+ 0.00267407507635653,
2832
+ 90.01448822021484,
2833
+ 0.6987061500549316
2834
+ ],
2835
+ [
2836
+ 0.1526920348405838,
2837
+ 0.00442832987755537,
2838
+ 0.20909786224365234,
2839
+ 176.06927490234375,
2840
+ 0.0022413244005292654,
2841
+ 90.01576232910156,
2842
+ 0.7444576025009155
2843
+ ],
2844
+ [
2845
+ 0.15560398995876312,
2846
+ 0.004830278921872377,
2847
+ 0.20910058915615082,
2848
+ 176.06788635253906,
2849
+ 0.0025365115143358707,
2850
+ 90.0177230834961,
2851
+ 0.8044632077217102
2852
+ ],
2853
+ [
2854
+ 0.15908944606781006,
2855
+ 0.005355764180421829,
2856
+ 0.2089800238609314,
2857
+ 176.0677947998047,
2858
+ 0.0007235665107145905,
2859
+ 90.0152816772461,
2860
+ 0.7970201373100281
2861
+ ],
2862
+ [
2863
+ 0.16225340962409973,
2864
+ 0.005928054917603731,
2865
+ 0.20895995199680328,
2866
+ 176.06607055664062,
2867
+ 0.00022274779621511698,
2868
+ 90.01651763916016,
2869
+ 0.7135864496231079
2870
+ ],
2871
+ [
2872
+ 0.16526153683662415,
2873
+ 0.006400957703590393,
2874
+ 0.2089604288339615,
2875
+ 176.06787109375,
2876
+ -1.0556516826909501e-05,
2877
+ 90.01866912841797,
2878
+ 0.8239924907684326
2879
+ ],
2880
+ [
2881
+ 0.16810795664787292,
2882
+ 0.006781307980418205,
2883
+ 0.20872263610363007,
2884
+ 176.06768798828125,
2885
+ -0.000546993687748909,
2886
+ 90.01913452148438,
2887
+ 0.8681785464286804
2888
+ ],
2889
+ [
2890
+ 0.17112158238887787,
2891
+ 0.007493982091546059,
2892
+ 0.20866824686527252,
2893
+ 176.06712341308594,
2894
+ -0.001327631063759327,
2895
+ 90.02007293701172,
2896
+ 0.7277992367744446
2897
+ ],
2898
+ [
2899
+ 0.17460274696350098,
2900
+ 0.008094617165625095,
2901
+ 0.20866800844669342,
2902
+ 176.0659942626953,
2903
+ -0.0019740925636142492,
2904
+ 90.01825714111328,
2905
+ 0.7027584910392761
2906
+ ],
2907
+ [
2908
+ 0.17734290659427643,
2909
+ 0.008914713747799397,
2910
+ 0.20877674221992493,
2911
+ 176.0680694580078,
2912
+ -0.0023505177814513445,
2913
+ 90.01923370361328,
2914
+ 0.4651167094707489
2915
+ ],
2916
+ [
2917
+ 0.180923730134964,
2918
+ 0.009290380403399467,
2919
+ 0.20865961909294128,
2920
+ 176.06640625,
2921
+ -0.0033232741989195347,
2922
+ 90.01900482177734,
2923
+ 0.6333544850349426
2924
+ ],
2925
+ [
2926
+ 0.18475398421287537,
2927
+ 0.010008219629526138,
2928
+ 0.20842184126377106,
2929
+ 176.06101989746094,
2930
+ -0.0037326866295188665,
2931
+ 90.01280975341797,
2932
+ 0.6913871169090271
2933
+ ],
2934
+ [
2935
+ 0.18697169423103333,
2936
+ 0.010109730996191502,
2937
+ 0.20837467908859253,
2938
+ 176.05958557128906,
2939
+ -0.004359754268079996,
2940
+ 90.01374053955078,
2941
+ 0.8133594989776611
2942
+ ]
2943
+ ],
2944
+ [
2945
+ [
2946
+ 0.1459393948316574,
2947
+ 0.0026647618506103754,
2948
+ 0.2093164324760437,
2949
+ 176.06600952148438,
2950
+ 0.00192162801977247,
2951
+ 90.01443481445312,
2952
+ 0.44950979948043823
2953
+ ],
2954
+ [
2955
+ 0.14939002692699432,
2956
+ 0.0033358128275722265,
2957
+ 0.20907078683376312,
2958
+ 176.0657958984375,
2959
+ 0.0015133906854316592,
2960
+ 90.01676940917969,
2961
+ 0.5347806215286255
2962
+ ],
2963
+ [
2964
+ 0.15198354423046112,
2965
+ 0.003609301522374153,
2966
+ 0.20909734070301056,
2967
+ 176.0636444091797,
2968
+ 0.0013040334451943636,
2969
+ 90.01792907714844,
2970
+ 0.6040546894073486
2971
+ ],
2972
+ [
2973
+ 0.15443632006645203,
2974
+ 0.0040175761096179485,
2975
+ 0.2092650681734085,
2976
+ 176.06214904785156,
2977
+ 0.0008769400883466005,
2978
+ 90.01868438720703,
2979
+ 0.40932294726371765
2980
+ ],
2981
+ [
2982
+ 0.15729935467243195,
2983
+ 0.004496479872614145,
2984
+ 0.20915155112743378,
2985
+ 176.0602569580078,
2986
+ 0.0003366203745827079,
2987
+ 90.02132415771484,
2988
+ 0.43739408254623413
2989
+ ],
2990
+ [
2991
+ 0.16091039776802063,
2992
+ 0.004928280599415302,
2993
+ 0.20907168090343475,
2994
+ 176.05764770507812,
2995
+ -0.00043829786591231823,
2996
+ 90.02033233642578,
2997
+ 0.3386193513870239
2998
+ ],
2999
+ [
3000
+ 0.16445761919021606,
3001
+ 0.0054289959371089935,
3002
+ 0.20917731523513794,
3003
+ 176.05711364746094,
3004
+ -0.001454166485927999,
3005
+ 90.01973724365234,
3006
+ 0.5100647807121277
3007
+ ],
3008
+ [
3009
+ 0.1679045706987381,
3010
+ 0.005899304524064064,
3011
+ 0.20913070440292358,
3012
+ 176.054931640625,
3013
+ -0.0021595845464617014,
3014
+ 90.02226257324219,
3015
+ 0.36865168809890747
3016
+ ],
3017
+ [
3018
+ 0.17089883983135223,
3019
+ 0.006172821391373873,
3020
+ 0.20922040939331055,
3021
+ 176.05357360839844,
3022
+ -0.0021098870784044266,
3023
+ 90.02401733398438,
3024
+ 0.42084795236587524
3025
+ ],
3026
+ [
3027
+ 0.17408177256584167,
3028
+ 0.006712178699672222,
3029
+ 0.209229975938797,
3030
+ 176.05125427246094,
3031
+ -0.002903751563280821,
3032
+ 90.02425384521484,
3033
+ 0.44427600502967834
3034
+ ],
3035
+ [
3036
+ 0.17689931392669678,
3037
+ 0.007295092102140188,
3038
+ 0.20918262004852295,
3039
+ 176.05206298828125,
3040
+ -0.003444937290623784,
3041
+ 90.02523803710938,
3042
+ 0.45067352056503296
3043
+ ],
3044
+ [
3045
+ 0.18033607304096222,
3046
+ 0.007948377169668674,
3047
+ 0.20906803011894226,
3048
+ 176.04959106445312,
3049
+ -0.004197859205305576,
3050
+ 90.02897644042969,
3051
+ 0.24019905924797058
3052
+ ],
3053
+ [
3054
+ 0.18311168253421783,
3055
+ 0.008662025444209576,
3056
+ 0.2091931700706482,
3057
+ 176.04855346679688,
3058
+ -0.003918559290468693,
3059
+ 90.03141784667969,
3060
+ 0.3362092077732086
3061
+ ],
3062
+ [
3063
+ 0.1847749501466751,
3064
+ 0.009233217686414719,
3065
+ 0.20921775698661804,
3066
+ 176.05078125,
3067
+ -0.00421652989462018,
3068
+ 90.03890228271484,
3069
+ 0.5818966627120972
3070
+ ],
3071
+ [
3072
+ 0.18705809116363525,
3073
+ 0.010348127223551273,
3074
+ 0.2091480791568756,
3075
+ 176.049072265625,
3076
+ -0.004549405071884394,
3077
+ 90.04230499267578,
3078
+ 0.5968301296234131
3079
+ ],
3080
+ [
3081
+ 0.188578262925148,
3082
+ 0.0115588940680027,
3083
+ 0.20919278264045715,
3084
+ 176.0491943359375,
3085
+ -0.005167542025446892,
3086
+ 90.04813385009766,
3087
+ 0.6264194250106812
3088
+ ]
3089
+ ],
3090
+ [
3091
+ [
3092
+ 0.14900004863739014,
3093
+ 0.002921953797340393,
3094
+ 0.20949354767799377,
3095
+ 176.06668090820312,
3096
+ 0.001516735297627747,
3097
+ 90.01408386230469,
3098
+ 0.3026089072227478
3099
+ ],
3100
+ [
3101
+ 0.15179364383220673,
3102
+ 0.003116740146651864,
3103
+ 0.20940186083316803,
3104
+ 176.0670623779297,
3105
+ 0.0011123995063826442,
3106
+ 90.015625,
3107
+ 0.5235627889633179
3108
+ ],
3109
+ [
3110
+ 0.15444277226924896,
3111
+ 0.0033007243182510138,
3112
+ 0.20949342846870422,
3113
+ 176.0649871826172,
3114
+ 0.0008960908744484186,
3115
+ 90.01746368408203,
3116
+ 0.3297939598560333
3117
+ ],
3118
+ [
3119
+ 0.15699930489063263,
3120
+ 0.003456363920122385,
3121
+ 0.209568053483963,
3122
+ 176.06341552734375,
3123
+ 0.0008366538095287979,
3124
+ 90.01636505126953,
3125
+ 0.49890604615211487
3126
+ ],
3127
+ [
3128
+ 0.16086389124393463,
3129
+ 0.004019460640847683,
3130
+ 0.20943576097488403,
3131
+ 176.063232421875,
3132
+ 5.518854231922887e-05,
3133
+ 90.01851654052734,
3134
+ 0.536245584487915
3135
+ ],
3136
+ [
3137
+ 0.1648116111755371,
3138
+ 0.004216460045427084,
3139
+ 0.20931807160377502,
3140
+ 176.06207275390625,
3141
+ -0.0003157079336233437,
3142
+ 90.02035522460938,
3143
+ 0.4826611578464508
3144
+ ],
3145
+ [
3146
+ 0.16802358627319336,
3147
+ 0.004554403014481068,
3148
+ 0.2093571126461029,
3149
+ 176.0594482421875,
3150
+ -0.0005549978232011199,
3151
+ 90.02200317382812,
3152
+ 0.5079677104949951
3153
+ ],
3154
+ [
3155
+ 0.17050562798976898,
3156
+ 0.00496663898229599,
3157
+ 0.20933926105499268,
3158
+ 176.0605926513672,
3159
+ -0.0013579692458733916,
3160
+ 90.02130126953125,
3161
+ 0.49605876207351685
3162
+ ],
3163
+ [
3164
+ 0.17323371767997742,
3165
+ 0.005222120322287083,
3166
+ 0.20939065515995026,
3167
+ 176.0598602294922,
3168
+ -0.0015922823222354054,
3169
+ 90.02249145507812,
3170
+ 0.5645294189453125
3171
+ ],
3172
+ [
3173
+ 0.1767740249633789,
3174
+ 0.005624893121421337,
3175
+ 0.2093580961227417,
3176
+ 176.0605010986328,
3177
+ -0.0015111772809177637,
3178
+ 90.02519226074219,
3179
+ 0.40448492765426636
3180
+ ],
3181
+ [
3182
+ 0.17952607572078705,
3183
+ 0.005938116926699877,
3184
+ 0.20940861105918884,
3185
+ 176.0559844970703,
3186
+ -0.0025071382988244295,
3187
+ 90.0236587524414,
3188
+ 0.4641360938549042
3189
+ ],
3190
+ [
3191
+ 0.18321995437145233,
3192
+ 0.006393213756382465,
3193
+ 0.20940688252449036,
3194
+ 176.05604553222656,
3195
+ -0.002185596851631999,
3196
+ 90.02716064453125,
3197
+ 0.3673107624053955
3198
+ ],
3199
+ [
3200
+ 0.18606168031692505,
3201
+ 0.006786658428609371,
3202
+ 0.20944973826408386,
3203
+ 176.0542755126953,
3204
+ -0.0034062264021486044,
3205
+ 90.02542114257812,
3206
+ 0.308982789516449
3207
+ ],
3208
+ [
3209
+ 0.18914251029491425,
3210
+ 0.007327276282012463,
3211
+ 0.20951667428016663,
3212
+ 176.05125427246094,
3213
+ -0.0028737098909914494,
3214
+ 90.02667999267578,
3215
+ 0.2772078216075897
3216
+ ],
3217
+ [
3218
+ 0.191814124584198,
3219
+ 0.007811395917087793,
3220
+ 0.20961053669452667,
3221
+ 176.0531463623047,
3222
+ -0.003147333627566695,
3223
+ 90.02890014648438,
3224
+ 0.409576952457428
3225
+ ],
3226
+ [
3227
+ 0.19489523768424988,
3228
+ 0.008414356037974358,
3229
+ 0.20946261286735535,
3230
+ 176.0500946044922,
3231
+ -0.0037130373530089855,
3232
+ 90.02975463867188,
3233
+ 0.32769688963890076
3234
+ ]
3235
+ ],
3236
+ [
3237
+ [
3238
+ 0.15320706367492676,
3239
+ 0.003877518232911825,
3240
+ 0.2095641791820526,
3241
+ 176.0668487548828,
3242
+ -0.001166658359579742,
3243
+ 90.01170349121094,
3244
+ 0.6711252927780151
3245
+ ],
3246
+ [
3247
+ 0.1566144973039627,
3248
+ 0.004569030366837978,
3249
+ 0.20953533053398132,
3250
+ 176.06362915039062,
3251
+ -0.0020470903255045414,
3252
+ 90.01277160644531,
3253
+ 0.843066930770874
3254
+ ],
3255
+ [
3256
+ 0.16024918854236603,
3257
+ 0.00502287270501256,
3258
+ 0.20954887568950653,
3259
+ 176.0618896484375,
3260
+ -0.0027252447325736284,
3261
+ 90.01306915283203,
3262
+ 0.8675051331520081
3263
+ ],
3264
+ [
3265
+ 0.16360752284526825,
3266
+ 0.0056188576854765415,
3267
+ 0.20952168107032776,
3268
+ 176.06117248535156,
3269
+ -0.0028743562288582325,
3270
+ 90.01525115966797,
3271
+ 0.7952479720115662
3272
+ ],
3273
+ [
3274
+ 0.16767333447933197,
3275
+ 0.006405533291399479,
3276
+ 0.20970648527145386,
3277
+ 176.0563507080078,
3278
+ -0.002970325294882059,
3279
+ 90.01740264892578,
3280
+ 0.7962521910667419
3281
+ ],
3282
+ [
3283
+ 0.1707918345928192,
3284
+ 0.0068721105344593525,
3285
+ 0.2097848653793335,
3286
+ 176.05723571777344,
3287
+ -0.00312036438845098,
3288
+ 90.0158462524414,
3289
+ 0.757518470287323
3290
+ ],
3291
+ [
3292
+ 0.1740151196718216,
3293
+ 0.0074592093005776405,
3294
+ 0.20961347222328186,
3295
+ 176.0572967529297,
3296
+ -0.0039813644252717495,
3297
+ 90.01248931884766,
3298
+ 0.8143046498298645
3299
+ ],
3300
+ [
3301
+ 0.17717716097831726,
3302
+ 0.007950231432914734,
3303
+ 0.20968925952911377,
3304
+ 176.0526123046875,
3305
+ -0.00506437337026,
3306
+ 90.01351165771484,
3307
+ 0.8191958665847778
3308
+ ],
3309
+ [
3310
+ 0.1810409277677536,
3311
+ 0.008750645443797112,
3312
+ 0.2097550928592682,
3313
+ 176.05140686035156,
3314
+ -0.006298130378127098,
3315
+ 90.01214599609375,
3316
+ 0.8906230926513672
3317
+ ],
3318
+ [
3319
+ 0.1847178339958191,
3320
+ 0.009585577063262463,
3321
+ 0.20978476107120514,
3322
+ 176.05023193359375,
3323
+ -0.007116713095456362,
3324
+ 90.01170349121094,
3325
+ 0.8436222076416016
3326
+ ],
3327
+ [
3328
+ 0.18780097365379333,
3329
+ 0.010180408135056496,
3330
+ 0.20972739160060883,
3331
+ 176.04714965820312,
3332
+ -0.007670117076486349,
3333
+ 90.01290893554688,
3334
+ 0.6384347081184387
3335
+ ],
3336
+ [
3337
+ 0.19051514565944672,
3338
+ 0.010563481599092484,
3339
+ 0.20976945757865906,
3340
+ 176.04820251464844,
3341
+ -0.006965750828385353,
3342
+ 90.01403045654297,
3343
+ 0.7892048358917236
3344
+ ],
3345
+ [
3346
+ 0.19445815682411194,
3347
+ 0.011537492275238037,
3348
+ 0.21000604331493378,
3349
+ 176.04360961914062,
3350
+ -0.008108519949018955,
3351
+ 90.0125732421875,
3352
+ 0.7036859393119812
3353
+ ],
3354
+ [
3355
+ 0.19760701060295105,
3356
+ 0.012063547968864441,
3357
+ 0.20986729860305786,
3358
+ 176.0408477783203,
3359
+ -0.008672082796692848,
3360
+ 90.01353454589844,
3361
+ 0.8137848377227783
3362
+ ],
3363
+ [
3364
+ 0.20081570744514465,
3365
+ 0.012924863956868649,
3366
+ 0.2099616974592209,
3367
+ 176.03785705566406,
3368
+ -0.008717702701687813,
3369
+ 90.0132827758789,
3370
+ 0.7565792202949524
3371
+ ],
3372
+ [
3373
+ 0.20393992960453033,
3374
+ 0.013328734785318375,
3375
+ 0.21003961563110352,
3376
+ 176.03724670410156,
3377
+ -0.008869550190865993,
3378
+ 90.0144271850586,
3379
+ 0.5986968278884888
3380
+ ]
3381
+ ],
3382
+ [
3383
+ [
3384
+ 0.15570738911628723,
3385
+ 0.004031960386782885,
3386
+ 0.20950137078762054,
3387
+ 176.06748962402344,
3388
+ 0.0008320023771375418,
3389
+ 90.02385711669922,
3390
+ 0.26037225127220154
3391
+ ],
3392
+ [
3393
+ 0.1596946120262146,
3394
+ 0.0049184272065758705,
3395
+ 0.20922081172466278,
3396
+ 176.0600128173828,
3397
+ -0.0004946738481521606,
3398
+ 90.03562927246094,
3399
+ 0.3610609173774719
3400
+ ],
3401
+ [
3402
+ 0.16316814720630646,
3403
+ 0.0051771411672234535,
3404
+ 0.20932269096374512,
3405
+ 176.0504913330078,
3406
+ 0.00031913636485114694,
3407
+ 90.04635620117188,
3408
+ 0.4131803512573242
3409
+ ],
3410
+ [
3411
+ 0.16617445647716522,
3412
+ 0.005922356154769659,
3413
+ 0.20914535224437714,
3414
+ 176.04766845703125,
3415
+ 0.0007085510296747088,
3416
+ 90.05162048339844,
3417
+ 0.25813931226730347
3418
+ ],
3419
+ [
3420
+ 0.16922764480113983,
3421
+ 0.00679750507697463,
3422
+ 0.2091502845287323,
3423
+ 176.04852294921875,
3424
+ -0.0003173237491864711,
3425
+ 90.05496215820312,
3426
+ 0.33611470460891724
3427
+ ],
3428
+ [
3429
+ 0.17232975363731384,
3430
+ 0.007941234856843948,
3431
+ 0.20914505422115326,
3432
+ 176.04612731933594,
3433
+ -0.0014954834477975965,
3434
+ 90.05684661865234,
3435
+ 0.3006240725517273
3436
+ ],
3437
+ [
3438
+ 0.17566494643688202,
3439
+ 0.00892396830022335,
3440
+ 0.20918969810009003,
3441
+ 176.04808044433594,
3442
+ -0.00037949191755615175,
3443
+ 90.06536102294922,
3444
+ 0.30304014682769775
3445
+ ],
3446
+ [
3447
+ 0.1784704029560089,
3448
+ 0.009752323850989342,
3449
+ 0.20918208360671997,
3450
+ 176.0474090576172,
3451
+ -0.0005751223070546985,
3452
+ 90.07138061523438,
3453
+ 0.35009118914604187
3454
+ ],
3455
+ [
3456
+ 0.1819218546152115,
3457
+ 0.010791818611323833,
3458
+ 0.2091527283191681,
3459
+ 176.04249572753906,
3460
+ -0.0007570591405965388,
3461
+ 90.07756805419922,
3462
+ 0.2684592306613922
3463
+ ],
3464
+ [
3465
+ 0.18544505536556244,
3466
+ 0.012088554911315441,
3467
+ 0.20915399491786957,
3468
+ 176.04083251953125,
3469
+ -0.002598742488771677,
3470
+ 90.07618713378906,
3471
+ 0.48995068669319153
3472
+ ],
3473
+ [
3474
+ 0.18818335235118866,
3475
+ 0.013036024756729603,
3476
+ 0.20932374894618988,
3477
+ 176.0377655029297,
3478
+ -0.0022734468802809715,
3479
+ 90.08090209960938,
3480
+ 0.2815437316894531
3481
+ ],
3482
+ [
3483
+ 0.19041289389133453,
3484
+ 0.014055602252483368,
3485
+ 0.20929141342639923,
3486
+ 176.04513549804688,
3487
+ -0.001175259705632925,
3488
+ 90.08084869384766,
3489
+ 0.304794579744339
3490
+ ],
3491
+ [
3492
+ 0.19379822909832,
3493
+ 0.015518001280725002,
3494
+ 0.2092347890138626,
3495
+ 176.03819274902344,
3496
+ -0.00430992292240262,
3497
+ 90.0817642211914,
3498
+ 0.22246555984020233
3499
+ ],
3500
+ [
3501
+ 0.19677460193634033,
3502
+ 0.016914932057261467,
3503
+ 0.2091177999973297,
3504
+ 176.03799438476562,
3505
+ -0.0033689693082123995,
3506
+ 90.0866928100586,
3507
+ 0.15583205223083496
3508
+ ],
3509
+ [
3510
+ 0.19934877753257751,
3511
+ 0.018543174490332603,
3512
+ 0.20896847546100616,
3513
+ 176.03729248046875,
3514
+ -0.003937090281397104,
3515
+ 90.08851623535156,
3516
+ 0.1489855796098709
3517
+ ],
3518
+ [
3519
+ 0.20130197703838348,
3520
+ 0.019675541669130325,
3521
+ 0.2090020775794983,
3522
+ 176.0382843017578,
3523
+ -0.004012223798781633,
3524
+ 90.09304809570312,
3525
+ 0.25474265217781067
3526
+ ]
3527
+ ],
3528
+ [
3529
+ [
3530
+ 0.15965940058231354,
3531
+ 0.0043397825211286545,
3532
+ 0.209621861577034,
3533
+ 176.0689239501953,
3534
+ -0.0011879531666636467,
3535
+ 90.02320098876953,
3536
+ 0.6312397122383118
3537
+ ],
3538
+ [
3539
+ 0.16217365860939026,
3540
+ 0.0043952446430921555,
3541
+ 0.20965008437633514,
3542
+ 176.06741333007812,
3543
+ -0.0007959406357258558,
3544
+ 90.02256774902344,
3545
+ 0.560364842414856
3546
+ ],
3547
+ [
3548
+ 0.1667148470878601,
3549
+ 0.004959119483828545,
3550
+ 0.2096257358789444,
3551
+ 176.06631469726562,
3552
+ -0.0010053787846118212,
3553
+ 90.02458953857422,
3554
+ 0.6710071563720703
3555
+ ],
3556
+ [
3557
+ 0.16926433145999908,
3558
+ 0.00525676179677248,
3559
+ 0.2097669392824173,
3560
+ 176.0628204345703,
3561
+ -0.002619990846142173,
3562
+ 90.02403259277344,
3563
+ 0.8193199038505554
3564
+ ],
3565
+ [
3566
+ 0.17260019481182098,
3567
+ 0.005627262871712446,
3568
+ 0.2096869796514511,
3569
+ 176.06051635742188,
3570
+ -0.0023580575361847878,
3571
+ 90.02559661865234,
3572
+ 0.6407030820846558
3573
+ ],
3574
+ [
3575
+ 0.17537415027618408,
3576
+ 0.005928244441747665,
3577
+ 0.20979009568691254,
3578
+ 176.06105041503906,
3579
+ -0.0029288141522556543,
3580
+ 90.02571105957031,
3581
+ 0.5887490510940552
3582
+ ],
3583
+ [
3584
+ 0.1782412827014923,
3585
+ 0.006451264023780823,
3586
+ 0.2097741812467575,
3587
+ 176.06076049804688,
3588
+ -0.0031277562957257032,
3589
+ 90.02436065673828,
3590
+ 0.5876089334487915
3591
+ ],
3592
+ [
3593
+ 0.18165722489356995,
3594
+ 0.006829468533396721,
3595
+ 0.20969098806381226,
3596
+ 176.0586395263672,
3597
+ -0.00429123267531395,
3598
+ 90.02703857421875,
3599
+ 0.5860849022865295
3600
+ ],
3601
+ [
3602
+ 0.185263529419899,
3603
+ 0.007085599936544895,
3604
+ 0.20965443551540375,
3605
+ 176.05691528320312,
3606
+ -0.0043725185096263885,
3607
+ 90.02728271484375,
3608
+ 0.5322582125663757
3609
+ ],
3610
+ [
3611
+ 0.18779006600379944,
3612
+ 0.007498227991163731,
3613
+ 0.2097581923007965,
3614
+ 176.0555419921875,
3615
+ -0.0049880146980285645,
3616
+ 90.02754211425781,
3617
+ 0.6229104995727539
3618
+ ],
3619
+ [
3620
+ 0.19105805456638336,
3621
+ 0.007973063737154007,
3622
+ 0.20969772338867188,
3623
+ 176.0548553466797,
3624
+ -0.005742683075368404,
3625
+ 90.0288314819336,
3626
+ 0.5579782724380493
3627
+ ],
3628
+ [
3629
+ 0.19413703680038452,
3630
+ 0.008566942065954208,
3631
+ 0.2096378654241562,
3632
+ 176.05535888671875,
3633
+ -0.005284748040139675,
3634
+ 90.03034973144531,
3635
+ 0.5289738178253174
3636
+ ],
3637
+ [
3638
+ 0.197028249502182,
3639
+ 0.009145704098045826,
3640
+ 0.20970022678375244,
3641
+ 176.05313110351562,
3642
+ -0.0053259809501469135,
3643
+ 90.03465270996094,
3644
+ 0.5114293694496155
3645
+ ],
3646
+ [
3647
+ 0.20025233924388885,
3648
+ 0.009961273521184921,
3649
+ 0.20975342392921448,
3650
+ 176.0496826171875,
3651
+ -0.005832890048623085,
3652
+ 90.0359878540039,
3653
+ 0.453940212726593
3654
+ ],
3655
+ [
3656
+ 0.20342357456684113,
3657
+ 0.010857763700187206,
3658
+ 0.20972304046154022,
3659
+ 176.04771423339844,
3660
+ -0.005916388239711523,
3661
+ 90.03768157958984,
3662
+ 0.4093288481235504
3663
+ ],
3664
+ [
3665
+ 0.20566204190254211,
3666
+ 0.011463065631687641,
3667
+ 0.20958004891872406,
3668
+ 176.0487823486328,
3669
+ -0.006741437129676342,
3670
+ 90.04026794433594,
3671
+ 0.462369829416275
3672
+ ]
3673
+ ],
3674
+ [
3675
+ [
3676
+ 0.1627015769481659,
3677
+ 0.004767170641571283,
3678
+ 0.20974454283714294,
3679
+ 176.0701446533203,
3680
+ -0.002045096829533577,
3681
+ 90.0233154296875,
3682
+ 0.7582746148109436
3683
+ ],
3684
+ [
3685
+ 0.16562864184379578,
3686
+ 0.0051562669686973095,
3687
+ 0.20952576398849487,
3688
+ 176.06871032714844,
3689
+ -0.0027279285714030266,
3690
+ 90.0236587524414,
3691
+ 0.8048058152198792
3692
+ ],
3693
+ [
3694
+ 0.1691281944513321,
3695
+ 0.00562769640237093,
3696
+ 0.20948272943496704,
3697
+ 176.0654296875,
3698
+ -0.0032336099538952112,
3699
+ 90.02269744873047,
3700
+ 0.8207907676696777
3701
+ ],
3702
+ [
3703
+ 0.171921968460083,
3704
+ 0.006076496094465256,
3705
+ 0.2094859629869461,
3706
+ 176.06527709960938,
3707
+ -0.003252998925745487,
3708
+ 90.02222442626953,
3709
+ 0.8254575133323669
3710
+ ],
3711
+ [
3712
+ 0.17476625740528107,
3713
+ 0.006483426317572594,
3714
+ 0.20935216546058655,
3715
+ 176.0651092529297,
3716
+ -0.004123971797525883,
3717
+ 90.01970672607422,
3718
+ 0.7532180547714233
3719
+ ],
3720
+ [
3721
+ 0.17783357203006744,
3722
+ 0.006940271705389023,
3723
+ 0.20938663184642792,
3724
+ 176.0624542236328,
3725
+ -0.0038694136310368776,
3726
+ 90.02134704589844,
3727
+ 0.7255072593688965
3728
+ ],
3729
+ [
3730
+ 0.18114420771598816,
3731
+ 0.007429271470755339,
3732
+ 0.20929883420467377,
3733
+ 176.0595703125,
3734
+ -0.003606880782172084,
3735
+ 90.02422332763672,
3736
+ 0.7561952471733093
3737
+ ],
3738
+ [
3739
+ 0.18437445163726807,
3740
+ 0.008040769957005978,
3741
+ 0.20931850373744965,
3742
+ 176.05868530273438,
3743
+ -0.00382827571593225,
3744
+ 90.02410888671875,
3745
+ 0.6625480055809021
3746
+ ],
3747
+ [
3748
+ 0.18748801946640015,
3749
+ 0.00863991491496563,
3750
+ 0.20934908092021942,
3751
+ 176.05992126464844,
3752
+ -0.004143931902945042,
3753
+ 90.02449035644531,
3754
+ 0.7723160982131958
3755
+ ],
3756
+ [
3757
+ 0.19126126170158386,
3758
+ 0.009501046501100063,
3759
+ 0.20913909375667572,
3760
+ 176.0572052001953,
3761
+ -0.004465906415134668,
3762
+ 90.02906799316406,
3763
+ 0.4436911940574646
3764
+ ],
3765
+ [
3766
+ 0.19416716694831848,
3767
+ 0.010205825790762901,
3768
+ 0.20915868878364563,
3769
+ 176.05453491210938,
3770
+ -0.004463860299438238,
3771
+ 90.027587890625,
3772
+ 0.5903676152229309
3773
+ ],
3774
+ [
3775
+ 0.19717185199260712,
3776
+ 0.010860432870686054,
3777
+ 0.2091618925333023,
3778
+ 176.05538940429688,
3779
+ -0.005199267994612455,
3780
+ 90.02757263183594,
3781
+ 0.6078943610191345
3782
+ ],
3783
+ [
3784
+ 0.20031048357486725,
3785
+ 0.011642749421298504,
3786
+ 0.20912106335163116,
3787
+ 176.05511474609375,
3788
+ -0.005928014405071735,
3789
+ 90.02796173095703,
3790
+ 0.6361249685287476
3791
+ ],
3792
+ [
3793
+ 0.20392723381519318,
3794
+ 0.01258503645658493,
3795
+ 0.20941230654716492,
3796
+ 176.0525360107422,
3797
+ -0.006043020635843277,
3798
+ 90.02578735351562,
3799
+ 0.5885009169578552
3800
+ ],
3801
+ [
3802
+ 0.2072317898273468,
3803
+ 0.013506201095879078,
3804
+ 0.20940367877483368,
3805
+ 176.049560546875,
3806
+ -0.006071696989238262,
3807
+ 90.02678680419922,
3808
+ 0.5975212454795837
3809
+ ],
3810
+ [
3811
+ 0.2100575864315033,
3812
+ 0.014562325552105904,
3813
+ 0.2093134969472885,
3814
+ 176.0478973388672,
3815
+ -0.0073579587042331696,
3816
+ 90.0262680053711,
3817
+ 0.6309738755226135
3818
+ ]
3819
+ ],
3820
+ [
3821
+ [
3822
+ 0.1651243418455124,
3823
+ 0.004650649148970842,
3824
+ 0.2099265307188034,
3825
+ 176.0723419189453,
3826
+ -0.0020860014483332634,
3827
+ 90.02278900146484,
3828
+ 0.6095306873321533
3829
+ ],
3830
+ [
3831
+ 0.16753995418548584,
3832
+ 0.004822032991796732,
3833
+ 0.20993070304393768,
3834
+ 176.07127380371094,
3835
+ -0.0024738460779190063,
3836
+ 90.02287292480469,
3837
+ 0.674486517906189
3838
+ ],
3839
+ [
3840
+ 0.1708865463733673,
3841
+ 0.005058744922280312,
3842
+ 0.2098793387413025,
3843
+ 176.068359375,
3844
+ -0.0024691452272236347,
3845
+ 90.0244140625,
3846
+ 0.5181872248649597
3847
+ ],
3848
+ [
3849
+ 0.1745997816324234,
3850
+ 0.0053174421191215515,
3851
+ 0.20972159504890442,
3852
+ 176.0693817138672,
3853
+ -0.0028478067833930254,
3854
+ 90.02423858642578,
3855
+ 0.7765102386474609
3856
+ ],
3857
+ [
3858
+ 0.17773738503456116,
3859
+ 0.005469720344990492,
3860
+ 0.20982065796852112,
3861
+ 176.06507873535156,
3862
+ -0.0025920160114765167,
3863
+ 90.02468872070312,
3864
+ 0.6843870282173157
3865
+ ],
3866
+ [
3867
+ 0.18066078424453735,
3868
+ 0.00577480299398303,
3869
+ 0.20992393791675568,
3870
+ 176.06198120117188,
3871
+ -0.003113750834017992,
3872
+ 90.02423095703125,
3873
+ 0.7013289332389832
3874
+ ],
3875
+ [
3876
+ 0.1831689178943634,
3877
+ 0.006065744441002607,
3878
+ 0.20992209017276764,
3879
+ 176.05795288085938,
3880
+ -0.0030602707993239164,
3881
+ 90.02643585205078,
3882
+ 0.518021821975708
3883
+ ],
3884
+ [
3885
+ 0.18636475503444672,
3886
+ 0.006411133334040642,
3887
+ 0.20998111367225647,
3888
+ 176.05857849121094,
3889
+ -0.003373814281076193,
3890
+ 90.02595520019531,
3891
+ 0.379337877035141
3892
+ ],
3893
+ [
3894
+ 0.1895712912082672,
3895
+ 0.006721135228872299,
3896
+ 0.20990917086601257,
3897
+ 176.0587158203125,
3898
+ -0.0028866035863757133,
3899
+ 90.02997589111328,
3900
+ 0.4883025586605072
3901
+ ],
3902
+ [
3903
+ 0.19290366768836975,
3904
+ 0.007123997900635004,
3905
+ 0.21008679270744324,
3906
+ 176.05540466308594,
3907
+ -0.0034077009186148643,
3908
+ 90.02896118164062,
3909
+ 0.5834147930145264
3910
+ ],
3911
+ [
3912
+ 0.19599564373493195,
3913
+ 0.007611199282109737,
3914
+ 0.210096538066864,
3915
+ 176.0533447265625,
3916
+ -0.003941349685192108,
3917
+ 90.03162384033203,
3918
+ 0.4957633912563324
3919
+ ],
3920
+ [
3921
+ 0.19921129941940308,
3922
+ 0.0080696577206254,
3923
+ 0.2101949006319046,
3924
+ 176.04644775390625,
3925
+ -0.00373558490537107,
3926
+ 90.03898620605469,
3927
+ 0.3913472592830658
3928
+ ],
3929
+ [
3930
+ 0.20198361575603485,
3931
+ 0.008670545183122158,
3932
+ 0.2100811004638672,
3933
+ 176.04823303222656,
3934
+ -0.004277922213077545,
3935
+ 90.03763580322266,
3936
+ 0.5152808427810669
3937
+ ],
3938
+ [
3939
+ 0.2047715038061142,
3940
+ 0.00912513304501772,
3941
+ 0.21017470955848694,
3942
+ 176.04974365234375,
3943
+ -0.0037934803403913975,
3944
+ 90.03868865966797,
3945
+ 0.48113709688186646
3946
+ ],
3947
+ [
3948
+ 0.20853449404239655,
3949
+ 0.009845931082963943,
3950
+ 0.21011631190776825,
3951
+ 176.0499725341797,
3952
+ -0.003713260404765606,
3953
+ 90.04168701171875,
3954
+ 0.383797824382782
3955
+ ],
3956
+ [
3957
+ 0.2110190987586975,
3958
+ 0.010597487911581993,
3959
+ 0.2101048082113266,
3960
+ 176.04354858398438,
3961
+ -0.004673217423260212,
3962
+ 90.04524230957031,
3963
+ 0.321653813123703
3964
+ ]
3965
+ ]
3966
+ ]
3967
+ }
bundle/artifacts/sim/pi_rollout_preview_3500.gif ADDED

Git LFS Details

  • SHA256: 5b86564a9b60a0e432ec9aed7efa2b79bf363f65d91b44bb94981db644aa1339
  • Pointer size: 132 Bytes
  • Size of remote file: 6.98 MB
bundle/artifacts/sim/pi_rollout_preview_3500_strip.png ADDED

Git LFS Details

  • SHA256: fda514eb97db8e04e99c9d4d036d210d4a83061f6c7625834956b7af591f3ef1
  • Pointer size: 132 Bytes
  • Size of remote file: 1.6 MB
bundle/artifacts/sim/real_start.png ADDED

Git LFS Details

  • SHA256: 648411de0e34a8e43cb172f4654bffb303748d8c5c08e656d2a9122a36a14cc0
  • Pointer size: 132 Bytes
  • Size of remote file: 1.75 MB
bundle/artifacts/sim/real_vs_scene_start.png ADDED

Git LFS Details

  • SHA256: af5240382c64e3ef42670a4b0890a2f45425e78330e4cae0b17a2ee858db000f
  • Pointer size: 132 Bytes
  • Size of remote file: 2.28 MB
bundle/artifacts/sim/recorded_motion.gif ADDED

Git LFS Details

  • SHA256: 12135fdb59e60d7f7246dd0b0718c087b0176f82ded90b4034ec3be2ba9df8f8
  • Pointer size: 132 Bytes
  • Size of remote file: 8.64 MB
bundle/artifacts/sim/scene_motion_fit.png ADDED

Git LFS Details

  • SHA256: 77300bcca13faffbcc9a9fb6f7c228a679f804a8731a6e1fea4313b38170bf94
  • Pointer size: 132 Bytes
  • Size of remote file: 1.69 MB
bundle/artifacts/sim/scene_start_render.png ADDED

Git LFS Details

  • SHA256: 431cd417f99bc16d5d9748c23f27ef64ef34495105b2d1cf7cf92a1056d54450
  • Pointer size: 132 Bytes
  • Size of remote file: 1.77 MB
bundle/artifacts/sim/session_20260327_165944_bear_scene_fit.json ADDED
@@ -0,0 +1,123 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ {
2
+ "session_root": "/workspace/data/teddybear_raw/session_20260327_165944_bear",
3
+ "sync_row_index": 0,
4
+ "azure_rgb_seq": 10,
5
+ "azure_depth_seq": 10,
6
+ "robot_seq": 37,
7
+ "rgb_path": "/workspace/data/teddybear_raw/session_20260327_165944_bear/azure_rgb/000010.jpg",
8
+ "depth_path": "/workspace/data/teddybear_raw/session_20260327_165944_bear/azure_depth/000010.png",
9
+ "table_corners_px": [
10
+ [
11
+ 192.0,
12
+ 138.0
13
+ ],
14
+ [
15
+ 1635.0,
16
+ 46.0
17
+ ],
18
+ [
19
+ 1712.0,
20
+ 787.0
21
+ ],
22
+ [
23
+ 185.0,
24
+ 858.0
25
+ ]
26
+ ],
27
+ "table_size_m": [
28
+ 1.52,
29
+ 0.76
30
+ ],
31
+ "camera_focal_px": 650.0,
32
+ "rvec": [
33
+ -0.09174914809320757,
34
+ 0.01916933742850816,
35
+ -0.052062912426137815
36
+ ],
37
+ "tvec": [
38
+ -0.045156570030564204,
39
+ -0.10354127538092003,
40
+ 0.6651521249148916
41
+ ],
42
+ "robot_base_world": [
43
+ 0.5,
44
+ 0.45,
45
+ -0.45
46
+ ],
47
+ "robot_base_yaw_rad": -2.0,
48
+ "sync_row": {
49
+ "t_sync_sec": 2.750489500002004,
50
+ "t_sync_wall_time_sec": 1774645185.553682,
51
+ "rgb_seq": 0,
52
+ "rgb_t_sec": 2.973579300014535,
53
+ "rgb_file": "rgb/000000.jpg",
54
+ "rgb_age_sec": -0.2230898000125307,
55
+ "depth_seq": 17,
56
+ "depth_t_sec": 2.750489500002004,
57
+ "depth_file": "depth/000017.png",
58
+ "depth_age_sec": 0.0,
59
+ "azure_rgb_seq": 10,
60
+ "azure_rgb_t_sec": 2.7677244000078645,
61
+ "azure_rgb_file": "azure_rgb/000010.jpg",
62
+ "azure_rgb_age_sec": -0.0172349000058602,
63
+ "azure_depth_seq": 10,
64
+ "azure_depth_t_sec": 2.7677244000078645,
65
+ "azure_depth_file": "azure_depth/000010.png",
66
+ "azure_depth_age_sec": -0.0172349000058602,
67
+ "robot_seq": 37,
68
+ "robot_t_sec": 2.7384919000032824,
69
+ "robot_age_sec": 0.0119975999987218,
70
+ "tool_x_m": 0.1304228156805038,
71
+ "tool_y_m": 0.0013459887122735,
72
+ "tool_z_m": 0.2086409330368042,
73
+ "tool_theta_x_deg": 176.00607299804688,
74
+ "tool_theta_y_deg": -0.0013248149771243,
75
+ "tool_theta_z_deg": 89.99845886230469,
76
+ "cam_x_m": NaN,
77
+ "cam_y_m": NaN,
78
+ "cam_z_m": NaN,
79
+ "q1_deg": 0.0008167303167283,
80
+ "q2_deg": 340.0004272460937,
81
+ "q3_deg": 180.00140380859375,
82
+ "q4_deg": 213.99542236328125,
83
+ "q5_deg": 359.9988708496094,
84
+ "q6_deg": 309.9989318847656,
85
+ "q7_deg": 90.00142669677734,
86
+ "gripper_pos": 4.80349588394165
87
+ },
88
+ "table_depth_mm": 975.0,
89
+ "box_height_m": 0.076,
90
+ "teddy_height_m": 0.099,
91
+ "box_world_polygon": [
92
+ [
93
+ 0.22150550362135488,
94
+ 0.24670163116856353,
95
+ 0.0
96
+ ],
97
+ [
98
+ 0.22071163420598972,
99
+ -0.09764576770064368,
100
+ 0.0
101
+ ],
102
+ [
103
+ 0.4771996794142288,
104
+ -0.10335451470612148,
105
+ 0.0
106
+ ],
107
+ [
108
+ 0.46592016136934344,
109
+ 0.23941644811537086,
110
+ 0.0
111
+ ]
112
+ ],
113
+ "teddy_world_center": [
114
+ 0.17440522310559595,
115
+ 0.10013784762023073,
116
+ 0.0
117
+ ],
118
+ "teddy_world_extent": [
119
+ 0.24986488552884822,
120
+ 0.2295185354746066,
121
+ 0.0
122
+ ]
123
+ }
bundle/artifacts/sim/teddy_mask_overlay.png ADDED

Git LFS Details

  • SHA256: a697af818423867ebe3fcf2468ed53fc4c63d528bbbf1350970abbf9a3183486
  • Pointer size: 132 Bytes
  • Size of remote file: 1.74 MB
bundle/code/openpi/pyproject.toml ADDED
@@ -0,0 +1,137 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ [project]
2
+ name = "openpi"
3
+ version = "0.1.0"
4
+ description = "Physical Intelligence open source repo"
5
+ readme = "README.md"
6
+ requires-python = ">=3.11"
7
+ license = { file = "LICENSE" }
8
+ dependencies = [
9
+ "augmax>=0.3.4",
10
+ "dm-tree>=0.1.8",
11
+ "einops>=0.8.0",
12
+ "equinox>=0.11.8",
13
+ "flatbuffers>=24.3.25",
14
+ "flax==0.10.2",
15
+ "fsspec[gcs]>=2024.6.0",
16
+ "gym-aloha>=0.1.1",
17
+ "imageio>=2.36.1",
18
+ "jax[cuda12]==0.5.3",
19
+ "jaxtyping==0.2.36",
20
+ "lerobot",
21
+ "ml_collections==1.0.0",
22
+ "numpy>=1.22.4,<2.0.0",
23
+ "numpydantic>=1.6.6",
24
+ "opencv-python>=4.10.0.84",
25
+ "openpi-client",
26
+ "orbax-checkpoint==0.11.13",
27
+ "pillow>=11.0.0",
28
+ "sentencepiece>=0.2.0",
29
+ "torch==2.7.1",
30
+ "tqdm-loggable>=0.2",
31
+ "typing-extensions>=4.12.2",
32
+ "tyro>=0.9.5",
33
+ "wandb>=0.19.1",
34
+ "filelock>=3.16.1",
35
+ "beartype==0.19.0",
36
+ "treescope>=0.1.7",
37
+ "transformers==4.53.2",
38
+ "rich>=14.0.0",
39
+ "polars>=1.30.0",
40
+ ]
41
+
42
+
43
+ [project.urls]
44
+ Repository = "https://github.com/Physical-Intelligence/openpi"
45
+
46
+ [dependency-groups]
47
+ dev = [
48
+ "pytest>=8.3.4",
49
+ "ruff>=0.8.6",
50
+ "pre-commit>=4.0.1",
51
+ "ipykernel>=6.29.5",
52
+ "ipywidgets>=8.1.5",
53
+ "matplotlib>=3.10.0",
54
+ "pynvml>=12.0.0",
55
+ ]
56
+ rlds = [
57
+ "dlimp",
58
+ "tensorflow-cpu==2.15.0",
59
+ "tensorflow-datasets==4.9.9",
60
+ ]
61
+
62
+ [tool.uv]
63
+ override-dependencies = ["ml-dtypes==0.4.1", "tensorstore==0.1.74"]
64
+
65
+ [tool.uv.sources]
66
+ openpi-client = { workspace = true }
67
+ lerobot = { git = "https://github.com/huggingface/lerobot", rev = "0cf864870cf29f4738d3ade893e6fd13fbd7cdb5" }
68
+ dlimp = { git = "https://github.com/kvablack/dlimp", rev = "ad72ce3a9b414db2185bc0b38461d4101a65477a" }
69
+
70
+ [tool.uv.workspace]
71
+ members = ["packages/*"]
72
+
73
+ [tool.ruff]
74
+ line-length = 120
75
+ target-version = "py311"
76
+ extend-exclude = ["docker", "third_party", "src/openpi/models_pytorch/transformers_replace/*"]
77
+
78
+ [tool.ruff.lint]
79
+ # https://docs.astral.sh/ruff/rules/
80
+ select = [
81
+ "B",
82
+ "C4",
83
+ "DTZ",
84
+ "E4",
85
+ "E7",
86
+ "E9",
87
+ "F",
88
+ "FBT",
89
+ "FURB",
90
+ "I",
91
+ "ICN",
92
+ "ISC",
93
+ "LOG",
94
+ "N",
95
+ "PD",
96
+ "PERF",
97
+ "PIE",
98
+ "PLC",
99
+ "PLE",
100
+ "PLR1",
101
+ "PLR5",
102
+ "PLW",
103
+ "PT",
104
+ "Q",
105
+ "RET",
106
+ "RUF",
107
+ "SIM",
108
+ "SLF",
109
+ "T10",
110
+ "T20",
111
+ "UP",
112
+ "W",
113
+ ]
114
+ ignore = [
115
+ "F722", # Conflicts with array typing.
116
+ "T201", # We use print statements.
117
+ "PD008", # Lots of false positives.
118
+ "ISC001", # Disabling to support ruff format.
119
+ "LOG015", # Use logger.info.
120
+ ]
121
+ unfixable = [
122
+ "B905", # Fix defaults to strict=False, which is not what we want.
123
+ ]
124
+
125
+ [tool.ruff.lint.isort]
126
+ force-single-line = true
127
+ force-sort-within-sections = true
128
+ single-line-exclusions = ["collections.abc", "typing", "typing_extensions"]
129
+ known-third-party = ["wandb"]
130
+
131
+ [build-system]
132
+ requires = ["hatchling"]
133
+ build-backend = "hatchling.build"
134
+
135
+ [tool.pytest.ini_options]
136
+ markers = ["manual: should be run manually."]
137
+ testpaths = ["src", "scripts", "packages"]
bundle/code/openpi/scripts/archive_teddybear_checkpoints_to_hf.sh ADDED
@@ -0,0 +1,89 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -uo pipefail
3
+
4
+ if [[ $# -lt 4 ]]; then
5
+ echo "usage: $0 <repo_id> <checkpoint_root> <status_log> <state_file> [interval_s]" >&2
6
+ exit 1
7
+ fi
8
+
9
+ REPO_ID="$1"
10
+ CHECKPOINT_ROOT="$2"
11
+ STATUS_LOG="$3"
12
+ STATE_FILE="$4"
13
+ INTERVAL_S="${5:-120}"
14
+
15
+ mkdir -p "$(dirname "$STATUS_LOG")"
16
+ mkdir -p "$(dirname "$STATE_FILE")"
17
+ touch "$STATE_FILE"
18
+
19
+ log() {
20
+ printf '%s | %s\n' "$(date -u +%FT%TZ)" "$*" >> "$STATUS_LOG"
21
+ }
22
+
23
+ already_done() {
24
+ grep -qx "$1" "$STATE_FILE" 2>/dev/null
25
+ }
26
+
27
+ mark_done() {
28
+ printf '%s\n' "$1" >> "$STATE_FILE"
29
+ }
30
+
31
+ checkpoint_ready() {
32
+ local step="$1"
33
+ local src="${CHECKPOINT_ROOT}/${step}"
34
+ [[ -f "${src}/_CHECKPOINT_METADATA" && -f "${src}/params/_METADATA" ]]
35
+ }
36
+
37
+ verify_remote_step() {
38
+ local step="$1"
39
+ local verify_dir="/workspace/hf_verify_${step}"
40
+ rm -rf "$verify_dir"
41
+ mkdir -p "$verify_dir"
42
+ hf download "$REPO_ID" "${step}/_CHECKPOINT_METADATA" --type model --local-dir "$verify_dir" >/dev/null
43
+ hf download "$REPO_ID" "${step}/params/_METADATA" --type model --local-dir "$verify_dir" >/dev/null
44
+ }
45
+
46
+ archive_step() {
47
+ local step="$1"
48
+ local src="${CHECKPOINT_ROOT}/${step}"
49
+ local stage="/workspace/hf_stage_${step}"
50
+
51
+ if [[ ! -d "$src" ]]; then
52
+ log "skip step=${step} missing_local_dir"
53
+ return 0
54
+ fi
55
+
56
+ rm -rf "$stage"
57
+ mkdir -p "$stage"
58
+ cp -al "$src" "$stage/"
59
+ log "upload_start step=${step}"
60
+ hf upload-large-folder "$REPO_ID" "$stage" --type model --num-workers 8 --no-bars >> "$STATUS_LOG" 2>&1
61
+ verify_remote_step "$step"
62
+ rm -rf "$src" "$stage"
63
+ mark_done "$step"
64
+ log "upload_done step=${step}"
65
+ }
66
+
67
+ log "archiver_start repo=${REPO_ID} root=${CHECKPOINT_ROOT}"
68
+
69
+ while true; do
70
+ if [[ ! -d "$CHECKPOINT_ROOT" ]]; then
71
+ log "checkpoint_root_missing"
72
+ sleep "$INTERVAL_S"
73
+ continue
74
+ fi
75
+
76
+ while IFS= read -r step; do
77
+ [[ -z "$step" ]] && continue
78
+ if already_done "$step"; then
79
+ continue
80
+ fi
81
+ if ! checkpoint_ready "$step"; then
82
+ log "skip step=${step} checkpoint_not_ready"
83
+ continue
84
+ fi
85
+ archive_step "$step" || log "upload_failed step=${step}"
86
+ done < <(find "$CHECKPOINT_ROOT" -maxdepth 1 -mindepth 1 -type d -printf '%f\n' | rg '^[0-9]+$' | sort -n)
87
+
88
+ sleep "$INTERVAL_S"
89
+ done
bundle/code/openpi/scripts/bench_first_kinova_batch.py ADDED
@@ -0,0 +1,28 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import dataclasses
2
+ import os
3
+ import time
4
+
5
+ from openpi.training import config as c
6
+ from openpi.training import data_loader as dl
7
+
8
+
9
+ def main() -> None:
10
+ workers = int(os.environ.get("KINOVA_BENCH_WORKERS", "12"))
11
+ batch_size = int(os.environ.get("KINOVA_BENCH_BATCH_SIZE", "24"))
12
+ cfg = dataclasses.replace(
13
+ c.get_config("pi05_kinova_teddybear"),
14
+ exp_name=f"bench_first_b{batch_size}_w{workers}",
15
+ batch_size=batch_size,
16
+ num_workers=workers,
17
+ )
18
+ print({"workers": workers, "batch_size": batch_size}, flush=True)
19
+ t0 = time.time()
20
+ loader = dl.create_data_loader(cfg, shuffle=False, num_batches=1)
21
+ print({"loader_created_s": round(time.time() - t0, 3)}, flush=True)
22
+ t1 = time.time()
23
+ _ = next(iter(loader))
24
+ print({"first_batch_s": round(time.time() - t1, 3)}, flush=True)
25
+
26
+
27
+ if __name__ == "__main__":
28
+ main()
bundle/code/openpi/scripts/bench_kinova_loader.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import dataclasses
2
+ import time
3
+
4
+ from openpi.training import config as c
5
+ from openpi.training import data_loader as dl
6
+
7
+
8
+ def main() -> None:
9
+ for workers in [16, 32, 48]:
10
+ cfg = dataclasses.replace(
11
+ c.get_config("pi05_kinova_teddybear"),
12
+ exp_name=f"bench_{workers}",
13
+ num_workers=workers,
14
+ )
15
+ t0 = time.time()
16
+ loader = dl.create_data_loader(cfg, shuffle=True, num_batches=6, skip_norm_stats=True)
17
+ loader_s = time.time() - t0
18
+
19
+ it = iter(loader)
20
+ t1 = time.time()
21
+ first_batch_s = None
22
+ for i in range(6):
23
+ _ = next(it)
24
+ if i == 0:
25
+ first_batch_s = time.time() - t1
26
+ total_s = time.time() - t1
27
+ print(
28
+ {
29
+ "workers": workers,
30
+ "loader_s": round(loader_s, 3),
31
+ "first_batch_s": round(first_batch_s or 0.0, 3),
32
+ "avg_batch_s": round(total_s / 6, 3),
33
+ },
34
+ flush=True,
35
+ )
36
+
37
+
38
+ if __name__ == "__main__":
39
+ main()
bundle/code/openpi/scripts/compute_norm_stats_kinova_teddybear.py ADDED
@@ -0,0 +1,58 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """Compute norm stats for the Kinova TeddyBear dataset without decoding videos.
2
+
3
+ This matches the training-time state/action preprocessing for the custom
4
+ `pi05_kinova_teddybear` config:
5
+ - state stats are computed on raw `observation.state`
6
+ - action stats are computed on 16-step action chunks after converting the
7
+ first 6 dimensions from absolute targets to deltas relative to the current state
8
+ while leaving the gripper dimension absolute
9
+ """
10
+
11
+ from pathlib import Path
12
+
13
+ import numpy as np
14
+ import pandas as pd
15
+
16
+ from openpi.shared import normalize
17
+ from openpi.training import config as config_lib
18
+ from openpi.training.kinova_lerobot_v3_dataset import locate_dataset_root
19
+
20
+
21
+ def main() -> None:
22
+ cfg = config_lib.get_config("pi05_kinova_teddybear")
23
+ repo_id = "lsnu/TeddyBearKinovaTestSetLeRobot"
24
+ root = locate_dataset_root()
25
+
26
+ data_df = pd.concat(
27
+ [pd.read_parquet(path) for path in sorted((root / "data").rglob("*.parquet"))],
28
+ ignore_index=True,
29
+ ).sort_values("index")
30
+
31
+ state_stats = normalize.RunningStats()
32
+ action_stats = normalize.RunningStats()
33
+ horizon = cfg.model.action_horizon
34
+
35
+ for _, ep_rows in data_df.groupby("episode_index", sort=True):
36
+ states = np.stack(ep_rows["observation.state"].to_list()).astype(np.float32)
37
+ actions = np.stack(ep_rows["action"].to_list()).astype(np.float32)
38
+ length = len(states)
39
+
40
+ state_stats.update(states)
41
+
42
+ idx = np.arange(length)[:, None] + np.arange(horizon)[None, :]
43
+ idx = np.clip(idx, 0, length - 1)
44
+ action_chunks = actions[idx]
45
+ action_chunks[..., :6] -= states[:, None, :6]
46
+ action_stats.update(action_chunks)
47
+
48
+ output_path = cfg.assets_dirs / repo_id
49
+ norm_stats = {
50
+ "state": state_stats.get_statistics(),
51
+ "actions": action_stats.get_statistics(),
52
+ }
53
+ print(f"Writing stats to: {output_path}")
54
+ normalize.save(output_path, norm_stats)
55
+
56
+
57
+ if __name__ == "__main__":
58
+ main()
bundle/code/openpi/scripts/serve_policy.py ADDED
@@ -0,0 +1,122 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import dataclasses
2
+ import enum
3
+ import logging
4
+ import socket
5
+
6
+ import tyro
7
+
8
+ from openpi.policies import policy as _policy
9
+ from openpi.policies import policy_config as _policy_config
10
+ from openpi.serving import websocket_policy_server
11
+ from openpi.training import config as _config
12
+
13
+
14
+ class EnvMode(enum.Enum):
15
+ """Supported environments."""
16
+
17
+ ALOHA = "aloha"
18
+ ALOHA_SIM = "aloha_sim"
19
+ DROID = "droid"
20
+ LIBERO = "libero"
21
+
22
+
23
+ @dataclasses.dataclass
24
+ class Checkpoint:
25
+ """Load a policy from a trained checkpoint."""
26
+
27
+ # Training config name (e.g., "pi0_aloha_sim").
28
+ config: str
29
+ # Checkpoint directory (e.g., "checkpoints/pi0_aloha_sim/exp/10000").
30
+ dir: str
31
+
32
+
33
+ @dataclasses.dataclass
34
+ class Default:
35
+ """Use the default policy for the given environment."""
36
+
37
+
38
+ @dataclasses.dataclass
39
+ class Args:
40
+ """Arguments for the serve_policy script."""
41
+
42
+ # Environment to serve the policy for. This is only used when serving default policies.
43
+ env: EnvMode = EnvMode.ALOHA_SIM
44
+
45
+ # If provided, will be used in case the "prompt" key is not present in the data, or if the model doesn't have a default
46
+ # prompt.
47
+ default_prompt: str | None = None
48
+
49
+ # Port to serve the policy on.
50
+ port: int = 8000
51
+ # Record the policy's behavior for debugging.
52
+ record: bool = False
53
+
54
+ # Specifies how to load the policy. If not provided, the default policy for the environment will be used.
55
+ policy: Checkpoint | Default = dataclasses.field(default_factory=Default)
56
+
57
+
58
+ # Default checkpoints that should be used for each environment.
59
+ DEFAULT_CHECKPOINT: dict[EnvMode, Checkpoint] = {
60
+ EnvMode.ALOHA: Checkpoint(
61
+ config="pi05_aloha",
62
+ dir="gs://openpi-assets/checkpoints/pi05_base",
63
+ ),
64
+ EnvMode.ALOHA_SIM: Checkpoint(
65
+ config="pi0_aloha_sim",
66
+ dir="gs://openpi-assets/checkpoints/pi0_aloha_sim",
67
+ ),
68
+ EnvMode.DROID: Checkpoint(
69
+ config="pi05_droid",
70
+ dir="gs://openpi-assets/checkpoints/pi05_droid",
71
+ ),
72
+ EnvMode.LIBERO: Checkpoint(
73
+ config="pi05_libero",
74
+ dir="gs://openpi-assets/checkpoints/pi05_libero",
75
+ ),
76
+ }
77
+
78
+
79
+ def create_default_policy(env: EnvMode, *, default_prompt: str | None = None) -> _policy.Policy:
80
+ """Create a default policy for the given environment."""
81
+ if checkpoint := DEFAULT_CHECKPOINT.get(env):
82
+ return _policy_config.create_trained_policy(
83
+ _config.get_config(checkpoint.config), checkpoint.dir, default_prompt=default_prompt
84
+ )
85
+ raise ValueError(f"Unsupported environment mode: {env}")
86
+
87
+
88
+ def create_policy(args: Args) -> _policy.Policy:
89
+ """Create a policy from the given arguments."""
90
+ match args.policy:
91
+ case Checkpoint():
92
+ return _policy_config.create_trained_policy(
93
+ _config.get_config(args.policy.config), args.policy.dir, default_prompt=args.default_prompt
94
+ )
95
+ case Default():
96
+ return create_default_policy(args.env, default_prompt=args.default_prompt)
97
+
98
+
99
+ def main(args: Args) -> None:
100
+ policy = create_policy(args)
101
+ policy_metadata = policy.metadata
102
+
103
+ # Record the policy's behavior.
104
+ if args.record:
105
+ policy = _policy.PolicyRecorder(policy, "policy_records")
106
+
107
+ hostname = socket.gethostname()
108
+ local_ip = socket.gethostbyname(hostname)
109
+ logging.info("Creating server (host: %s, ip: %s)", hostname, local_ip)
110
+
111
+ server = websocket_policy_server.WebsocketPolicyServer(
112
+ policy=policy,
113
+ host="0.0.0.0",
114
+ port=args.port,
115
+ metadata=policy_metadata,
116
+ )
117
+ server.serve_forever()
118
+
119
+
120
+ if __name__ == "__main__":
121
+ logging.basicConfig(level=logging.INFO, force=True)
122
+ main(tyro.cli(Args))
bundle/code/openpi/scripts/stop_train_at_checkpoint.sh ADDED
@@ -0,0 +1,44 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ if [[ $# -lt 3 ]]; then
5
+ echo "usage: $0 <pid> <checkpoint_root> <target_step> [status_log] [interval_s]" >&2
6
+ exit 1
7
+ fi
8
+
9
+ PID="$1"
10
+ CHECKPOINT_ROOT="$2"
11
+ TARGET_STEP="$3"
12
+ STATUS_LOG="${4:-/workspace/openpi/stop_at_checkpoint.log}"
13
+ INTERVAL_S="${5:-15}"
14
+
15
+ mkdir -p "$(dirname "$STATUS_LOG")"
16
+
17
+ log() {
18
+ printf '%s | %s\n' "$(date -u +%FT%TZ)" "$*" >> "$STATUS_LOG"
19
+ }
20
+
21
+ checkpoint_ready() {
22
+ local step="$1"
23
+ local src="${CHECKPOINT_ROOT}/${step}"
24
+ [[ -f "${src}/_CHECKPOINT_METADATA" && -f "${src}/params/_METADATA" ]]
25
+ }
26
+
27
+ log "watch_start pid=${PID} target_step=${TARGET_STEP} checkpoint_root=${CHECKPOINT_ROOT}"
28
+
29
+ while kill -0 "$PID" 2>/dev/null; do
30
+ if checkpoint_ready "$TARGET_STEP"; then
31
+ log "checkpoint_ready step=${TARGET_STEP}"
32
+ kill -TERM "$PID"
33
+ log "signal_sent signal=TERM pid=${PID}"
34
+ sleep 5
35
+ if kill -0 "$PID" 2>/dev/null; then
36
+ kill -INT "$PID"
37
+ log "signal_sent signal=INT pid=${PID}"
38
+ fi
39
+ exit 0
40
+ fi
41
+ sleep "$INTERVAL_S"
42
+ done
43
+
44
+ log "watch_end pid=${PID} process_not_running"
bundle/code/openpi/scripts/train.py ADDED
@@ -0,0 +1,280 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import dataclasses
2
+ import functools
3
+ import logging
4
+ import platform
5
+ from typing import Any
6
+
7
+ import etils.epath as epath
8
+ import flax.nnx as nnx
9
+ from flax.training import common_utils
10
+ import flax.traverse_util as traverse_util
11
+ import jax
12
+ import jax.experimental
13
+ import jax.numpy as jnp
14
+ import numpy as np
15
+ import optax
16
+ import tqdm_loggable.auto as tqdm
17
+ import wandb
18
+
19
+ import openpi.models.model as _model
20
+ import openpi.shared.array_typing as at
21
+ import openpi.shared.nnx_utils as nnx_utils
22
+ import openpi.training.checkpoints as _checkpoints
23
+ import openpi.training.config as _config
24
+ import openpi.training.data_loader as _data_loader
25
+ import openpi.training.optimizer as _optimizer
26
+ import openpi.training.sharding as sharding
27
+ import openpi.training.utils as training_utils
28
+ import openpi.training.weight_loaders as _weight_loaders
29
+
30
+
31
+ def init_logging():
32
+ """Custom logging format for better readability."""
33
+ level_mapping = {"DEBUG": "D", "INFO": "I", "WARNING": "W", "ERROR": "E", "CRITICAL": "C"}
34
+
35
+ class CustomFormatter(logging.Formatter):
36
+ def format(self, record):
37
+ record.levelname = level_mapping.get(record.levelname, record.levelname)
38
+ return super().format(record)
39
+
40
+ formatter = CustomFormatter(
41
+ fmt="%(asctime)s.%(msecs)03d [%(levelname)s] %(message)-80s (%(process)d:%(filename)s:%(lineno)s)",
42
+ datefmt="%H:%M:%S",
43
+ )
44
+
45
+ logger = logging.getLogger()
46
+ logger.setLevel(logging.INFO)
47
+ logger.handlers[0].setFormatter(formatter)
48
+
49
+
50
+ def init_wandb(config: _config.TrainConfig, *, resuming: bool, log_code: bool = False, enabled: bool = True):
51
+ if not enabled:
52
+ wandb.init(mode="disabled")
53
+ return
54
+
55
+ ckpt_dir = config.checkpoint_dir
56
+ if not ckpt_dir.exists():
57
+ raise FileNotFoundError(f"Checkpoint directory {ckpt_dir} does not exist.")
58
+ if resuming:
59
+ run_id = (ckpt_dir / "wandb_id.txt").read_text().strip()
60
+ wandb.init(id=run_id, resume="must", project=config.project_name)
61
+ else:
62
+ wandb.init(
63
+ name=config.exp_name,
64
+ config=dataclasses.asdict(config),
65
+ project=config.project_name,
66
+ )
67
+ (ckpt_dir / "wandb_id.txt").write_text(wandb.run.id)
68
+
69
+ if log_code:
70
+ wandb.run.log_code(epath.Path(__file__).parent.parent)
71
+
72
+
73
+ def _load_weights_and_validate(loader: _weight_loaders.WeightLoader, params_shape: at.Params) -> at.Params:
74
+ """Loads and validates the weights. Returns a loaded subset of the weights."""
75
+ loaded_params = loader.load(params_shape)
76
+ at.check_pytree_equality(expected=params_shape, got=loaded_params, check_shapes=True, check_dtypes=True)
77
+
78
+ # Remove jax.ShapeDtypeStruct from the loaded params. This makes sure that only the loaded params are returned.
79
+ return traverse_util.unflatten_dict(
80
+ {k: v for k, v in traverse_util.flatten_dict(loaded_params).items() if not isinstance(v, jax.ShapeDtypeStruct)}
81
+ )
82
+
83
+
84
+ @at.typecheck
85
+ def init_train_state(
86
+ config: _config.TrainConfig, init_rng: at.KeyArrayLike, mesh: jax.sharding.Mesh, *, resume: bool
87
+ ) -> tuple[training_utils.TrainState, Any]:
88
+ tx = _optimizer.create_optimizer(config.optimizer, config.lr_schedule, weight_decay_mask=None)
89
+
90
+ def init(rng: at.KeyArrayLike, partial_params: at.Params | None = None) -> training_utils.TrainState:
91
+ rng, model_rng = jax.random.split(rng)
92
+ # initialize the model (and its parameters).
93
+ model = config.model.create(model_rng)
94
+
95
+ # Merge the partial params into the model.
96
+ if partial_params is not None:
97
+ graphdef, state = nnx.split(model)
98
+ # This will produce an error if the partial params are not a subset of the state.
99
+ state.replace_by_pure_dict(partial_params)
100
+ model = nnx.merge(graphdef, state)
101
+
102
+ params = nnx.state(model)
103
+ # Convert frozen params to bfloat16.
104
+ params = nnx_utils.state_map(params, config.freeze_filter, lambda p: p.replace(p.value.astype(jnp.bfloat16)))
105
+
106
+ return training_utils.TrainState(
107
+ step=0,
108
+ params=params,
109
+ model_def=nnx.graphdef(model),
110
+ tx=tx,
111
+ opt_state=tx.init(params.filter(config.trainable_filter)),
112
+ ema_decay=config.ema_decay,
113
+ ema_params=None if config.ema_decay is None else params,
114
+ )
115
+
116
+ train_state_shape = jax.eval_shape(init, init_rng)
117
+ state_sharding = sharding.fsdp_sharding(train_state_shape, mesh, log=True)
118
+
119
+ if resume:
120
+ return train_state_shape, state_sharding
121
+
122
+ partial_params = _load_weights_and_validate(config.weight_loader, train_state_shape.params.to_pure_dict())
123
+ replicated_sharding = jax.sharding.NamedSharding(mesh, jax.sharding.PartitionSpec())
124
+
125
+ # Initialize the train state and mix in the partial params.
126
+ train_state = jax.jit(
127
+ init,
128
+ donate_argnums=(1,), # donate the partial params buffer.
129
+ in_shardings=replicated_sharding,
130
+ out_shardings=state_sharding,
131
+ )(init_rng, partial_params)
132
+
133
+ return train_state, state_sharding
134
+
135
+
136
+ @at.typecheck
137
+ def train_step(
138
+ config: _config.TrainConfig,
139
+ rng: at.KeyArrayLike,
140
+ state: training_utils.TrainState,
141
+ batch: tuple[_model.Observation, _model.Actions],
142
+ ) -> tuple[training_utils.TrainState, dict[str, at.Array]]:
143
+ model = nnx.merge(state.model_def, state.params)
144
+ model.train()
145
+
146
+ @at.typecheck
147
+ def loss_fn(
148
+ model: _model.BaseModel, rng: at.KeyArrayLike, observation: _model.Observation, actions: _model.Actions
149
+ ):
150
+ chunked_loss = model.compute_loss(rng, observation, actions, train=True)
151
+ return jnp.mean(chunked_loss)
152
+
153
+ train_rng = jax.random.fold_in(rng, state.step)
154
+ observation, actions = batch
155
+
156
+ # Filter out frozen params.
157
+ diff_state = nnx.DiffState(0, config.trainable_filter)
158
+ loss, grads = nnx.value_and_grad(loss_fn, argnums=diff_state)(model, train_rng, observation, actions)
159
+
160
+ params = state.params.filter(config.trainable_filter)
161
+ updates, new_opt_state = state.tx.update(grads, state.opt_state, params)
162
+ new_params = optax.apply_updates(params, updates)
163
+
164
+ # Update the model in place and return the new full state.
165
+ nnx.update(model, new_params)
166
+ new_params = nnx.state(model)
167
+
168
+ new_state = dataclasses.replace(state, step=state.step + 1, params=new_params, opt_state=new_opt_state)
169
+ if state.ema_decay is not None:
170
+ new_state = dataclasses.replace(
171
+ new_state,
172
+ ema_params=jax.tree.map(
173
+ lambda old, new: state.ema_decay * old + (1 - state.ema_decay) * new, state.ema_params, new_params
174
+ ),
175
+ )
176
+
177
+ # Filter out params that aren't kernels.
178
+ kernel_params = nnx.state(
179
+ model,
180
+ nnx.All(
181
+ nnx.Param,
182
+ nnx.Not(nnx_utils.PathRegex(".*/(bias|scale|pos_embedding|input_embedding)")),
183
+ lambda _, x: x.value.ndim > 1,
184
+ ),
185
+ )
186
+ info = {
187
+ "loss": loss,
188
+ "grad_norm": optax.global_norm(grads),
189
+ "param_norm": optax.global_norm(kernel_params),
190
+ }
191
+ return new_state, info
192
+
193
+
194
+ def main(config: _config.TrainConfig):
195
+ init_logging()
196
+ logging.info(f"Running on: {platform.node()}")
197
+
198
+ if config.batch_size % jax.device_count() != 0:
199
+ raise ValueError(
200
+ f"Batch size {config.batch_size} must be divisible by the number of devices {jax.device_count()}."
201
+ )
202
+
203
+ jax.config.update("jax_compilation_cache_dir", str(epath.Path("~/.cache/jax").expanduser()))
204
+
205
+ rng = jax.random.key(config.seed)
206
+ train_rng, init_rng = jax.random.split(rng)
207
+
208
+ mesh = sharding.make_mesh(config.fsdp_devices)
209
+ data_sharding = jax.sharding.NamedSharding(mesh, jax.sharding.PartitionSpec(sharding.DATA_AXIS))
210
+ replicated_sharding = jax.sharding.NamedSharding(mesh, jax.sharding.PartitionSpec())
211
+
212
+ checkpoint_manager, resuming = _checkpoints.initialize_checkpoint_dir(
213
+ config.checkpoint_dir,
214
+ keep_period=config.keep_period,
215
+ overwrite=config.overwrite,
216
+ resume=config.resume,
217
+ )
218
+ init_wandb(config, resuming=resuming, enabled=config.wandb_enabled)
219
+
220
+ data_loader = _data_loader.create_data_loader(
221
+ config,
222
+ sharding=data_sharding,
223
+ shuffle=True,
224
+ )
225
+ data_iter = iter(data_loader)
226
+ batch = next(data_iter)
227
+ logging.info(f"Initialized data loader:\n{training_utils.array_tree_to_info(batch)}")
228
+
229
+ # Log images from first batch to sanity check.
230
+ images_to_log = [
231
+ wandb.Image(np.concatenate([np.array(img[i]) for img in batch[0].images.values()], axis=1))
232
+ for i in range(min(5, len(next(iter(batch[0].images.values())))))
233
+ ]
234
+ wandb.log({"camera_views": images_to_log}, step=0)
235
+
236
+ train_state, train_state_sharding = init_train_state(config, init_rng, mesh, resume=resuming)
237
+ jax.block_until_ready(train_state)
238
+ logging.info(f"Initialized train state:\n{training_utils.array_tree_to_info(train_state.params)}")
239
+
240
+ if resuming:
241
+ train_state = _checkpoints.restore_state(checkpoint_manager, train_state, data_loader)
242
+
243
+ ptrain_step = jax.jit(
244
+ functools.partial(train_step, config),
245
+ in_shardings=(replicated_sharding, train_state_sharding, data_sharding),
246
+ out_shardings=(train_state_sharding, replicated_sharding),
247
+ donate_argnums=(1,),
248
+ )
249
+
250
+ start_step = int(train_state.step)
251
+ pbar = tqdm.tqdm(
252
+ range(start_step, config.num_train_steps),
253
+ initial=start_step,
254
+ total=config.num_train_steps,
255
+ dynamic_ncols=True,
256
+ )
257
+
258
+ infos = []
259
+ for step in pbar:
260
+ with sharding.set_mesh(mesh):
261
+ train_state, info = ptrain_step(train_rng, train_state, batch)
262
+ infos.append(info)
263
+ if step % config.log_interval == 0:
264
+ stacked_infos = common_utils.stack_forest(infos)
265
+ reduced_info = jax.device_get(jax.tree.map(jnp.mean, stacked_infos))
266
+ info_str = ", ".join(f"{k}={v:.4f}" for k, v in reduced_info.items())
267
+ pbar.write(f"Step {step}: {info_str}")
268
+ wandb.log(reduced_info, step=step)
269
+ infos = []
270
+ batch = next(data_iter)
271
+
272
+ if (step % config.save_interval == 0 and step > start_step) or step == config.num_train_steps - 1:
273
+ _checkpoints.save_state(checkpoint_manager, train_state, data_loader, step)
274
+
275
+ logging.info("Waiting for checkpoint manager to finish")
276
+ checkpoint_manager.wait_until_finished()
277
+
278
+
279
+ if __name__ == "__main__":
280
+ main(_config.cli())
bundle/code/openpi/scripts/watch_teddybear_train.sh ADDED
@@ -0,0 +1,49 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -uo pipefail
3
+
4
+ if [[ $# -lt 4 ]]; then
5
+ echo "usage: $0 <pid> <train_log> <checkpoint_dir> <status_log> [interval_s]" >&2
6
+ exit 1
7
+ fi
8
+
9
+ PID="$1"
10
+ TRAIN_LOG="$2"
11
+ CHECKPOINT_DIR="$3"
12
+ STATUS_LOG="$4"
13
+ INTERVAL_S="${5:-60}"
14
+
15
+ mkdir -p "$(dirname "$STATUS_LOG")"
16
+
17
+ latest_step_line() {
18
+ grep -oE 'Step [0-9]+:.*' "$TRAIN_LOG" | tail -n 1 || true
19
+ }
20
+
21
+ latest_gpu_line() {
22
+ nvidia-smi \
23
+ --query-gpu=utilization.gpu,utilization.memory,memory.used,memory.free \
24
+ --format=csv,noheader,nounits | head -n 1 || true
25
+ }
26
+
27
+ latest_ckpts() {
28
+ find "$CHECKPOINT_DIR" -maxdepth 1 -mindepth 1 -type d -printf '%f\n' 2>/dev/null \
29
+ | sort -n \
30
+ | tail -n 5 \
31
+ | paste -sd ',' -
32
+ }
33
+
34
+ printf 'watch start %s pid=%s\n' "$(date -u +%FT%TZ)" "$PID" >> "$STATUS_LOG"
35
+
36
+ while kill -0 "$PID" 2>/dev/null; do
37
+ STEP_LINE="$(latest_step_line || true)"
38
+ GPU_LINE="$(latest_gpu_line || true)"
39
+ CKPTS="$(latest_ckpts || true)"
40
+ printf '%s | %s | gpu=%s | ckpts=%s\n' \
41
+ "$(date -u +%FT%TZ)" \
42
+ "${STEP_LINE:-no_step_yet}" \
43
+ "${GPU_LINE:-na}" \
44
+ "${CKPTS:-none}" >> "$STATUS_LOG"
45
+ sleep "$INTERVAL_S" || true
46
+ done
47
+
48
+ printf 'watch end %s pid=%s\n' "$(date -u +%FT%TZ)" "$PID" >> "$STATUS_LOG"
49
+ tail -n 40 "$TRAIN_LOG" >> "$STATUS_LOG" || true
bundle/code/openpi/src/openpi/training/config.py ADDED
@@ -0,0 +1,1036 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ """See _CONFIGS for the list of available configs."""
2
+
3
+ import abc
4
+ from collections.abc import Sequence
5
+ import dataclasses
6
+ import difflib
7
+ import logging
8
+ import pathlib
9
+ from typing import Any, Literal, Protocol, TypeAlias
10
+
11
+ import etils.epath as epath
12
+ import flax.nnx as nnx
13
+ from typing_extensions import override
14
+ import tyro
15
+
16
+ import openpi.models.model as _model
17
+ import openpi.models.pi0_config as pi0_config
18
+ import openpi.models.pi0_fast as pi0_fast
19
+ import openpi.models.tokenizer as _tokenizer
20
+ import openpi.policies.aloha_policy as aloha_policy
21
+ import openpi.policies.droid_policy as droid_policy
22
+ import openpi.policies.libero_policy as libero_policy
23
+ import openpi.shared.download as _download
24
+ import openpi.shared.normalize as _normalize
25
+ import openpi.training.droid_rlds_dataset as droid_rlds_dataset
26
+ import openpi.training.misc.polaris_config as polaris_config
27
+ import openpi.training.misc.roboarena_config as roboarena_config
28
+ import openpi.training.optimizer as _optimizer
29
+ import openpi.training.weight_loaders as weight_loaders
30
+ import openpi.transforms as _transforms
31
+
32
+ ModelType: TypeAlias = _model.ModelType
33
+ # Work around a tyro issue with using nnx.filterlib.Filter directly.
34
+ Filter: TypeAlias = nnx.filterlib.Filter
35
+
36
+
37
+ @dataclasses.dataclass(frozen=True)
38
+ class AssetsConfig:
39
+ """Determines the location of assets (e.g., norm stats) that will be used to set up the data pipeline.
40
+
41
+ These assets will be replicated inside the checkpoint under the `assets/asset_id` directory.
42
+
43
+ This can be used to load assets from a different checkpoint (e.g., base model checkpoint) or some other
44
+ centralized location. For example, to load the norm stats for the Trossen robot from the base model checkpoint
45
+ during fine-tuning, use:
46
+
47
+ ```
48
+ AssetsConfig(
49
+ assets_dir="gs://openpi-assets/checkpoints/pi0_base/assets",
50
+ asset_id="trossen",
51
+ )
52
+ ```
53
+ """
54
+
55
+ # Assets directory. If not provided, the config assets_dirs will be used. This is useful to load assets from
56
+ # a different checkpoint (e.g., base model checkpoint) or some other centralized location.
57
+ assets_dir: str | None = None
58
+
59
+ # Asset id. If not provided, the repo id will be used. This allows users to reference assets that describe
60
+ # different robot platforms.
61
+ asset_id: str | None = None
62
+
63
+
64
+ @dataclasses.dataclass(frozen=True)
65
+ class DataConfig:
66
+ # LeRobot repo id. If None, fake data will be created.
67
+ repo_id: str | None = None
68
+ # Directory within the assets directory containing the data assets.
69
+ asset_id: str | None = None
70
+ # Contains precomputed normalization stats. If None, normalization will not be performed.
71
+ norm_stats: dict[str, _transforms.NormStats] | None = None
72
+
73
+ # Used to adopt the inputs from a dataset specific format to a common format
74
+ # which is expected by the data transforms.
75
+ repack_transforms: _transforms.Group = dataclasses.field(default_factory=_transforms.Group)
76
+ # Data transforms, typically include robot specific transformations. Will be applied
77
+ # before the data is normalized. See `model.Observation` and `model.Actions` to learn about the
78
+ # normalized data.
79
+ data_transforms: _transforms.Group = dataclasses.field(default_factory=_transforms.Group)
80
+ # Model specific transforms. Will be applied after the data is normalized.
81
+ model_transforms: _transforms.Group = dataclasses.field(default_factory=_transforms.Group)
82
+ # If true, will use quantile normalization. Otherwise, normal z-score normalization will be used.
83
+ use_quantile_norm: bool = False
84
+
85
+ # Names of keys that will be used by the data loader to generate the action sequence. The length of the
86
+ # sequence is defined by the `action_horizon` field in the model config. This should be adjusted if your
87
+ # LeRobot dataset is using different keys to represent the action.
88
+ action_sequence_keys: Sequence[str] = ("actions",)
89
+
90
+ # If true, will use the LeRobot dataset task to define the prompt.
91
+ prompt_from_task: bool = False
92
+
93
+ # Only used for RLDS data loader (ie currently only used for DROID).
94
+ rlds_data_dir: str | None = None
95
+ # Action space for DROID dataset.
96
+ action_space: droid_rlds_dataset.DroidActionSpace | None = None
97
+ # List of datasets to sample from: name, version, weight, and optionally filter_dict_path
98
+ datasets: Sequence[droid_rlds_dataset.RLDSDataset] = ()
99
+
100
+
101
+ class GroupFactory(Protocol):
102
+ def __call__(self, model_config: _model.BaseModelConfig) -> _transforms.Group:
103
+ """Create a group."""
104
+
105
+
106
+ @dataclasses.dataclass(frozen=True)
107
+ class ModelTransformFactory(GroupFactory):
108
+ """Creates model transforms for standard pi0 models."""
109
+
110
+ # If provided, will determine the default prompt that be used by the model.
111
+ default_prompt: str | None = None
112
+
113
+ def __call__(self, model_config: _model.BaseModelConfig) -> _transforms.Group:
114
+ match model_config.model_type:
115
+ case _model.ModelType.PI0:
116
+ return _transforms.Group(
117
+ inputs=[
118
+ _transforms.InjectDefaultPrompt(self.default_prompt),
119
+ _transforms.ResizeImages(224, 224),
120
+ _transforms.TokenizePrompt(
121
+ _tokenizer.PaligemmaTokenizer(model_config.max_token_len),
122
+ ),
123
+ _transforms.PadStatesAndActions(model_config.action_dim),
124
+ ],
125
+ )
126
+ case _model.ModelType.PI05:
127
+ assert isinstance(model_config, pi0_config.Pi0Config)
128
+ return _transforms.Group(
129
+ inputs=[
130
+ _transforms.InjectDefaultPrompt(self.default_prompt),
131
+ _transforms.ResizeImages(224, 224),
132
+ _transforms.TokenizePrompt(
133
+ _tokenizer.PaligemmaTokenizer(model_config.max_token_len),
134
+ discrete_state_input=model_config.discrete_state_input,
135
+ ),
136
+ _transforms.PadStatesAndActions(model_config.action_dim),
137
+ ],
138
+ )
139
+ case _model.ModelType.PI0_FAST:
140
+ tokenizer_cls = (
141
+ _tokenizer.FASTTokenizer
142
+ if model_config.fast_model_tokenizer is None
143
+ else model_config.fast_model_tokenizer
144
+ )
145
+ tokenizer_kwargs = (
146
+ {} if model_config.fast_model_tokenizer_kwargs is None else model_config.fast_model_tokenizer_kwargs
147
+ )
148
+ return _transforms.Group(
149
+ inputs=[
150
+ _transforms.InjectDefaultPrompt(self.default_prompt),
151
+ _transforms.ResizeImages(224, 224),
152
+ _transforms.TokenizeFASTInputs(
153
+ tokenizer_cls(model_config.max_token_len, **tokenizer_kwargs),
154
+ ),
155
+ ],
156
+ outputs=[
157
+ _transforms.ExtractFASTActions(
158
+ tokenizer_cls(model_config.max_token_len, **tokenizer_kwargs),
159
+ action_horizon=model_config.action_horizon,
160
+ action_dim=model_config.action_dim,
161
+ )
162
+ ],
163
+ )
164
+
165
+
166
+ @dataclasses.dataclass(frozen=True)
167
+ class DataConfigFactory(abc.ABC):
168
+ # The LeRobot repo id.
169
+ repo_id: str = tyro.MISSING
170
+ # Determines how the assets will be loaded.
171
+ assets: AssetsConfig = dataclasses.field(default_factory=AssetsConfig)
172
+ # Base config that will be updated by the factory.
173
+ base_config: tyro.conf.Suppress[DataConfig | None] = None
174
+
175
+ @abc.abstractmethod
176
+ def create(self, assets_dirs: pathlib.Path, model_config: _model.BaseModelConfig) -> DataConfig:
177
+ """Create a data config."""
178
+
179
+ def create_base_config(self, assets_dirs: pathlib.Path, model_config: _model.BaseModelConfig) -> DataConfig:
180
+ repo_id = self.repo_id if self.repo_id is not tyro.MISSING else None
181
+ asset_id = self.assets.asset_id or repo_id
182
+ return dataclasses.replace(
183
+ self.base_config or DataConfig(),
184
+ repo_id=repo_id,
185
+ asset_id=asset_id,
186
+ norm_stats=self._load_norm_stats(epath.Path(self.assets.assets_dir or assets_dirs), asset_id),
187
+ use_quantile_norm=model_config.model_type != ModelType.PI0,
188
+ )
189
+
190
+ def _load_norm_stats(self, assets_dir: epath.Path, asset_id: str | None) -> dict[str, _transforms.NormStats] | None:
191
+ if asset_id is None:
192
+ return None
193
+ try:
194
+ data_assets_dir = str(assets_dir / asset_id)
195
+ norm_stats = _normalize.load(_download.maybe_download(data_assets_dir))
196
+ logging.info(f"Loaded norm stats from {data_assets_dir}")
197
+ return norm_stats
198
+ except FileNotFoundError:
199
+ logging.info(f"Norm stats not found in {data_assets_dir}, skipping.")
200
+ return None
201
+
202
+
203
+ @dataclasses.dataclass(frozen=True)
204
+ class FakeDataConfig(DataConfigFactory):
205
+ repo_id: str = "fake"
206
+
207
+ @override
208
+ def create(self, assets_dirs: pathlib.Path, model_config: _model.BaseModelConfig) -> DataConfig:
209
+ return DataConfig(repo_id=self.repo_id)
210
+
211
+
212
+ @dataclasses.dataclass(frozen=True)
213
+ class SimpleDataConfig(DataConfigFactory):
214
+ # Factory for the data transforms.
215
+ data_transforms: tyro.conf.Suppress[GroupFactory] = dataclasses.field(default_factory=GroupFactory)
216
+ # Factory for the model transforms.
217
+ model_transforms: tyro.conf.Suppress[GroupFactory] = dataclasses.field(default_factory=ModelTransformFactory)
218
+
219
+ @override
220
+ def create(self, assets_dirs: pathlib.Path, model_config: _model.BaseModelConfig) -> DataConfig:
221
+ return dataclasses.replace(
222
+ self.create_base_config(assets_dirs, model_config),
223
+ data_transforms=self.data_transforms(model_config),
224
+ model_transforms=self.model_transforms(model_config),
225
+ )
226
+
227
+
228
+ @dataclasses.dataclass(frozen=True)
229
+ class LeRobotAlohaDataConfig(DataConfigFactory):
230
+ # If true, will convert joint dimensions to deltas with respect to the current state before passing to the model.
231
+ # Gripper dimensions will remain in absolute values.
232
+ use_delta_joint_actions: bool = True
233
+ # If provided, will be injected into the input data if the "prompt" key is not present.
234
+ default_prompt: str | None = None
235
+ # If true, this will convert the joint and gripper values from the standard Aloha space to
236
+ # the space used by the pi internal runtime which was used to train the base model. People who
237
+ # use standard Aloha data should set this to true.
238
+ adapt_to_pi: bool = True
239
+
240
+ # Repack transforms.
241
+ repack_transforms: tyro.conf.Suppress[_transforms.Group] = dataclasses.field(
242
+ default=_transforms.Group(
243
+ inputs=[
244
+ _transforms.RepackTransform(
245
+ {
246
+ "images": {"cam_high": "observation.images.top"},
247
+ "state": "observation.state",
248
+ "actions": "action",
249
+ }
250
+ )
251
+ ]
252
+ )
253
+ )
254
+ # Action keys that will be used to read the action sequence from the dataset.
255
+ action_sequence_keys: Sequence[str] = ("action",)
256
+
257
+ @override
258
+ def create(self, assets_dirs: pathlib.Path, model_config: _model.BaseModelConfig) -> DataConfig:
259
+ data_transforms = _transforms.Group(
260
+ inputs=[aloha_policy.AlohaInputs(adapt_to_pi=self.adapt_to_pi)],
261
+ outputs=[aloha_policy.AlohaOutputs(adapt_to_pi=self.adapt_to_pi)],
262
+ )
263
+ if self.use_delta_joint_actions:
264
+ delta_action_mask = _transforms.make_bool_mask(6, -1, 6, -1)
265
+ data_transforms = data_transforms.push(
266
+ inputs=[_transforms.DeltaActions(delta_action_mask)],
267
+ outputs=[_transforms.AbsoluteActions(delta_action_mask)],
268
+ )
269
+
270
+ model_transforms = ModelTransformFactory(default_prompt=self.default_prompt)(model_config)
271
+
272
+ return dataclasses.replace(
273
+ self.create_base_config(assets_dirs, model_config),
274
+ repack_transforms=self.repack_transforms,
275
+ data_transforms=data_transforms,
276
+ model_transforms=model_transforms,
277
+ action_sequence_keys=self.action_sequence_keys,
278
+ )
279
+
280
+
281
+ @dataclasses.dataclass(frozen=True)
282
+ class LeRobotLiberoDataConfig(DataConfigFactory):
283
+ """
284
+ This config is used to configure transforms that are applied at various parts of the data pipeline.
285
+ For your own dataset, you can copy this class and modify the transforms to match your dataset based on the
286
+ comments below.
287
+ """
288
+
289
+ extra_delta_transform: bool = False
290
+
291
+ @override
292
+ def create(self, assets_dirs: pathlib.Path, model_config: _model.BaseModelConfig) -> DataConfig:
293
+ # The repack transform is *only* applied to the data coming from the dataset,
294
+ # and *not* during inference. We can use it to make inputs from the dataset look
295
+ # as close as possible to those coming from the inference environment (e.g. match the keys).
296
+ # Below, we match the keys in the dataset (which we defined in the data conversion script) to
297
+ # the keys we use in our inference pipeline (defined in the inference script for libero).
298
+ # For your own dataset, first figure out what keys your environment passes to the policy server
299
+ # and then modify the mappings below so your dataset's keys get matched to those target keys.
300
+ # The repack transform simply remaps key names here.
301
+ repack_transform = _transforms.Group(
302
+ inputs=[
303
+ _transforms.RepackTransform(
304
+ {
305
+ "observation/image": "image",
306
+ "observation/wrist_image": "wrist_image",
307
+ "observation/state": "state",
308
+ "actions": "actions",
309
+ "prompt": "prompt",
310
+ }
311
+ )
312
+ ]
313
+ )
314
+
315
+ # The data transforms are applied to the data coming from the dataset *and* during inference.
316
+ # Below, we define the transforms for data going into the model (``inputs``) and the transforms
317
+ # for data coming out of the model (``outputs``) (the latter is only used during inference).
318
+ # We defined these transforms in `libero_policy.py`. You can check the detailed comments there for
319
+ # how to modify the transforms to match your dataset. Once you created your own transforms, you can
320
+ # replace the transforms below with your own.
321
+ data_transforms = _transforms.Group(
322
+ inputs=[libero_policy.LiberoInputs(model_type=model_config.model_type)],
323
+ outputs=[libero_policy.LiberoOutputs()],
324
+ )
325
+
326
+ # One additional data transform: pi0 models are trained on delta actions (relative to the first
327
+ # state in each action chunk). IF your data has ``absolute`` actions (e.g. target joint angles)
328
+ # you can uncomment the following line to convert the actions to delta actions. The only exception
329
+ # is for the gripper actions which are always absolute.
330
+ # In the example below, we would apply the delta conversion to the first 6 actions (joints) and
331
+ # leave the 7th action (gripper) unchanged, i.e. absolute.
332
+ # In Libero, the raw actions in the dataset are already delta actions, so we *do not* need to
333
+ # apply a separate delta conversion (that's why it's commented out). Choose whether to apply this
334
+ # transform based on whether your dataset uses ``absolute`` or ``delta`` actions out of the box.
335
+
336
+ # LIBERO already represents actions as deltas, but we have some old Pi0 checkpoints that are trained with this
337
+ # extra delta transform.
338
+ if self.extra_delta_transform:
339
+ delta_action_mask = _transforms.make_bool_mask(6, -1)
340
+ data_transforms = data_transforms.push(
341
+ inputs=[_transforms.DeltaActions(delta_action_mask)],
342
+ outputs=[_transforms.AbsoluteActions(delta_action_mask)],
343
+ )
344
+
345
+ # Model transforms include things like tokenizing the prompt and action targets
346
+ # You do not need to change anything here for your own dataset.
347
+ model_transforms = ModelTransformFactory()(model_config)
348
+
349
+ # We return all data transforms for training and inference. No need to change anything here.
350
+ return dataclasses.replace(
351
+ self.create_base_config(assets_dirs, model_config),
352
+ repack_transforms=repack_transform,
353
+ data_transforms=data_transforms,
354
+ model_transforms=model_transforms,
355
+ )
356
+
357
+
358
+ @dataclasses.dataclass(frozen=True)
359
+ class RLDSDroidDataConfig(DataConfigFactory):
360
+ """
361
+ Config for training on DROID, using RLDS data format (for efficient training on larger datasets).
362
+ """
363
+
364
+ rlds_data_dir: str | None = None
365
+ action_space: droid_rlds_dataset.DroidActionSpace | None = None
366
+
367
+ # Filtering options. Can pass a path to a dictionary that maps episodes to timestep ranges
368
+ # to tuples denoting ranges of time steps to keep (start, end). Episodes are uniquely identified with
369
+ # f"{recording_folderpath}--{file_path}", both of which are present in the RLDS episode metadata.
370
+
371
+ # List of datasets to sample from: name, version, weight, and optionally filter_dict_path
372
+ datasets: Sequence[droid_rlds_dataset.RLDSDataset] = (
373
+ droid_rlds_dataset.RLDSDataset(
374
+ name="droid",
375
+ version="1.0.1",
376
+ weight=1.0,
377
+ filter_dict_path="gs://openpi-assets/droid/droid_sample_ranges_v1_0_1.json",
378
+ ),
379
+ )
380
+
381
+ @override
382
+ def create(self, assets_dirs: pathlib.Path, model_config: _model.BaseModelConfig) -> DataConfig:
383
+ repack_transform = _transforms.Group(
384
+ inputs=[
385
+ _transforms.RepackTransform(
386
+ {
387
+ "observation/exterior_image_1_left": "observation/image",
388
+ "observation/wrist_image_left": "observation/wrist_image",
389
+ "observation/joint_position": "observation/joint_position",
390
+ "observation/gripper_position": "observation/gripper_position",
391
+ "actions": "actions",
392
+ "prompt": "prompt",
393
+ }
394
+ )
395
+ ]
396
+ )
397
+
398
+ data_transforms = _transforms.Group(
399
+ inputs=[droid_policy.DroidInputs(model_type=model_config.model_type)],
400
+ outputs=[droid_policy.DroidOutputs()],
401
+ )
402
+
403
+ if self.action_space == droid_rlds_dataset.DroidActionSpace.JOINT_POSITION:
404
+ # Data loader returns absolute joint position actions -- convert to delta actions for training.
405
+ delta_action_mask = _transforms.make_bool_mask(7, -1)
406
+ data_transforms = data_transforms.push(
407
+ inputs=[_transforms.DeltaActions(delta_action_mask)],
408
+ outputs=[_transforms.AbsoluteActions(delta_action_mask)],
409
+ )
410
+
411
+ model_transforms = ModelTransformFactory()(model_config)
412
+
413
+ assert self.rlds_data_dir is not None, "Need to set rlds data dir for RLDS data loader."
414
+
415
+ return dataclasses.replace(
416
+ self.create_base_config(assets_dirs, model_config),
417
+ repack_transforms=repack_transform,
418
+ data_transforms=data_transforms,
419
+ model_transforms=model_transforms,
420
+ rlds_data_dir=self.rlds_data_dir,
421
+ action_space=self.action_space,
422
+ datasets=self.datasets,
423
+ )
424
+
425
+
426
+ @dataclasses.dataclass(frozen=True)
427
+ class LeRobotDROIDDataConfig(DataConfigFactory):
428
+ """
429
+ Example data config for custom DROID dataset in LeRobot format.
430
+ To convert your custom DROID dataset (<10s of hours) to LeRobot format, see examples/droid/convert_droid_data_to_lerobot.py
431
+ """
432
+
433
+ @override
434
+ def create(self, assets_dirs: pathlib.Path, model_config: _model.BaseModelConfig) -> DataConfig:
435
+ repack_transform = _transforms.Group(
436
+ inputs=[
437
+ _transforms.RepackTransform(
438
+ {
439
+ "observation/exterior_image_1_left": "exterior_image_1_left",
440
+ "observation/exterior_image_2_left": "exterior_image_2_left",
441
+ "observation/wrist_image_left": "wrist_image_left",
442
+ "observation/joint_position": "joint_position",
443
+ "observation/gripper_position": "gripper_position",
444
+ "actions": "actions",
445
+ "prompt": "prompt",
446
+ }
447
+ )
448
+ ]
449
+ )
450
+ # We assume joint *velocity* actions, so we should *not* apply an additional delta transform.
451
+ data_transforms = _transforms.Group(
452
+ inputs=[droid_policy.DroidInputs(model_type=model_config.model_type)],
453
+ outputs=[droid_policy.DroidOutputs()],
454
+ )
455
+ model_transforms = ModelTransformFactory()(model_config)
456
+
457
+ return dataclasses.replace(
458
+ self.create_base_config(assets_dirs, model_config),
459
+ repack_transforms=repack_transform,
460
+ data_transforms=data_transforms,
461
+ model_transforms=model_transforms,
462
+ )
463
+
464
+
465
+ @dataclasses.dataclass(frozen=True)
466
+ class TrainConfig:
467
+ # Name of the config. Must be unique. Will be used to reference this config.
468
+ name: tyro.conf.Suppress[str]
469
+ # Project name.
470
+ project_name: str = "openpi"
471
+ # Experiment name. Will be used to name the metadata and checkpoint directories.
472
+ exp_name: str = tyro.MISSING
473
+
474
+ # Defines the model config. Some attributes (action_dim, action_horizon, and max_token_len) are shared by all models
475
+ # -- see BaseModelConfig. Specific model implementations (e.g., Pi0Config) inherit from BaseModelConfig and may
476
+ # define additional attributes.
477
+ model: _model.BaseModelConfig = dataclasses.field(default_factory=pi0_config.Pi0Config)
478
+
479
+ # A weight loader can optionally load (possibly partial) weights from disk after the model is initialized.
480
+ weight_loader: weight_loaders.WeightLoader = dataclasses.field(default_factory=weight_loaders.NoOpWeightLoader)
481
+
482
+ # Optional path to a PyTorch checkpoint to load weights from.
483
+ pytorch_weight_path: str | None = None
484
+
485
+ # Precision for PyTorch training.
486
+ pytorch_training_precision: Literal["bfloat16", "float32"] = "bfloat16"
487
+
488
+ lr_schedule: _optimizer.LRScheduleConfig = dataclasses.field(default_factory=_optimizer.CosineDecaySchedule)
489
+ optimizer: _optimizer.OptimizerConfig = dataclasses.field(default_factory=_optimizer.AdamW)
490
+ ema_decay: float | None = 0.99
491
+
492
+ # Specifies which weights should be frozen.
493
+ freeze_filter: tyro.conf.Suppress[Filter] = dataclasses.field(default_factory=nnx.Nothing)
494
+
495
+ # Determines the data to be trained on.
496
+ data: DataConfigFactory = dataclasses.field(default_factory=FakeDataConfig)
497
+
498
+ # Base directory for config assets (e.g., norm stats).
499
+ assets_base_dir: str = "./assets"
500
+ # Base directory for checkpoints.
501
+ checkpoint_base_dir: str = "./checkpoints"
502
+
503
+ # Random seed that will be used by random generators during training.
504
+ seed: int = 42
505
+ # Global batch size.
506
+ batch_size: int = 32
507
+ # Number of workers to use for the data loader. Increasing this number will speed up data loading but
508
+ # will increase memory and CPU usage.
509
+ num_workers: int = 2
510
+ # Number of train steps (batches) to run.
511
+ num_train_steps: int = 30_000
512
+
513
+ # How often (in steps) to log training metrics.
514
+ log_interval: int = 100
515
+ # How often (in steps) to save checkpoints.
516
+ save_interval: int = 1000
517
+ # If set, any existing checkpoints matching step % keep_period == 0 will not be deleted.
518
+ keep_period: int | None = 5000
519
+
520
+ # If true, will overwrite the checkpoint directory if it already exists.
521
+ overwrite: bool = False
522
+ # If true, will resume training from the last checkpoint.
523
+ resume: bool = False
524
+
525
+ # If true, will enable wandb logging.
526
+ wandb_enabled: bool = True
527
+
528
+ # Used to pass metadata to the policy server.
529
+ policy_metadata: dict[str, Any] | None = None
530
+
531
+ # If the value is greater than 1, FSDP will be enabled and shard across number of specified devices; overall
532
+ # device memory will be reduced but training could potentially be slower.
533
+ # eg. if total device is 4 and fsdp devices is 2; then the model will shard to 2 devices and run
534
+ # data parallel between 2 groups of devices.
535
+ fsdp_devices: int = 1
536
+
537
+ @property
538
+ def assets_dirs(self) -> pathlib.Path:
539
+ """Get the assets directory for this config."""
540
+ return (pathlib.Path(self.assets_base_dir) / self.name).resolve()
541
+
542
+ @property
543
+ def checkpoint_dir(self) -> pathlib.Path:
544
+ """Get the checkpoint directory for this config."""
545
+ if not self.exp_name:
546
+ raise ValueError("--exp_name must be set")
547
+ return (pathlib.Path(self.checkpoint_base_dir) / self.name / self.exp_name).resolve()
548
+
549
+ @property
550
+ def trainable_filter(self) -> nnx.filterlib.Filter:
551
+ """Get the filter for the trainable parameters."""
552
+ return nnx.All(nnx.Param, nnx.Not(self.freeze_filter))
553
+
554
+ def __post_init__(self) -> None:
555
+ if self.resume and self.overwrite:
556
+ raise ValueError("Cannot resume and overwrite at the same time.")
557
+
558
+
559
+ # Use `get_config` if you need to get a config by name in your code.
560
+ _CONFIGS = [
561
+ #
562
+ # Inference Aloha configs.
563
+ #
564
+ TrainConfig(
565
+ name="pi0_aloha",
566
+ model=pi0_config.Pi0Config(),
567
+ data=LeRobotAlohaDataConfig(
568
+ assets=AssetsConfig(asset_id="trossen"),
569
+ ),
570
+ policy_metadata={"reset_pose": [0, -1.5, 1.5, 0, 0, 0]},
571
+ ),
572
+ TrainConfig(
573
+ name="pi05_aloha",
574
+ model=pi0_config.Pi0Config(pi05=True),
575
+ data=LeRobotAlohaDataConfig(
576
+ assets=AssetsConfig(asset_id="trossen"),
577
+ ),
578
+ policy_metadata={"reset_pose": [0, -1.5, 1.5, 0, 0, 0]},
579
+ ),
580
+ TrainConfig(
581
+ name="pi0_aloha_towel",
582
+ model=pi0_config.Pi0Config(),
583
+ data=LeRobotAlohaDataConfig(
584
+ assets=AssetsConfig(asset_id="trossen"),
585
+ default_prompt="fold the towel",
586
+ ),
587
+ policy_metadata={"reset_pose": [0, -1.5, 1.5, 0, 0, 0]},
588
+ ),
589
+ TrainConfig(
590
+ name="pi0_aloha_tupperware",
591
+ model=pi0_config.Pi0Config(),
592
+ data=LeRobotAlohaDataConfig(
593
+ assets=AssetsConfig(asset_id="trossen"),
594
+ default_prompt="open the tupperware and put the food on the plate",
595
+ ),
596
+ policy_metadata={"reset_pose": [0, -1.5, 1.5, 0, 0, 0]},
597
+ ),
598
+ #
599
+ # Inference DROID configs.
600
+ #
601
+ TrainConfig(
602
+ name="pi0_droid",
603
+ model=pi0_config.Pi0Config(action_horizon=10),
604
+ data=SimpleDataConfig(
605
+ assets=AssetsConfig(asset_id="droid"),
606
+ data_transforms=lambda model: _transforms.Group(
607
+ inputs=[droid_policy.DroidInputs(model_type=ModelType.PI0)],
608
+ outputs=[droid_policy.DroidOutputs()],
609
+ ),
610
+ base_config=DataConfig(
611
+ prompt_from_task=True,
612
+ ),
613
+ ),
614
+ ),
615
+ TrainConfig(
616
+ name="pi0_fast_droid",
617
+ model=pi0_fast.Pi0FASTConfig(action_dim=8, action_horizon=10),
618
+ data=SimpleDataConfig(
619
+ assets=AssetsConfig(asset_id="droid"),
620
+ data_transforms=lambda model: _transforms.Group(
621
+ inputs=[droid_policy.DroidInputs(model_type=ModelType.PI0_FAST)],
622
+ outputs=[droid_policy.DroidOutputs()],
623
+ ),
624
+ base_config=DataConfig(
625
+ prompt_from_task=True,
626
+ ),
627
+ ),
628
+ ),
629
+ TrainConfig(
630
+ name="pi05_droid",
631
+ model=pi0_config.Pi0Config(action_horizon=15, pi05=True),
632
+ data=SimpleDataConfig(
633
+ assets=AssetsConfig(asset_id="droid"),
634
+ data_transforms=lambda model: _transforms.Group(
635
+ inputs=[droid_policy.DroidInputs(model_type=ModelType.PI05)],
636
+ outputs=[droid_policy.DroidOutputs()],
637
+ ),
638
+ base_config=DataConfig(
639
+ prompt_from_task=True,
640
+ ),
641
+ ),
642
+ ),
643
+ #
644
+ # Fine-tuning Libero configs.
645
+ #
646
+ # These train configs define the hyperparameters for fine-tuning the base model on your own dataset.
647
+ # They are used to define key elements like the dataset you are training on, the base checkpoint you
648
+ # are using, and other hyperparameters like how many training steps to run or what learning rate to use.
649
+ # For your own dataset, you can copy this class and modify the dataset name, and data transforms based on
650
+ # the comments below.
651
+ TrainConfig(
652
+ # Change the name to reflect your model and dataset.
653
+ name="pi0_libero",
654
+ # Here you define the model config -- In this example we use pi0 as the model
655
+ # architecture and perform *full* finetuning. in the examples below we show how to modify
656
+ # this to perform *low-memory* (LORA) finetuning and use pi0-FAST as an alternative architecture.
657
+ model=pi0_config.Pi0Config(),
658
+ # Here you define the dataset you are training on. In this example we use the Libero
659
+ # dataset. For your own dataset, you can change the repo_id to point to your dataset.
660
+ # Also modify the DataConfig to use the new config you made for your dataset above.
661
+ data=LeRobotLiberoDataConfig(
662
+ repo_id="physical-intelligence/libero",
663
+ base_config=DataConfig(
664
+ # This flag determines whether we load the prompt (i.e. the task instruction) from the
665
+ # ``task`` field in the LeRobot dataset. If set to True, the prompt will show up in
666
+ # a field called ``prompt`` in the input dict. The recommended setting is True.
667
+ prompt_from_task=True,
668
+ ),
669
+ extra_delta_transform=True,
670
+ ),
671
+ # Here you define which pre-trained checkpoint you want to load to initialize the model.
672
+ # This should match the model config you chose above -- i.e. in this case we use the pi0 base model.
673
+ weight_loader=weight_loaders.CheckpointWeightLoader("gs://openpi-assets/checkpoints/pi0_base/params"),
674
+ # Below you can define other hyperparameters like the learning rate, number of training steps, etc.
675
+ # Check the base TrainConfig class for a full list of available hyperparameters.
676
+ num_train_steps=30_000,
677
+ ),
678
+ TrainConfig(
679
+ name="pi0_libero_low_mem_finetune",
680
+ # Here is an example of loading a pi0 model for LoRA fine-tuning.
681
+ model=pi0_config.Pi0Config(paligemma_variant="gemma_2b_lora", action_expert_variant="gemma_300m_lora"),
682
+ data=LeRobotLiberoDataConfig(
683
+ repo_id="physical-intelligence/libero",
684
+ base_config=DataConfig(prompt_from_task=True),
685
+ extra_delta_transform=True,
686
+ ),
687
+ weight_loader=weight_loaders.CheckpointWeightLoader("gs://openpi-assets/checkpoints/pi0_base/params"),
688
+ num_train_steps=30_000,
689
+ # The freeze filter defines which parameters should be frozen during training.
690
+ # We have a convenience function in the model config that returns the default freeze filter
691
+ # for the given model config for LoRA finetuning. Just make sure it matches the model config
692
+ # you chose above.
693
+ freeze_filter=pi0_config.Pi0Config(
694
+ paligemma_variant="gemma_2b_lora", action_expert_variant="gemma_300m_lora"
695
+ ).get_freeze_filter(),
696
+ # Turn off EMA for LoRA finetuning.
697
+ ema_decay=None,
698
+ ),
699
+ TrainConfig(
700
+ name="pi0_fast_libero",
701
+ # Here is an example of loading a pi0-FAST model for full finetuning.
702
+ # Modify action_dim and action_horizon to match your dataset (action horizon is equal to
703
+ # the desired action chunk length).
704
+ # The max_token_len is the maximum number of (non-image) tokens the model can handle.
705
+ # This includes the tokenized prompt, proprioceptive state, and (FAST-tokenized) action tokens.
706
+ # Choosing this value too small may chop off tokens at the end of your sequence (the code will throw
707
+ # a warning), while choosing it too large will waste memory (since we pad each batch element to the
708
+ # max_token_len). A good rule of thumb is to use approx 180 for single-arm robots, and approx 250 for
709
+ # two-arm robots. Generally, err on the lower side here first, and potentially increase the value if
710
+ # you see many warnings being thrown during training.
711
+ model=pi0_fast.Pi0FASTConfig(action_dim=7, action_horizon=10, max_token_len=180),
712
+ data=LeRobotLiberoDataConfig(
713
+ repo_id="physical-intelligence/libero",
714
+ base_config=DataConfig(prompt_from_task=True),
715
+ extra_delta_transform=True,
716
+ ),
717
+ # Note that we load the pi0-FAST base model checkpoint here.
718
+ weight_loader=weight_loaders.CheckpointWeightLoader("gs://openpi-assets/checkpoints/pi0_fast_base/params"),
719
+ num_train_steps=30_000,
720
+ ),
721
+ TrainConfig(
722
+ name="pi0_fast_libero_low_mem_finetune",
723
+ # Here is an example of loading a pi0-FAST model for LoRA finetuning.
724
+ # For setting action_dim, action_horizon, and max_token_len, see the comments above.
725
+ model=pi0_fast.Pi0FASTConfig(
726
+ action_dim=7, action_horizon=10, max_token_len=180, paligemma_variant="gemma_2b_lora"
727
+ ),
728
+ data=LeRobotLiberoDataConfig(
729
+ repo_id="physical-intelligence/libero",
730
+ base_config=DataConfig(prompt_from_task=True),
731
+ extra_delta_transform=True,
732
+ ),
733
+ weight_loader=weight_loaders.CheckpointWeightLoader("gs://openpi-assets/checkpoints/pi0_fast_base/params"),
734
+ num_train_steps=30_000,
735
+ # Again, make sure to match the model config above when extracting the freeze filter
736
+ # that specifies which parameters should be frozen during LoRA finetuning.
737
+ freeze_filter=pi0_fast.Pi0FASTConfig(
738
+ action_dim=7, action_horizon=10, max_token_len=180, paligemma_variant="gemma_2b_lora"
739
+ ).get_freeze_filter(),
740
+ # Turn off EMA for LoRA finetuning.
741
+ ema_decay=None,
742
+ ),
743
+ TrainConfig(
744
+ name="pi05_libero",
745
+ model=pi0_config.Pi0Config(pi05=True, action_horizon=10, discrete_state_input=False),
746
+ data=LeRobotLiberoDataConfig(
747
+ repo_id="physical-intelligence/libero",
748
+ base_config=DataConfig(prompt_from_task=True),
749
+ extra_delta_transform=False,
750
+ ),
751
+ batch_size=256,
752
+ lr_schedule=_optimizer.CosineDecaySchedule(
753
+ warmup_steps=10_000,
754
+ peak_lr=5e-5,
755
+ decay_steps=1_000_000,
756
+ decay_lr=5e-5,
757
+ ),
758
+ optimizer=_optimizer.AdamW(clip_gradient_norm=1.0),
759
+ ema_decay=0.999,
760
+ weight_loader=weight_loaders.CheckpointWeightLoader("gs://openpi-assets/checkpoints/pi05_base/params"),
761
+ pytorch_weight_path="/path/to/your/pytorch_weight_path",
762
+ num_train_steps=30_000,
763
+ ),
764
+ TrainConfig(
765
+ name="pi05_kinova_teddybear",
766
+ model=pi0_config.Pi0Config(
767
+ pi05=True,
768
+ action_dim=32,
769
+ action_horizon=16,
770
+ ),
771
+ data=SimpleDataConfig(
772
+ repo_id="lsnu/TeddyBearKinovaTestSetLeRobot",
773
+ base_config=DataConfig(
774
+ prompt_from_task=False,
775
+ repack_transforms=_transforms.Group(
776
+ inputs=[
777
+ _transforms.RepackTransform(
778
+ {
779
+ "observation/image": "observation.images.azure_rgb",
780
+ "observation/wrist_image": "observation.images.wrist",
781
+ "observation/state": "observation.state",
782
+ "actions": "action",
783
+ }
784
+ )
785
+ ]
786
+ ),
787
+ action_sequence_keys=("action",),
788
+ ),
789
+ data_transforms=lambda model: _transforms.Group(
790
+ inputs=[libero_policy.LiberoInputs(model_type=model.model_type)],
791
+ outputs=[libero_policy.LiberoOutputs()],
792
+ ).push(
793
+ # The dataset stores absolute next-step end-effector poses.
794
+ # Convert the 6 pose dimensions to deltas and keep gripper absolute.
795
+ inputs=[_transforms.DeltaActions(_transforms.make_bool_mask(6, -1))],
796
+ outputs=[_transforms.AbsoluteActions(_transforms.make_bool_mask(6, -1))],
797
+ ),
798
+ model_transforms=ModelTransformFactory(
799
+ default_prompt="pick up the teddy bear and place it in the red box",
800
+ ),
801
+ ),
802
+ weight_loader=weight_loaders.CheckpointWeightLoader("gs://openpi-assets/checkpoints/pi05_base/params"),
803
+ batch_size=32,
804
+ num_workers=32,
805
+ num_train_steps=5_000,
806
+ log_interval=25,
807
+ save_interval=500,
808
+ keep_period=2_000,
809
+ wandb_enabled=False,
810
+ ),
811
+ #
812
+ # Fine-tuning Aloha configs.
813
+ #
814
+ # This is a test config that is used to illustate how train on a custom LeRobot dataset.
815
+ # For instructions on how to convert and train on your own Aloha dataset see examples/aloha_real/README.md
816
+ TrainConfig(
817
+ name="pi0_aloha_pen_uncap",
818
+ model=pi0_config.Pi0Config(),
819
+ data=LeRobotAlohaDataConfig(
820
+ repo_id="physical-intelligence/aloha_pen_uncap_diverse",
821
+ assets=AssetsConfig(
822
+ assets_dir="gs://openpi-assets/checkpoints/pi0_base/assets",
823
+ asset_id="trossen",
824
+ ),
825
+ default_prompt="uncap the pen",
826
+ repack_transforms=_transforms.Group(
827
+ inputs=[
828
+ _transforms.RepackTransform(
829
+ {
830
+ "images": {
831
+ "cam_high": "observation.images.cam_high",
832
+ "cam_left_wrist": "observation.images.cam_left_wrist",
833
+ "cam_right_wrist": "observation.images.cam_right_wrist",
834
+ },
835
+ "state": "observation.state",
836
+ "actions": "action",
837
+ }
838
+ )
839
+ ]
840
+ ),
841
+ ),
842
+ weight_loader=weight_loaders.CheckpointWeightLoader("gs://openpi-assets/checkpoints/pi0_base/params"),
843
+ num_train_steps=20_000,
844
+ ),
845
+ TrainConfig(
846
+ name="pi05_aloha_pen_uncap",
847
+ model=pi0_config.Pi0Config(pi05=True),
848
+ data=LeRobotAlohaDataConfig(
849
+ repo_id="physical-intelligence/aloha_pen_uncap_diverse",
850
+ assets=AssetsConfig(
851
+ assets_dir="gs://openpi-assets/checkpoints/pi05_base/assets",
852
+ asset_id="trossen",
853
+ ),
854
+ default_prompt="uncap the pen",
855
+ repack_transforms=_transforms.Group(
856
+ inputs=[
857
+ _transforms.RepackTransform(
858
+ {
859
+ "images": {
860
+ "cam_high": "observation.images.cam_high",
861
+ "cam_left_wrist": "observation.images.cam_left_wrist",
862
+ "cam_right_wrist": "observation.images.cam_right_wrist",
863
+ },
864
+ "state": "observation.state",
865
+ "actions": "action",
866
+ }
867
+ )
868
+ ]
869
+ ),
870
+ ),
871
+ weight_loader=weight_loaders.CheckpointWeightLoader("gs://openpi-assets/checkpoints/pi05_base/params"),
872
+ num_train_steps=20_000,
873
+ batch_size=64,
874
+ ),
875
+ #
876
+ # Fine-tuning DROID configs.
877
+ #
878
+ TrainConfig(
879
+ # This config is for fine-tuning pi0-FAST-base on the *full* DROID dataset.
880
+ # We use RLDS data loading to make training on this large dataset tractable.
881
+ # For fine-tuning on your own DROID dataset, see below.
882
+ name="pi0_fast_full_droid_finetune",
883
+ model=pi0_fast.Pi0FASTConfig(
884
+ action_dim=8,
885
+ action_horizon=16,
886
+ max_token_len=180,
887
+ ),
888
+ data=RLDSDroidDataConfig(
889
+ repo_id="droid",
890
+ # Set this to the path to your DROID RLDS dataset (the parent directory of the `droid` directory).
891
+ rlds_data_dir="<path_to_droid_rlds_dataset>",
892
+ action_space=droid_rlds_dataset.DroidActionSpace.JOINT_POSITION,
893
+ ),
894
+ weight_loader=weight_loaders.CheckpointWeightLoader("gs://openpi-assets/checkpoints/pi0_fast_base/params"),
895
+ lr_schedule=_optimizer.CosineDecaySchedule(
896
+ warmup_steps=1_000,
897
+ peak_lr=5e-5,
898
+ decay_steps=1_000_000,
899
+ decay_lr=5e-5,
900
+ ),
901
+ num_train_steps=100_000, # 100k steps should be sufficient, takes ~2 days on 8x H100s
902
+ batch_size=256,
903
+ log_interval=100,
904
+ save_interval=5000,
905
+ keep_period=20_000,
906
+ num_workers=0, # Important: RLDS DataLoader requires num_workers=0, handles multi-processing internally
907
+ ),
908
+ TrainConfig(
909
+ # This config is for fine-tuning pi05 on the *full* DROID dataset.
910
+ # We use RLDS data loading to make training on this large dataset tractable.
911
+ # For fine-tuning on your own DROID dataset, see below.
912
+ name="pi05_full_droid_finetune",
913
+ model=pi0_config.Pi0Config(
914
+ pi05=True,
915
+ action_dim=32,
916
+ action_horizon=16,
917
+ ),
918
+ data=RLDSDroidDataConfig(
919
+ repo_id="droid",
920
+ # Set this to the path to your DROID RLDS dataset (the parent directory of the `droid` directory).
921
+ rlds_data_dir="/mnt/pi-data/kevin",
922
+ action_space=droid_rlds_dataset.DroidActionSpace.JOINT_POSITION,
923
+ assets=AssetsConfig(
924
+ assets_dir="gs://openpi-assets/checkpoints/pi05_base/assets/",
925
+ asset_id="droid",
926
+ ),
927
+ ),
928
+ weight_loader=weight_loaders.CheckpointWeightLoader("gs://openpi-assets/checkpoints/pi05_base/params"),
929
+ lr_schedule=_optimizer.CosineDecaySchedule(
930
+ warmup_steps=1_000,
931
+ peak_lr=5e-5,
932
+ decay_steps=1_000_000,
933
+ decay_lr=5e-5,
934
+ ),
935
+ num_train_steps=100_000,
936
+ batch_size=256,
937
+ log_interval=100,
938
+ save_interval=5000,
939
+ keep_period=10_000,
940
+ num_workers=0, # Important: RLDS DataLoader requires num_workers=0, handles multi-processing internally
941
+ ),
942
+ TrainConfig(
943
+ # This config is for fine-tuning pi05-DROID on a custom (smaller) DROID dataset.
944
+ # Here, we use LeRobot data format (like for all other fine-tuning examples)
945
+ # To convert your custom DROID dataset (<10s of hours) to LeRobot format, see examples/droid/convert_droid_data_to_lerobot.py
946
+ name="pi05_droid_finetune",
947
+ model=pi0_config.Pi0Config(
948
+ pi05=True,
949
+ action_dim=32, # pi05 is trained with 32-dim actions
950
+ action_horizon=16,
951
+ ),
952
+ data=LeRobotDROIDDataConfig(
953
+ # Replace with your custom DROID LeRobot dataset repo id.
954
+ repo_id="your_hf_username/my_droid_dataset",
955
+ base_config=DataConfig(prompt_from_task=True),
956
+ assets=AssetsConfig(
957
+ # Important: reuse the original DROID norm stats during fine-tuning!
958
+ assets_dir="gs://openpi-assets/checkpoints/pi05_droid/assets",
959
+ asset_id="droid",
960
+ ),
961
+ ),
962
+ weight_loader=weight_loaders.CheckpointWeightLoader("gs://openpi-assets/checkpoints/pi05_droid/params"),
963
+ num_train_steps=20_000,
964
+ batch_size=32,
965
+ ),
966
+ #
967
+ # ALOHA Sim configs. This config is used to demonstrate how to train on a simple simulated environment.
968
+ #
969
+ TrainConfig(
970
+ name="pi0_aloha_sim",
971
+ model=pi0_config.Pi0Config(),
972
+ data=LeRobotAlohaDataConfig(
973
+ repo_id="lerobot/aloha_sim_transfer_cube_human",
974
+ default_prompt="Transfer cube",
975
+ use_delta_joint_actions=False,
976
+ ),
977
+ weight_loader=weight_loaders.CheckpointWeightLoader("gs://openpi-assets/checkpoints/pi0_base/params"),
978
+ num_train_steps=20_000,
979
+ ),
980
+ #
981
+ # Debugging configs.
982
+ #
983
+ TrainConfig(
984
+ name="debug",
985
+ data=FakeDataConfig(),
986
+ batch_size=2,
987
+ model=pi0_config.Pi0Config(paligemma_variant="dummy", action_expert_variant="dummy"),
988
+ save_interval=100,
989
+ overwrite=True,
990
+ exp_name="debug",
991
+ num_train_steps=10,
992
+ wandb_enabled=False,
993
+ ),
994
+ TrainConfig(
995
+ name="debug_restore",
996
+ data=FakeDataConfig(),
997
+ batch_size=2,
998
+ model=pi0_config.Pi0Config(paligemma_variant="dummy", action_expert_variant="dummy"),
999
+ weight_loader=weight_loaders.CheckpointWeightLoader("./checkpoints/debug/debug/9/params"),
1000
+ overwrite=True,
1001
+ exp_name="debug",
1002
+ num_train_steps=10,
1003
+ wandb_enabled=False,
1004
+ ),
1005
+ TrainConfig(
1006
+ name="debug_pi05",
1007
+ model=pi0_config.Pi0Config(pi05=True, paligemma_variant="dummy", action_expert_variant="dummy"),
1008
+ data=FakeDataConfig(),
1009
+ batch_size=2,
1010
+ num_train_steps=10,
1011
+ overwrite=True,
1012
+ exp_name="debug_pi05",
1013
+ wandb_enabled=False,
1014
+ ),
1015
+ # RoboArena & PolaRiS configs.
1016
+ *roboarena_config.get_roboarena_configs(),
1017
+ *polaris_config.get_polaris_configs(),
1018
+ ]
1019
+
1020
+ if len({config.name for config in _CONFIGS}) != len(_CONFIGS):
1021
+ raise ValueError("Config names must be unique.")
1022
+ _CONFIGS_DICT = {config.name: config for config in _CONFIGS}
1023
+
1024
+
1025
+ def cli() -> TrainConfig:
1026
+ return tyro.extras.overridable_config_cli({k: (k, v) for k, v in _CONFIGS_DICT.items()})
1027
+
1028
+
1029
+ def get_config(config_name: str) -> TrainConfig:
1030
+ """Get a config by name."""
1031
+ if config_name not in _CONFIGS_DICT:
1032
+ closest = difflib.get_close_matches(config_name, _CONFIGS_DICT.keys(), n=1, cutoff=0.0)
1033
+ closest_str = f" Did you mean '{closest[0]}'? " if closest else ""
1034
+ raise ValueError(f"Config '{config_name}' not found.{closest_str}")
1035
+
1036
+ return _CONFIGS_DICT[config_name]
bundle/code/openpi/src/openpi/training/data_loader.py ADDED
@@ -0,0 +1,550 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from collections.abc import Iterator, Sequence
2
+ import logging
3
+ import multiprocessing
4
+ import os
5
+ import typing
6
+ from typing import Literal, Protocol, SupportsIndex, TypeVar
7
+
8
+ import jax
9
+ import jax.numpy as jnp
10
+ import lerobot.common.datasets.lerobot_dataset as lerobot_dataset
11
+ import numpy as np
12
+ import torch
13
+
14
+ import openpi.models.model as _model
15
+ import openpi.training.config as _config
16
+ from openpi.training.droid_rlds_dataset import DroidRldsDataset
17
+ from openpi.training.kinova_lerobot_v3_dataset import KinovaLeRobotV3Dataset
18
+ from openpi.training.kinova_lerobot_v3_dataset import REPO_ID as KINOVA_TEDDYBEAR_REPO_ID
19
+ import openpi.transforms as _transforms
20
+
21
+ T_co = TypeVar("T_co", covariant=True)
22
+
23
+
24
+ class Dataset(Protocol[T_co]):
25
+ """Interface for a dataset with random access."""
26
+
27
+ def __getitem__(self, index: SupportsIndex) -> T_co:
28
+ raise NotImplementedError("Subclasses of Dataset should implement __getitem__.")
29
+
30
+ def __len__(self) -> int:
31
+ raise NotImplementedError("Subclasses of Dataset should implement __len__.")
32
+
33
+
34
+ class IterableDataset(Protocol[T_co]):
35
+ """Interface for an iterable dataset."""
36
+
37
+ def __iter__(self) -> Iterator[T_co]:
38
+ raise NotImplementedError("Subclasses of IterableDataset should implement __iter__.")
39
+
40
+ def __len__(self) -> int:
41
+ raise NotImplementedError("Subclasses of Dataset should implement __len__.")
42
+
43
+
44
+ class DataLoader(Protocol[T_co]):
45
+ """Interface for a data loader."""
46
+
47
+ def data_config(self) -> _config.DataConfig:
48
+ """Get the data config for this data loader."""
49
+ raise NotImplementedError("Subclasses of DataLoader should implement data_config.")
50
+
51
+ def __iter__(self) -> Iterator[T_co]:
52
+ raise NotImplementedError("Subclasses of DataLoader should implement __iter__.")
53
+
54
+
55
+ class TransformedDataset(Dataset[T_co]):
56
+ def __init__(self, dataset: Dataset, transforms: Sequence[_transforms.DataTransformFn]):
57
+ self._dataset = dataset
58
+ self._transform = _transforms.compose(transforms)
59
+
60
+ def __getitem__(self, index: SupportsIndex) -> T_co:
61
+ return self._transform(self._dataset[index])
62
+
63
+ def __len__(self) -> int:
64
+ return len(self._dataset)
65
+
66
+
67
+ class IterableTransformedDataset(IterableDataset[T_co]):
68
+ def __init__(
69
+ self,
70
+ dataset: IterableDataset,
71
+ transforms: Sequence[_transforms.DataTransformFn],
72
+ *,
73
+ is_batched: bool = False,
74
+ ):
75
+ self._dataset = dataset
76
+ self._transform = _transforms.compose(transforms)
77
+ self._is_batched = is_batched
78
+
79
+ def __iter__(self):
80
+ for sample in self._dataset:
81
+ if self._is_batched:
82
+ # Transforms are designed to be applied to individual samples. So we need to split the batch into
83
+ # individual samples and apply the transform to each sample individually.
84
+ batch_size = next(v.shape[0] for v in sample.values())
85
+
86
+ # Split batch into individual samples using tree_map
87
+ individual_samples = [jax.tree.map(lambda x: x[i], sample) for i in range(batch_size)] # noqa: B023
88
+
89
+ # Transform each sample
90
+ transformed = [self._transform(s) for s in individual_samples]
91
+
92
+ # Recombine batch with tree_map
93
+ yield jax.tree.map(lambda *x: np.stack(x, axis=0), *transformed)
94
+ else:
95
+ yield self._transform(sample)
96
+
97
+ def __len__(self) -> int:
98
+ return len(self._dataset)
99
+
100
+
101
+ class FakeDataset(Dataset):
102
+ def __init__(self, model_config: _model.BaseModelConfig, num_samples: int):
103
+ self._num_samples = num_samples
104
+ self._observation_spec, self._action_spec = model_config.inputs_spec()
105
+
106
+ def __getitem__(self, index: SupportsIndex) -> dict:
107
+ rng = jax.random.key(index.__index__())
108
+
109
+ def make_from_spec(spec: jax.ShapeDtypeStruct):
110
+ nonlocal rng
111
+ rng, data_rng = jax.random.split(rng)
112
+ # Remove the batch dimension.
113
+ shape = spec.shape[1:]
114
+ if spec.dtype == jnp.float32:
115
+ return jax.random.uniform(data_rng, shape=shape, minval=-1.0, maxval=1.0)
116
+ if spec.dtype == jnp.int32:
117
+ return jax.random.randint(data_rng, shape=shape, minval=0, maxval=2048)
118
+ return jnp.zeros(shape=shape, dtype=spec.dtype)
119
+
120
+ observation = jax.tree.map(make_from_spec, self._observation_spec)
121
+ action = jax.tree.map(make_from_spec, self._action_spec)
122
+
123
+ return {
124
+ **observation.to_dict(),
125
+ "actions": action,
126
+ }
127
+
128
+ def __len__(self) -> int:
129
+ return self._num_samples
130
+
131
+
132
+ def create_torch_dataset(
133
+ data_config: _config.DataConfig, action_horizon: int, model_config: _model.BaseModelConfig
134
+ ) -> Dataset:
135
+ """Create a dataset for training."""
136
+ repo_id = data_config.repo_id
137
+ if repo_id is None:
138
+ raise ValueError("Repo ID is not set. Cannot create dataset.")
139
+ if repo_id == "fake":
140
+ return FakeDataset(model_config, num_samples=1024)
141
+ if repo_id == KINOVA_TEDDYBEAR_REPO_ID:
142
+ return KinovaLeRobotV3Dataset(
143
+ action_horizon=action_horizon,
144
+ action_sequence_keys=data_config.action_sequence_keys,
145
+ load_videos=os.getenv("OPENPI_SKIP_VIDEO_DECODE", "0") != "1",
146
+ )
147
+
148
+ dataset_meta = lerobot_dataset.LeRobotDatasetMetadata(repo_id)
149
+ dataset = lerobot_dataset.LeRobotDataset(
150
+ data_config.repo_id,
151
+ delta_timestamps={
152
+ key: [t / dataset_meta.fps for t in range(action_horizon)] for key in data_config.action_sequence_keys
153
+ },
154
+ )
155
+
156
+ if data_config.prompt_from_task:
157
+ dataset = TransformedDataset(dataset, [_transforms.PromptFromLeRobotTask(dataset_meta.tasks)])
158
+
159
+ return dataset
160
+
161
+
162
+ def create_rlds_dataset(
163
+ data_config: _config.DataConfig,
164
+ action_horizon: int,
165
+ batch_size: int,
166
+ *,
167
+ shuffle: bool = False,
168
+ ) -> Dataset:
169
+ # At the moment, we only support DROID for RLDS datasets.
170
+ return DroidRldsDataset(
171
+ data_dir=data_config.rlds_data_dir,
172
+ batch_size=batch_size,
173
+ shuffle=shuffle,
174
+ action_chunk_size=action_horizon,
175
+ action_space=data_config.action_space,
176
+ datasets=data_config.datasets,
177
+ )
178
+
179
+
180
+ def transform_dataset(dataset: Dataset, data_config: _config.DataConfig, *, skip_norm_stats: bool = False) -> Dataset:
181
+ """Transform the dataset by applying the data transforms."""
182
+ norm_stats = {}
183
+ if data_config.repo_id != "fake" and not skip_norm_stats:
184
+ if data_config.norm_stats is None:
185
+ raise ValueError(
186
+ "Normalization stats not found. "
187
+ "Make sure to run `scripts/compute_norm_stats.py --config-name=<your-config>`."
188
+ )
189
+ norm_stats = data_config.norm_stats
190
+
191
+ return TransformedDataset(
192
+ dataset,
193
+ [
194
+ *data_config.repack_transforms.inputs,
195
+ *data_config.data_transforms.inputs,
196
+ _transforms.Normalize(norm_stats, use_quantiles=data_config.use_quantile_norm),
197
+ *data_config.model_transforms.inputs,
198
+ ],
199
+ )
200
+
201
+
202
+ def transform_iterable_dataset(
203
+ dataset: IterableDataset,
204
+ data_config: _config.DataConfig,
205
+ *,
206
+ skip_norm_stats: bool = False,
207
+ is_batched: bool = False,
208
+ ) -> IterableDataset:
209
+ """Transform the dataset by applying the data transforms."""
210
+ norm_stats = {}
211
+ if data_config.repo_id != "fake" and not skip_norm_stats:
212
+ if data_config.norm_stats is None:
213
+ raise ValueError(
214
+ "Normalization stats not found. "
215
+ "Make sure to run `scripts/compute_norm_stats.py --config-name=<your-config>`."
216
+ )
217
+ norm_stats = data_config.norm_stats
218
+
219
+ return IterableTransformedDataset(
220
+ dataset,
221
+ [
222
+ *data_config.repack_transforms.inputs,
223
+ *data_config.data_transforms.inputs,
224
+ _transforms.Normalize(norm_stats, use_quantiles=data_config.use_quantile_norm),
225
+ *data_config.model_transforms.inputs,
226
+ ],
227
+ is_batched=is_batched,
228
+ )
229
+
230
+
231
+ def create_data_loader(
232
+ config: _config.TrainConfig,
233
+ *,
234
+ sharding: jax.sharding.Sharding | None = None,
235
+ shuffle: bool = False,
236
+ num_batches: int | None = None,
237
+ skip_norm_stats: bool = False,
238
+ framework: Literal["jax", "pytorch"] = "jax",
239
+ ) -> DataLoader[tuple[_model.Observation, _model.Actions]]:
240
+ """Create a data loader for training.
241
+
242
+ Args:
243
+ config: The training configuration.
244
+ sharding: The sharding to use for the data loader (JAX only).
245
+ shuffle: Whether to shuffle the data.
246
+ num_batches: Determines the number of batches to return.
247
+ skip_norm_stats: Whether to skip data normalization.
248
+ framework: The framework to use ("jax" or "pytorch").
249
+ """
250
+ data_config = config.data.create(config.assets_dirs, config.model)
251
+ logging.info(f"data_config: {data_config}")
252
+
253
+ if data_config.rlds_data_dir is not None:
254
+ return create_rlds_data_loader(
255
+ data_config,
256
+ action_horizon=config.model.action_horizon,
257
+ batch_size=config.batch_size,
258
+ sharding=sharding,
259
+ shuffle=shuffle,
260
+ num_batches=num_batches,
261
+ skip_norm_stats=skip_norm_stats,
262
+ framework=framework,
263
+ )
264
+ return create_torch_data_loader(
265
+ data_config,
266
+ model_config=config.model,
267
+ action_horizon=config.model.action_horizon,
268
+ batch_size=config.batch_size,
269
+ sharding=sharding,
270
+ shuffle=shuffle,
271
+ num_batches=num_batches,
272
+ num_workers=config.num_workers,
273
+ seed=config.seed,
274
+ skip_norm_stats=skip_norm_stats,
275
+ framework=framework,
276
+ )
277
+
278
+
279
+ def create_torch_data_loader(
280
+ data_config: _config.DataConfig,
281
+ model_config: _model.BaseModelConfig,
282
+ action_horizon: int,
283
+ batch_size: int,
284
+ *,
285
+ sharding: jax.sharding.Sharding | None = None,
286
+ skip_norm_stats: bool = False,
287
+ shuffle: bool = False,
288
+ num_batches: int | None = None,
289
+ num_workers: int = 0,
290
+ seed: int = 0,
291
+ framework: str = "jax",
292
+ ) -> DataLoader[tuple[_model.Observation, _model.Actions]]:
293
+ """Create a data loader for training.
294
+
295
+ Args:
296
+ data_config: The data configuration.
297
+ action_horizon: The action horizon.
298
+ batch_size: The batch size.
299
+ sharding: The sharding to use for the data loader. If None, the data loader will
300
+ use a single device sharding.
301
+ skip_norm_stats: Whether to skip data normalization.
302
+ shuffle: Whether to shuffle the data.
303
+ num_batches: Determines the number of batches to return. If the number exceeds the
304
+ number of batches in the dataset, the data loader will loop over the dataset.
305
+ If not provided, will iterate over the dataset indefinitely.
306
+ num_workers: The number of worker processes to use. If zero, the data loader will
307
+ execute in the main process.
308
+ seed: The seed to use for shuffling the data.
309
+ """
310
+ dataset = create_torch_dataset(data_config, action_horizon, model_config)
311
+ dataset = transform_dataset(dataset, data_config, skip_norm_stats=skip_norm_stats)
312
+
313
+ # Use TorchDataLoader for both frameworks
314
+ # For PyTorch DDP, create DistributedSampler and divide batch size by world size
315
+ # For JAX, divide by process count
316
+ sampler = None
317
+ if framework == "pytorch":
318
+ if torch.distributed.is_initialized():
319
+ sampler = torch.utils.data.distributed.DistributedSampler(
320
+ dataset,
321
+ num_replicas=torch.distributed.get_world_size(),
322
+ rank=torch.distributed.get_rank(),
323
+ shuffle=shuffle,
324
+ drop_last=True,
325
+ )
326
+ local_batch_size = batch_size // torch.distributed.get_world_size()
327
+ else:
328
+ local_batch_size = batch_size
329
+ else:
330
+ local_batch_size = batch_size // jax.process_count()
331
+
332
+ logging.info(f"local_batch_size: {local_batch_size}")
333
+ data_loader = TorchDataLoader(
334
+ dataset,
335
+ local_batch_size=local_batch_size,
336
+ sharding=None if framework == "pytorch" else sharding,
337
+ shuffle=(sampler is None and shuffle), # Don't shuffle if using sampler
338
+ sampler=sampler,
339
+ num_batches=num_batches,
340
+ num_workers=num_workers,
341
+ seed=seed,
342
+ framework=framework,
343
+ )
344
+
345
+ return DataLoaderImpl(data_config, data_loader)
346
+
347
+
348
+ def create_rlds_data_loader(
349
+ data_config: _config.DataConfig,
350
+ action_horizon: int,
351
+ batch_size: int,
352
+ *,
353
+ sharding: jax.sharding.Sharding | None = None,
354
+ skip_norm_stats: bool = False,
355
+ shuffle: bool = False,
356
+ num_batches: int | None = None,
357
+ framework: str = "jax",
358
+ ) -> DataLoader[tuple[_model.Observation, _model.Actions]]:
359
+ """Create an RLDS data loader for training.
360
+
361
+ Note: This data loader requires some extra dependencies -- see examples/droid/README_train.md
362
+
363
+ Args:
364
+ data_config: The data configuration.
365
+ action_horizon: The action horizon.
366
+ batch_size: The batch size.
367
+ sharding: The sharding to use for the data loader. If None, the data loader will
368
+ use a single device sharding.
369
+ skip_norm_stats: Whether to skip data normalization.
370
+ shuffle: Whether to shuffle the data.
371
+ num_batches: Determines the number of batches to return. If the number exceeds the
372
+ number of batches in the dataset, the data loader will loop over the dataset.
373
+ If not provided, will iterate over the dataset indefinitely.
374
+ """
375
+ if framework == "pytorch":
376
+ raise NotImplementedError("PyTorch RLDS data loader is not supported yet")
377
+ dataset = create_rlds_dataset(data_config, action_horizon, batch_size, shuffle=shuffle)
378
+ dataset = transform_iterable_dataset(dataset, data_config, skip_norm_stats=skip_norm_stats, is_batched=True)
379
+
380
+ data_loader = RLDSDataLoader(
381
+ dataset,
382
+ sharding=sharding,
383
+ num_batches=num_batches,
384
+ )
385
+
386
+ return DataLoaderImpl(data_config, data_loader)
387
+
388
+
389
+ class TorchDataLoader:
390
+ """Torch data loader implementation."""
391
+
392
+ def __init__(
393
+ self,
394
+ dataset,
395
+ local_batch_size: int,
396
+ *,
397
+ sharding: jax.sharding.Sharding | None = None,
398
+ shuffle: bool = False,
399
+ sampler: torch.utils.data.Sampler | None = None,
400
+ num_batches: int | None = None,
401
+ num_workers: int = 0,
402
+ seed: int = 0,
403
+ framework: str = "jax",
404
+ ):
405
+ """Create a PyTorch data loader.
406
+
407
+ Args:
408
+ dataset: The dataset to load.
409
+ local_batch_size: The local batch size for each process.
410
+ sharding: The sharding to use for the data loader.
411
+ shuffle: Whether to shuffle the data.
412
+ num_batches: If provided, determines the number of returned batches. If the
413
+ number is larger than the number of batches in the dataset, the data loader
414
+ will loop over the dataset. If not provided, will iterate over the dataset
415
+ indefinitely.
416
+ num_workers: The number of worker processes to use. If zero, the data loader will
417
+ execute in the main process.
418
+ seed: The seed to use for shuffling the data.
419
+ """
420
+ if jax.process_count() > 1:
421
+ raise NotImplementedError("Data loading with multiple processes is not supported.")
422
+
423
+ if len(dataset) < local_batch_size:
424
+ raise ValueError(f"Local batch size ({local_batch_size}) is larger than the dataset size ({len(dataset)}).")
425
+
426
+ # Store sharding - None for PyTorch, JAX sharding for JAX
427
+ self._sharding = sharding
428
+ if sharding is None and framework == "jax":
429
+ # Use data parallel sharding by default for JAX only.
430
+ self._sharding = jax.sharding.NamedSharding(
431
+ jax.sharding.Mesh(jax.devices(), ("B",)),
432
+ jax.sharding.PartitionSpec("B"),
433
+ )
434
+ self._num_batches = num_batches
435
+
436
+ mp_context = None
437
+ if num_workers > 0:
438
+ mp_context_name = os.getenv("OPENPI_TORCH_DATALOADER_MP_CONTEXT", "spawn")
439
+ if mp_context_name != "default":
440
+ mp_context = multiprocessing.get_context(mp_context_name)
441
+
442
+ generator = torch.Generator()
443
+ generator.manual_seed(seed)
444
+ self._data_loader = torch.utils.data.DataLoader(
445
+ typing.cast(torch.utils.data.Dataset, dataset),
446
+ batch_size=local_batch_size,
447
+ shuffle=(sampler is None and shuffle), # Don't shuffle if using sampler
448
+ sampler=sampler,
449
+ num_workers=num_workers,
450
+ multiprocessing_context=mp_context,
451
+ persistent_workers=num_workers > 0,
452
+ collate_fn=_collate_fn,
453
+ worker_init_fn=_worker_init_fn,
454
+ drop_last=True,
455
+ generator=generator,
456
+ )
457
+
458
+ @property
459
+ def torch_loader(self) -> torch.utils.data.DataLoader:
460
+ return self._data_loader
461
+
462
+ def __iter__(self):
463
+ num_items = 0
464
+ while True:
465
+ data_iter = iter(self._data_loader)
466
+ while True:
467
+ if self._num_batches is not None and num_items >= self._num_batches:
468
+ return
469
+ try:
470
+ batch = next(data_iter)
471
+ except StopIteration:
472
+ break # We've exhausted the dataset. Create a new iterator and start over.
473
+ num_items += 1
474
+ # For JAX, convert to sharded arrays; for PyTorch, return torch tensors
475
+ if self._sharding is not None:
476
+ yield jax.tree.map(lambda x: jax.make_array_from_process_local_data(self._sharding, x), batch)
477
+ else:
478
+ yield jax.tree.map(torch.as_tensor, batch)
479
+
480
+
481
+ def _collate_fn(items):
482
+ """Collate the batch elements into batched numpy arrays."""
483
+ # Make sure to convert to numpy arrays before stacking since some of the incoming elements
484
+ # may be JAX arrays.
485
+ return jax.tree.map(lambda *xs: np.stack([np.asarray(x) for x in xs], axis=0), *items)
486
+
487
+
488
+ def _worker_init_fn(worker_id: int) -> None:
489
+ """Tell JAX inside the worker process not to preallocate the GPU memory."""
490
+ # NOTE: This is called after jax is imported inside the worker process. This
491
+ # means that this approach will not work for selecting the backend.
492
+ os.environ["XLA_PYTHON_CLIENT_PREALLOCATE"] = "false"
493
+ os.environ["XLA_PYTHON_CLIENT_ALLOCATOR"] = "platform"
494
+
495
+
496
+ class RLDSDataLoader:
497
+ """Shallow wrapper around the DROID data loader to make it compatible with openpi.
498
+
499
+ All batching already happens in the DROID dataset, so we don't need to do anything here.
500
+ """
501
+
502
+ def __init__(
503
+ self,
504
+ dataset: DroidRldsDataset,
505
+ *,
506
+ sharding: jax.sharding.Sharding | None = None,
507
+ num_batches: int | None = None,
508
+ ):
509
+ self._dataset = dataset
510
+ self._num_batches = num_batches
511
+
512
+ if jax.process_count() > 1:
513
+ raise NotImplementedError("Data loading with multiple processes is not supported.")
514
+
515
+ if sharding is None:
516
+ # Use data parallel sharding by default.
517
+ sharding = jax.sharding.NamedSharding(
518
+ jax.sharding.Mesh(jax.devices(), ("B",)),
519
+ jax.sharding.PartitionSpec("B"),
520
+ )
521
+
522
+ self._sharding = sharding
523
+ self._num_batches = num_batches
524
+
525
+ def __iter__(self):
526
+ num_items = 0
527
+ while True:
528
+ data_iter = iter(self._dataset)
529
+ while True:
530
+ if self._num_batches is not None and num_items >= self._num_batches:
531
+ return
532
+ try:
533
+ batch = next(data_iter)
534
+ except StopIteration:
535
+ break # We've exhausted the dataset. Create a new iterator and start over.
536
+ num_items += 1
537
+ yield jax.tree.map(lambda x: jax.make_array_from_process_local_data(self._sharding, x), batch)
538
+
539
+
540
+ class DataLoaderImpl(DataLoader):
541
+ def __init__(self, data_config: _config.DataConfig, data_loader: TorchDataLoader | RLDSDataLoader):
542
+ self._data_config = data_config
543
+ self._data_loader = data_loader
544
+
545
+ def data_config(self) -> _config.DataConfig:
546
+ return self._data_config
547
+
548
+ def __iter__(self):
549
+ for batch in self._data_loader:
550
+ yield _model.Observation.from_dict(batch), batch["actions"]
bundle/code/openpi/src/openpi/training/kinova_lerobot_v3_dataset.py ADDED
@@ -0,0 +1,169 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from collections.abc import Sequence
2
+ import json
3
+ import os
4
+ from pathlib import Path
5
+ from typing import Any
6
+
7
+ import numpy as np
8
+ import pandas as pd
9
+ import torch
10
+
11
+ from lerobot.common.datasets import utils as lerobot_utils
12
+ from lerobot.common.datasets.video_utils import decode_video_frames
13
+ from lerobot.common.datasets.video_utils import get_safe_default_codec
14
+
15
+ REPO_ID = "lsnu/TeddyBearKinovaTestSetLeRobot"
16
+
17
+
18
+ def _to_python(value: Any) -> Any:
19
+ if isinstance(value, np.generic):
20
+ return value.item()
21
+ if isinstance(value, np.ndarray):
22
+ return value.tolist()
23
+ return value
24
+
25
+
26
+ def locate_dataset_root() -> Path:
27
+ candidates = [
28
+ Path("/workspace/data/teddybear_kinova_full"),
29
+ Path.home() / ".cache" / "huggingface" / "lerobot" / REPO_ID,
30
+ ]
31
+ for candidate in candidates:
32
+ if (candidate / "meta" / "info.json").exists():
33
+ return candidate
34
+ raise FileNotFoundError(
35
+ "TeddyBear Kinova dataset not found locally. Expected it under "
36
+ "/workspace/data/teddybear_kinova_full or ~/.cache/huggingface/lerobot/lsnu/TeddyBearKinovaTestSetLeRobot."
37
+ )
38
+
39
+
40
+ class KinovaLeRobotV3Dataset:
41
+ def __init__(
42
+ self,
43
+ action_horizon: int,
44
+ action_sequence_keys: Sequence[str],
45
+ *,
46
+ tolerance_s: float = 0.05,
47
+ video_backend: str | None = None,
48
+ load_videos: bool = True,
49
+ ):
50
+ self.root = locate_dataset_root()
51
+ self.info = json.loads((self.root / "meta" / "info.json").read_text())
52
+ self.fps = int(self.info["fps"])
53
+ self.features = self.info["features"]
54
+ self.video_keys = [key for key, feature in self.features.items() if feature["dtype"] == "video"]
55
+ self.camera_keys = list(self.video_keys)
56
+ self.video_shapes = {
57
+ key: self._feature_shape_to_chw(self.features[key]["shape"]) for key in self.video_keys
58
+ }
59
+ # TorchCodec is discoverable in this environment but not linked against a usable FFmpeg runtime.
60
+ # Prefer the stable CPU pyav path unless an explicit backend is requested.
61
+ self.video_backend = video_backend or "pyav"
62
+ self.tolerance_s = tolerance_s
63
+ self.load_videos = load_videos
64
+
65
+ tasks_df = pd.read_parquet(self.root / "meta" / "tasks.parquet")
66
+ self.tasks = {int(row["task_index"]): str(index) for index, row in tasks_df.iterrows()}
67
+
68
+ episodes_df = pd.concat(
69
+ [pd.read_parquet(path) for path in sorted((self.root / "meta" / "episodes").rglob("*.parquet"))],
70
+ ignore_index=True,
71
+ ).sort_values("episode_index")
72
+ self.episodes = {
73
+ int(record["episode_index"]): {key: _to_python(value) for key, value in record.items()}
74
+ for record in episodes_df.to_dict("records")
75
+ }
76
+
77
+ data_df = pd.concat(
78
+ [pd.read_parquet(path) for path in sorted((self.root / "data").rglob("*.parquet"))],
79
+ ignore_index=True,
80
+ ).sort_values("index")
81
+ self.data = {column: data_df[column].tolist() for column in data_df.columns}
82
+
83
+ self.episode_data_index = lerobot_utils.get_episode_data_index(self.episodes)
84
+
85
+ delta_timestamps = {key: [t / self.fps for t in range(action_horizon)] for key in action_sequence_keys}
86
+ lerobot_utils.check_delta_timestamps(delta_timestamps, self.fps, self.tolerance_s)
87
+ self.delta_indices = lerobot_utils.get_delta_indices(delta_timestamps, self.fps)
88
+
89
+ def __len__(self) -> int:
90
+ return len(self.data["index"])
91
+
92
+ @staticmethod
93
+ def _feature_shape_to_chw(shape: Sequence[int]) -> tuple[int, int, int]:
94
+ if len(shape) != 3:
95
+ raise ValueError(f"Expected a 3D video shape, got {shape}")
96
+ if shape[-1] == 3:
97
+ height, width, channels = shape
98
+ return channels, height, width
99
+ channels, height, width = shape
100
+ return channels, height, width
101
+
102
+ def _get_query_indices(self, idx: int, ep_idx: int) -> tuple[dict[str, list[int]], dict[str, torch.BoolTensor]]:
103
+ ep_start = self.episode_data_index["from"][ep_idx].item()
104
+ ep_end = self.episode_data_index["to"][ep_idx].item()
105
+ query_indices = {
106
+ key: [max(ep_start, min(ep_end - 1, idx + delta)) for delta in delta_idx]
107
+ for key, delta_idx in self.delta_indices.items()
108
+ }
109
+ padding = {
110
+ f"{key}_is_pad": torch.BoolTensor([(idx + delta < ep_start) | (idx + delta >= ep_end) for delta in delta_idx])
111
+ for key, delta_idx in self.delta_indices.items()
112
+ }
113
+ return query_indices, padding
114
+
115
+ def _get_video_path(self, ep_idx: int, vid_key: str) -> Path:
116
+ episode = self.episodes[ep_idx]
117
+ return self.root / self.info["video_path"].format(
118
+ video_key=vid_key,
119
+ chunk_index=int(episode[f"videos/{vid_key}/chunk_index"]),
120
+ file_index=int(episode[f"videos/{vid_key}/file_index"]),
121
+ )
122
+
123
+ def _query_videos(self, timestamps: dict[str, list[float]], ep_idx: int) -> dict[str, torch.Tensor]:
124
+ if not self.load_videos:
125
+ return {
126
+ vid_key: torch.zeros((len(query_ts), *self.video_shapes[vid_key]), dtype=torch.float32).squeeze(0)
127
+ for vid_key, query_ts in timestamps.items()
128
+ }
129
+ episode = self.episodes[ep_idx]
130
+ item = {}
131
+ for vid_key, query_ts in timestamps.items():
132
+ offset = float(episode[f"videos/{vid_key}/from_timestamp"])
133
+ frames = decode_video_frames(
134
+ self._get_video_path(ep_idx, vid_key),
135
+ [ts + offset for ts in query_ts],
136
+ self.tolerance_s,
137
+ self.video_backend,
138
+ )
139
+ item[vid_key] = frames.squeeze(0)
140
+ return item
141
+
142
+ def __getitem__(self, idx: int) -> dict[str, Any]:
143
+ item = {key: self.data[key][idx] for key in self.data}
144
+ ep_idx = int(item["episode_index"])
145
+
146
+ query_indices, padding = self._get_query_indices(idx, ep_idx)
147
+ item.update(padding)
148
+ for key, indices in query_indices.items():
149
+ if key in self.video_keys:
150
+ continue
151
+ item[key] = torch.stack([torch.tensor(self.data[key][query_idx]) for query_idx in indices])
152
+
153
+ # LeRobot v3 keeps the raw sync-clock timestamp for tabular data, but the episode videos are
154
+ # encoded on the nominal frame grid implied by `frame_index` and `fps`. Querying by the raw
155
+ # timestamp causes systematic tail mismatches at episode ends, so use frame-index time for
156
+ # video lookup.
157
+ current_video_ts = float(item["frame_index"]) / self.fps
158
+ query_timestamps = {key: [current_video_ts] for key in self.video_keys}
159
+ item.update(self._query_videos(query_timestamps, ep_idx))
160
+
161
+ for key, value in list(item.items()):
162
+ if isinstance(value, torch.Tensor):
163
+ continue
164
+ if isinstance(value, str):
165
+ continue
166
+ item[key] = torch.tensor(value)
167
+
168
+ item["task"] = self.tasks[int(item["task_index"].item())]
169
+ return item
bundle/code/openpi/uv.lock ADDED
The diff for this file is too large to render. See raw diff
 
bundle/run_rollout_preview.sh ADDED
@@ -0,0 +1,22 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ OPENPI_ROOT="${1:-$HOME/workspace/teddybear_openpi/openpi}"
5
+ CHECKPOINT_DIR="${2:-$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)/4000}"
6
+ OUT_ROOT="${3:-$HOME/workspace/teddybear_rollout}"
7
+ BUNDLE_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
8
+
9
+ mkdir -p "$OUT_ROOT"
10
+ cd "$OPENPI_ROOT"
11
+
12
+ export JAX_PLATFORMS="${JAX_PLATFORMS:-cuda}"
13
+
14
+ .venv/bin/python "$BUNDLE_ROOT/sim/rollout_pi_policy.py" \
15
+ --checkpoint-dir "$CHECKPOINT_DIR" \
16
+ --output-json "$OUT_ROOT/pi_rollout.json"
17
+
18
+ python "$BUNDLE_ROOT/sim/render_pose_sequence.py" \
19
+ --poses-json "$OUT_ROOT/pi_rollout.json" \
20
+ --output "$OUT_ROOT/pi_rollout.gif"
21
+
22
+ echo "$OUT_ROOT"
bundle/setup_same_a100.sh ADDED
@@ -0,0 +1,32 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ BUNDLE_ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
5
+ TARGET_ROOT="${1:-$HOME/workspace/teddybear_openpi}"
6
+
7
+ mkdir -p "$TARGET_ROOT"
8
+ mkdir -p "$TARGET_ROOT/openpi"
9
+ mkdir -p "$TARGET_ROOT/sim"
10
+
11
+ if ! command -v uv >/dev/null 2>&1; then
12
+ curl -LsSf https://astral.sh/uv/install.sh | sh
13
+ export PATH="$HOME/.cargo/bin:$PATH"
14
+ fi
15
+
16
+ if ! command -v hf >/dev/null 2>&1; then
17
+ curl -LsSf https://hf.co/cli/install.sh | bash -s
18
+ fi
19
+
20
+ if [[ -n "${HF_TOKEN:-}" ]]; then
21
+ hf auth whoami >/dev/null 2>&1 || hf auth login --token "$HF_TOKEN"
22
+ fi
23
+
24
+ cp -a "$BUNDLE_ROOT/code/openpi/." "$TARGET_ROOT/openpi/"
25
+ cp -a "$BUNDLE_ROOT/sim/." "$TARGET_ROOT/sim/"
26
+
27
+ cd "$TARGET_ROOT/openpi"
28
+ uv sync --frozen
29
+ . .venv/bin/activate
30
+ pip install scipy opencv-python-headless
31
+
32
+ echo "$TARGET_ROOT"
bundle/sim/build_scene.py ADDED
@@ -0,0 +1,103 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ from pathlib import Path
5
+
6
+ import cv2
7
+ import numpy as np
8
+ import pandas as pd
9
+ from PIL import Image
10
+
11
+ from scene_tools import (
12
+ create_background_inpaint,
13
+ load_scene_calibration,
14
+ render_scene,
15
+ save_scene_json,
16
+ )
17
+
18
+
19
+ def _save_mask_overlay(rgb: np.ndarray, mask: np.ndarray, color: tuple[int, int, int], path: Path) -> None:
20
+ overlay = rgb.copy()
21
+ overlay[mask] = color
22
+ Image.fromarray(overlay).save(path)
23
+
24
+
25
+ def _save_box_outline(rgb: np.ndarray, polygon_world: np.ndarray, calibration, path: Path) -> None:
26
+ canvas = rgb.copy()
27
+ image_points, _ = cv2.projectPoints(
28
+ polygon_world.astype(np.float64), calibration.rvec, calibration.tvec, calibration.camera_matrix, None
29
+ )
30
+ pts = np.round(image_points[:, 0, :]).astype(np.int32)
31
+ cv2.polylines(canvas, [pts], True, (255, 0, 0), 4)
32
+ Image.fromarray(canvas).save(path)
33
+
34
+
35
+ def main() -> None:
36
+ parser = argparse.ArgumentParser()
37
+ parser.add_argument(
38
+ "--session-root",
39
+ default="/workspace/data/teddybear_raw/session_20260327_165944_bear",
40
+ help="Raw session root used for calibration.",
41
+ )
42
+ parser.add_argument(
43
+ "--sync-row-index",
44
+ type=int,
45
+ default=0,
46
+ help="Row of sync_index.csv to use as the start frame.",
47
+ )
48
+ parser.add_argument(
49
+ "--output-dir",
50
+ default="/workspace/kinova_scene_sim/outputs",
51
+ help="Directory for the scene JSON and visual checks.",
52
+ )
53
+ args = parser.parse_args()
54
+
55
+ output_dir = Path(args.output_dir)
56
+ output_dir.mkdir(parents=True, exist_ok=True)
57
+
58
+ calibration = load_scene_calibration(args.session_root, args.sync_row_index)
59
+ sync = pd.read_csv(Path(args.session_root) / "sync_index.csv")
60
+ start_q = sync.iloc[args.sync_row_index][[f"q{i}_deg" for i in range(1, 8)]].to_numpy(np.float64)
61
+ motion_q = sync.iloc[[0, 56, 70, 84, 98, 112]][[f"q{i}_deg" for i in range(1, 8)]].to_numpy(np.float64)
62
+
63
+ background = create_background_inpaint(calibration.rgb)
64
+ scene_json = output_dir / f"{Path(args.session_root).name}_scene_fit.json"
65
+ save_scene_json(calibration, scene_json)
66
+
67
+ Image.fromarray(calibration.rgb).save(output_dir / "real_start.png")
68
+ Image.fromarray(background).save(output_dir / "background_inpaint.png")
69
+
70
+ _save_mask_overlay(calibration.rgb, calibration.box_mask, (255, 0, 0), output_dir / "box_mask_overlay.png")
71
+ _save_mask_overlay(calibration.rgb, calibration.teddy_mask, (0, 255, 0), output_dir / "teddy_mask_overlay.png")
72
+ _save_box_outline(calibration.rgb, calibration.box_world_polygon, calibration, output_dir / "box_world_outline.png")
73
+
74
+ start_render = render_scene(calibration, start_q, background=background)
75
+ Image.fromarray(start_render).save(output_dir / "scene_start_render.png")
76
+
77
+ colors = [
78
+ (255, 64, 64),
79
+ (64, 255, 64),
80
+ (64, 64, 255),
81
+ (255, 255, 64),
82
+ (255, 64, 255),
83
+ (64, 255, 255),
84
+ ]
85
+ motion_render = background.copy()
86
+ for q_deg, color in zip(motion_q, colors):
87
+ motion_render = render_scene(calibration, q_deg, background=motion_render, color=color, alpha=0.95)
88
+ Image.fromarray(motion_render).save(output_dir / "scene_motion_fit.png")
89
+
90
+ side_by_side = np.concatenate([calibration.rgb, start_render], axis=1)
91
+ Image.fromarray(side_by_side).save(output_dir / "real_vs_scene_start.png")
92
+
93
+ print(f"saved scene json to {scene_json}")
94
+ print(f"start frame: azure_rgb/{calibration.azure_rgb_seq:06d}.jpg")
95
+ print(f"depth frame: azure_depth/{calibration.azure_depth_seq:06d}.png")
96
+ print(f"robot seq: {calibration.robot_seq}")
97
+ print(f"box height estimate: {calibration.box_height_m:.3f} m")
98
+ print(f"teddy height estimate: {calibration.teddy_height_m:.3f} m")
99
+ print(f"teddy center world: {calibration.teddy_world_center.tolist()}")
100
+
101
+
102
+ if __name__ == "__main__":
103
+ main()
bundle/sim/export_pi_actions.py ADDED
@@ -0,0 +1,84 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import json
5
+ import time
6
+ from pathlib import Path
7
+
8
+ import numpy as np
9
+ import pandas as pd
10
+ from PIL import Image
11
+
12
+
13
+ def main() -> None:
14
+ t0 = time.time()
15
+ parser = argparse.ArgumentParser()
16
+ parser.add_argument("--checkpoint-dir", required=True, help="Local checkpoint directory, e.g. .../4000")
17
+ parser.add_argument("--session-root", default="/workspace/data/teddybear_raw/session_20260327_165944_bear")
18
+ parser.add_argument("--sync-row-index", type=int, default=0)
19
+ parser.add_argument("--config-name", default="pi05_kinova_teddybear")
20
+ parser.add_argument("--output-json", default="/workspace/kinova_scene_sim/outputs/pi_actions.json")
21
+ parser.add_argument("--prompt", default="pick up the teddy bear and place it in the red box")
22
+ args = parser.parse_args()
23
+
24
+ session_root = Path(args.session_root)
25
+ print(f"[export] loading session from {session_root}", flush=True)
26
+ sync = pd.read_csv(session_root / "sync_index.csv")
27
+ row = sync.iloc[args.sync_row_index]
28
+
29
+ azure_rgb = np.array(Image.open(session_root / row["azure_rgb_file"]).convert("RGB"))
30
+ wrist_rgb = np.array(Image.open(session_root / row["rgb_file"]).convert("RGB"))
31
+ state = np.array(
32
+ [
33
+ row["tool_x_m"],
34
+ row["tool_y_m"],
35
+ row["tool_z_m"],
36
+ row["tool_theta_x_deg"],
37
+ row["tool_theta_y_deg"],
38
+ row["tool_theta_z_deg"],
39
+ row["gripper_pos"],
40
+ ],
41
+ dtype=np.float32,
42
+ )
43
+ print(f"[export] loaded observation in {time.time() - t0:.2f}s", flush=True)
44
+
45
+ print("[export] importing openpi modules", flush=True)
46
+ from openpi.policies import policy_config as _policy_config
47
+ from openpi.training import config as _config
48
+
49
+ print(f"[export] imported openpi in {time.time() - t0:.2f}s", flush=True)
50
+ print(f"[export] building train config {args.config_name}", flush=True)
51
+ train_config = _config.get_config(args.config_name)
52
+ print(f"[export] creating policy from {args.checkpoint_dir}", flush=True)
53
+ policy = _policy_config.create_trained_policy(train_config, Path(args.checkpoint_dir))
54
+ print(f"[export] policy ready in {time.time() - t0:.2f}s", flush=True)
55
+ print("[export] running inference", flush=True)
56
+ results = policy.infer(
57
+ {
58
+ "observation/state": state,
59
+ "observation/image": azure_rgb,
60
+ "observation/wrist_image": wrist_rgb,
61
+ "prompt": args.prompt,
62
+ }
63
+ )
64
+ print(f"[export] inference done in {time.time() - t0:.2f}s", flush=True)
65
+
66
+ actions = np.asarray(results["actions"], dtype=np.float32)
67
+ output = {
68
+ "checkpoint_dir": str(Path(args.checkpoint_dir)),
69
+ "session_root": str(session_root),
70
+ "sync_row_index": int(args.sync_row_index),
71
+ "azure_rgb_file": str(row["azure_rgb_file"]),
72
+ "wrist_rgb_file": str(row["rgb_file"]),
73
+ "state": state.tolist(),
74
+ "actions": actions.tolist(),
75
+ }
76
+
77
+ output_path = Path(args.output_json)
78
+ output_path.parent.mkdir(parents=True, exist_ok=True)
79
+ output_path.write_text(json.dumps(output, indent=2))
80
+ print(f"saved action chunk to {output_path}")
81
+
82
+
83
+ if __name__ == "__main__":
84
+ main()
bundle/sim/render_pose_sequence.py ADDED
@@ -0,0 +1,108 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import json
5
+ from pathlib import Path
6
+
7
+ import cv2
8
+ import numpy as np
9
+ import pandas as pd
10
+ from PIL import Image
11
+ from scipy.optimize import least_squares
12
+
13
+ from scene_tools import create_background_inpaint, kinova_fk_points_and_tool_pose, load_scene_calibration, render_scene
14
+
15
+
16
+ def euler_xyz_deg_to_matrix(theta_x_deg: float, theta_y_deg: float, theta_z_deg: float) -> np.ndarray:
17
+ rx, ry, rz = np.deg2rad([theta_x_deg, theta_y_deg, theta_z_deg])
18
+ cx, sx = np.cos(rx), np.sin(rx)
19
+ cy, sy = np.cos(ry), np.sin(ry)
20
+ cz, sz = np.cos(rz), np.sin(rz)
21
+ rot_x = np.array([[1, 0, 0], [0, cx, -sx], [0, sx, cx]], dtype=np.float64)
22
+ rot_y = np.array([[cy, 0, sy], [0, 1, 0], [-sy, 0, cy]], dtype=np.float64)
23
+ rot_z = np.array([[cz, -sz, 0], [sz, cz, 0], [0, 0, 1]], dtype=np.float64)
24
+ return rot_z @ rot_y @ rot_x
25
+
26
+
27
+ def solve_ik(target_pose: np.ndarray, q_init_deg: np.ndarray) -> np.ndarray:
28
+ target_pos = target_pose[:3].astype(np.float64)
29
+ target_rot = euler_xyz_deg_to_matrix(*target_pose[3:6])
30
+ q_init = np.asarray(q_init_deg, dtype=np.float64)
31
+
32
+ def residual(q_deg: np.ndarray) -> np.ndarray:
33
+ _, tool = kinova_fk_points_and_tool_pose(q_deg)
34
+ pos_err = tool[:3, 3] - target_pos
35
+ rot_err_mat = tool[:3, :3].T @ target_rot
36
+ rot_err, _ = cv2.Rodrigues(rot_err_mat)
37
+ regularize = 0.01 * (q_deg - q_init)
38
+ return np.concatenate([12.0 * pos_err, 0.75 * rot_err.reshape(-1), regularize])
39
+
40
+ result = least_squares(residual, q_init, method="lm", max_nfev=120)
41
+ return result.x.astype(np.float64)
42
+
43
+
44
+ def load_target_poses(args: argparse.Namespace) -> tuple[np.ndarray, np.ndarray]:
45
+ if args.poses_json:
46
+ payload = json.loads(Path(args.poses_json).read_text())
47
+ if isinstance(payload, dict) and "actions" in payload:
48
+ poses = np.asarray(payload["actions"], dtype=np.float64)
49
+ else:
50
+ poses = np.asarray(payload, dtype=np.float64)
51
+ start_q = np.asarray(args.q_init_deg, dtype=np.float64)
52
+ return poses, start_q
53
+
54
+ sync = pd.read_csv(Path(args.session_root) / "sync_index.csv")
55
+ rows = sync.iloc[args.sync_start : args.sync_stop : args.sync_step]
56
+ poses = rows[
57
+ ["tool_x_m", "tool_y_m", "tool_z_m", "tool_theta_x_deg", "tool_theta_y_deg", "tool_theta_z_deg", "gripper_pos"]
58
+ ].to_numpy(np.float64)
59
+ start_q = rows.iloc[0][[f"q{i}_deg" for i in range(1, 8)]].to_numpy(np.float64)
60
+ return poses, start_q
61
+
62
+
63
+ def main() -> None:
64
+ parser = argparse.ArgumentParser()
65
+ parser.add_argument("--session-root", default="/workspace/data/teddybear_raw/session_20260327_165944_bear")
66
+ parser.add_argument("--output", default="/workspace/kinova_scene_sim/outputs/rollout.gif")
67
+ parser.add_argument("--poses-json", default=None, help="JSON file containing a list of 7D tool poses.")
68
+ parser.add_argument(
69
+ "--q-init-deg",
70
+ nargs=7,
71
+ type=float,
72
+ default=[0.0008167303, 340.0004272461, 180.0014038086, 213.9954223633, 359.9988708496, 309.9989318848, 90.0014266968],
73
+ help="Initial joint seed for IK when using --poses-json.",
74
+ )
75
+ parser.add_argument("--sync-start", type=int, default=0)
76
+ parser.add_argument("--sync-stop", type=int, default=130)
77
+ parser.add_argument("--sync-step", type=int, default=8)
78
+ parser.add_argument("--fps", type=int, default=5)
79
+ args = parser.parse_args()
80
+
81
+ calibration = load_scene_calibration(args.session_root, sync_row_index=0)
82
+ background = create_background_inpaint(calibration.rgb)
83
+ poses, q_seed = load_target_poses(args)
84
+
85
+ frames: list[Image.Image] = []
86
+ q_current = q_seed.copy()
87
+ for idx, pose in enumerate(poses):
88
+ q_current = solve_ik(pose, q_current)
89
+ frame = render_scene(calibration, q_current, background=background)
90
+ # Mark the target tool center on the rendered frame.
91
+ points_world, _ = kinova_fk_points_and_tool_pose(q_current)
92
+ _ = points_world # quiet lint-like readers; pose solving already uses the FK.
93
+ frames.append(Image.fromarray(frame))
94
+
95
+ output = Path(args.output)
96
+ output.parent.mkdir(parents=True, exist_ok=True)
97
+ frames[0].save(
98
+ output,
99
+ save_all=True,
100
+ append_images=frames[1:],
101
+ loop=0,
102
+ duration=int(1000 / max(args.fps, 1)),
103
+ )
104
+ print(f"saved rollout gif to {output}")
105
+
106
+
107
+ if __name__ == "__main__":
108
+ main()
bundle/sim/rollout_pi_policy.py ADDED
@@ -0,0 +1,97 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import json
5
+ import time
6
+ from pathlib import Path
7
+
8
+ import numpy as np
9
+ import pandas as pd
10
+ from PIL import Image
11
+
12
+
13
+ def main() -> None:
14
+ t0 = time.time()
15
+ parser = argparse.ArgumentParser()
16
+ parser.add_argument("--checkpoint-dir", required=True)
17
+ parser.add_argument("--session-root", default="/workspace/data/teddybear_raw/session_20260327_165944_bear")
18
+ parser.add_argument("--sync-row-index", type=int, default=0)
19
+ parser.add_argument("--config-name", default="pi05_kinova_teddybear")
20
+ parser.add_argument("--prompt", default="pick up the teddy bear and place it in the red box")
21
+ parser.add_argument("--rollout-steps", type=int, default=24)
22
+ parser.add_argument("--output-json", default="/workspace/kinova_scene_sim/outputs/pi_rollout.json")
23
+ args = parser.parse_args()
24
+
25
+ session_root = Path(args.session_root)
26
+ print(f"[rollout] loading session from {session_root}", flush=True)
27
+ sync = pd.read_csv(session_root / "sync_index.csv")
28
+ row = sync.iloc[args.sync_row_index]
29
+
30
+ azure_rgb = np.array(Image.open(session_root / row["azure_rgb_file"]).convert("RGB"))
31
+ wrist_rgb = np.array(Image.open(session_root / row["rgb_file"]).convert("RGB"))
32
+ state = np.array(
33
+ [
34
+ row["tool_x_m"],
35
+ row["tool_y_m"],
36
+ row["tool_z_m"],
37
+ row["tool_theta_x_deg"],
38
+ row["tool_theta_y_deg"],
39
+ row["tool_theta_z_deg"],
40
+ row["gripper_pos"],
41
+ ],
42
+ dtype=np.float32,
43
+ )
44
+ print(f"[rollout] loaded observation in {time.time() - t0:.2f}s", flush=True)
45
+
46
+ print("[rollout] importing openpi modules", flush=True)
47
+ from openpi.policies import policy_config as _policy_config
48
+ from openpi.training import config as _config
49
+
50
+ print(f"[rollout] imported openpi in {time.time() - t0:.2f}s", flush=True)
51
+ train_config = _config.get_config(args.config_name)
52
+ print(f"[rollout] creating policy from {args.checkpoint_dir}", flush=True)
53
+ policy = _policy_config.create_trained_policy(train_config, Path(args.checkpoint_dir))
54
+ print(f"[rollout] policy ready in {time.time() - t0:.2f}s", flush=True)
55
+
56
+ states = [state.astype(np.float32)]
57
+ chunks = []
58
+ current_state = state.astype(np.float32)
59
+ for step_idx in range(args.rollout_steps):
60
+ results = policy.infer(
61
+ {
62
+ "observation/state": current_state,
63
+ "observation/image": azure_rgb,
64
+ "observation/wrist_image": wrist_rgb,
65
+ "prompt": args.prompt,
66
+ }
67
+ )
68
+ chunk = np.asarray(results["actions"], dtype=np.float32)
69
+ chunks.append(chunk)
70
+ current_state = chunk[0].copy()
71
+ states.append(current_state)
72
+ print(
73
+ f"[rollout] step={step_idx + 1}/{args.rollout_steps} "
74
+ f"xyz={current_state[:3].tolist()} grip={float(current_state[6]):.3f}",
75
+ flush=True,
76
+ )
77
+
78
+ output = {
79
+ "checkpoint_dir": str(Path(args.checkpoint_dir)),
80
+ "session_root": str(session_root),
81
+ "sync_row_index": int(args.sync_row_index),
82
+ "azure_rgb_file": str(row["azure_rgb_file"]),
83
+ "wrist_rgb_file": str(row["rgb_file"]),
84
+ "initial_state": state.tolist(),
85
+ "states": np.stack(states, axis=0).tolist(),
86
+ "actions": np.stack(states[1:], axis=0).tolist(),
87
+ "chunks": np.stack(chunks, axis=0).tolist(),
88
+ }
89
+
90
+ output_path = Path(args.output_json)
91
+ output_path.parent.mkdir(parents=True, exist_ok=True)
92
+ output_path.write_text(json.dumps(output, indent=2))
93
+ print(f"[rollout] saved rollout to {output_path}", flush=True)
94
+
95
+
96
+ if __name__ == "__main__":
97
+ main()
bundle/sim/run_policy_preview.py ADDED
@@ -0,0 +1,136 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import os
5
+ import shutil
6
+ import subprocess
7
+ import sys
8
+ import time
9
+ from pathlib import Path
10
+
11
+
12
+ def checkpoint_ready(checkpoint_dir: Path) -> bool:
13
+ return (checkpoint_dir / "_CHECKPOINT_METADATA").is_file() and (checkpoint_dir / "params" / "_METADATA").is_file()
14
+
15
+
16
+ def wait_for_checkpoint(checkpoint_dir: Path, poll_s: float) -> None:
17
+ while not checkpoint_ready(checkpoint_dir):
18
+ print(f"waiting for checkpoint: {checkpoint_dir}", flush=True)
19
+ time.sleep(poll_s)
20
+
21
+
22
+ def pid_running(pid: int) -> bool:
23
+ return Path(f"/proc/{pid}").exists()
24
+
25
+
26
+ def wait_for_pid_exit(pid: int, poll_s: float) -> None:
27
+ while pid_running(pid):
28
+ print(f"waiting for pid to exit: {pid}", flush=True)
29
+ time.sleep(poll_s)
30
+
31
+
32
+ def stage_checkpoint(checkpoint_dir: Path, stage_root: Path) -> Path:
33
+ stage_root.mkdir(parents=True, exist_ok=True)
34
+ staged_dir = stage_root / checkpoint_dir.name
35
+ if staged_dir.exists():
36
+ shutil.rmtree(staged_dir)
37
+ subprocess.run(["cp", "-al", str(checkpoint_dir), str(stage_root)], check=True)
38
+ return staged_dir
39
+
40
+
41
+ def main() -> None:
42
+ parser = argparse.ArgumentParser()
43
+ parser.add_argument("--checkpoint-dir", default=None, help="Checkpoint step directory, e.g. .../4000")
44
+ parser.add_argument(
45
+ "--checkpoint-root",
46
+ default="/workspace/openpi/checkpoints/pi05_kinova_teddybear/teddybear_kinova_ft_v4_b24_w12_fork",
47
+ help="Checkpoint experiment root used with --step.",
48
+ )
49
+ parser.add_argument("--step", type=int, default=None, help="Checkpoint step under --checkpoint-root.")
50
+ parser.add_argument("--wait", action="store_true", help="Wait until the checkpoint has finalized before exporting.")
51
+ parser.add_argument("--poll-s", type=float, default=15.0)
52
+ parser.add_argument("--wait-for-pid-exit", type=int, default=None, help="Wait for this PID to exit before export.")
53
+ parser.add_argument(
54
+ "--stage-root",
55
+ default=None,
56
+ help="Optional directory where the finalized checkpoint is hardlink-staged before export.",
57
+ )
58
+ parser.add_argument("--session-root", default="/workspace/data/teddybear_raw/session_20260327_165944_bear")
59
+ parser.add_argument("--sync-row-index", type=int, default=0)
60
+ parser.add_argument("--prompt", default="pick up the teddy bear and place it in the red box")
61
+ parser.add_argument(
62
+ "--python",
63
+ default="/workspace/openpi/.venv/bin/python",
64
+ help="Python interpreter used to run the OpenPI export step.",
65
+ )
66
+ parser.add_argument(
67
+ "--jax-platforms",
68
+ default="cpu",
69
+ help="Value for JAX_PLATFORMS during action export. Use 'cuda' once training has stopped.",
70
+ )
71
+ parser.add_argument(
72
+ "--output-json",
73
+ default="/workspace/kinova_scene_sim/outputs/pi_actions_preview.json",
74
+ )
75
+ parser.add_argument(
76
+ "--output-gif",
77
+ default="/workspace/kinova_scene_sim/outputs/pi_policy_preview.gif",
78
+ )
79
+ parser.add_argument("--fps", type=int, default=4)
80
+ args = parser.parse_args()
81
+
82
+ if args.checkpoint_dir is None:
83
+ if args.step is None:
84
+ raise ValueError("provide either --checkpoint-dir or --step")
85
+ checkpoint_dir = Path(args.checkpoint_root) / str(args.step)
86
+ else:
87
+ checkpoint_dir = Path(args.checkpoint_dir)
88
+
89
+ if args.wait:
90
+ wait_for_checkpoint(checkpoint_dir, args.poll_s)
91
+ elif not checkpoint_ready(checkpoint_dir):
92
+ raise FileNotFoundError(f"checkpoint not ready: {checkpoint_dir}")
93
+
94
+ if args.stage_root is not None:
95
+ checkpoint_dir = stage_checkpoint(checkpoint_dir, Path(args.stage_root))
96
+ print(f"staged checkpoint to {checkpoint_dir}", flush=True)
97
+
98
+ if args.wait_for_pid_exit is not None:
99
+ wait_for_pid_exit(args.wait_for_pid_exit, args.poll_s)
100
+
101
+ export_cmd = [
102
+ args.python,
103
+ "/workspace/kinova_scene_sim/export_pi_actions.py",
104
+ "--checkpoint-dir",
105
+ str(checkpoint_dir),
106
+ "--session-root",
107
+ args.session_root,
108
+ "--sync-row-index",
109
+ str(args.sync_row_index),
110
+ "--prompt",
111
+ args.prompt,
112
+ "--output-json",
113
+ args.output_json,
114
+ ]
115
+ export_env = os.environ.copy()
116
+ export_env["JAX_PLATFORMS"] = args.jax_platforms
117
+ subprocess.run(export_cmd, check=True, env=export_env)
118
+
119
+ render_cmd = [
120
+ sys.executable,
121
+ "/workspace/kinova_scene_sim/render_pose_sequence.py",
122
+ "--session-root",
123
+ args.session_root,
124
+ "--poses-json",
125
+ args.output_json,
126
+ "--output",
127
+ args.output_gif,
128
+ "--fps",
129
+ str(args.fps),
130
+ ]
131
+ subprocess.run(render_cmd, check=True)
132
+ print(f"saved preview gif to {args.output_gif}")
133
+
134
+
135
+ if __name__ == "__main__":
136
+ main()
bundle/sim/run_policy_rollout_preview.py ADDED
@@ -0,0 +1,120 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import argparse
4
+ import os
5
+ import shutil
6
+ import subprocess
7
+ import sys
8
+ import time
9
+ from pathlib import Path
10
+
11
+
12
+ def checkpoint_ready(checkpoint_dir: Path) -> bool:
13
+ return (checkpoint_dir / "_CHECKPOINT_METADATA").is_file() and (checkpoint_dir / "params" / "_METADATA").is_file()
14
+
15
+
16
+ def wait_for_checkpoint(checkpoint_dir: Path, poll_s: float) -> None:
17
+ while not checkpoint_ready(checkpoint_dir):
18
+ print(f"waiting for checkpoint: {checkpoint_dir}", flush=True)
19
+ time.sleep(poll_s)
20
+
21
+
22
+ def pid_running(pid: int) -> bool:
23
+ return Path(f"/proc/{pid}").exists()
24
+
25
+
26
+ def wait_for_pid_exit(pid: int, poll_s: float) -> None:
27
+ while pid_running(pid):
28
+ print(f"waiting for pid to exit: {pid}", flush=True)
29
+ time.sleep(poll_s)
30
+
31
+
32
+ def stage_checkpoint(checkpoint_dir: Path, stage_root: Path) -> Path:
33
+ stage_root.mkdir(parents=True, exist_ok=True)
34
+ staged_dir = stage_root / checkpoint_dir.name
35
+ if staged_dir.exists():
36
+ shutil.rmtree(staged_dir)
37
+ subprocess.run(["cp", "-al", str(checkpoint_dir), str(stage_root)], check=True)
38
+ return staged_dir
39
+
40
+
41
+ def main() -> None:
42
+ parser = argparse.ArgumentParser()
43
+ parser.add_argument("--checkpoint-dir", default=None)
44
+ parser.add_argument(
45
+ "--checkpoint-root",
46
+ default="/workspace/openpi/checkpoints/pi05_kinova_teddybear/teddybear_kinova_ft_v4_b24_w12_fork",
47
+ )
48
+ parser.add_argument("--step", type=int, default=None)
49
+ parser.add_argument("--wait", action="store_true")
50
+ parser.add_argument("--poll-s", type=float, default=15.0)
51
+ parser.add_argument("--wait-for-pid-exit", type=int, default=None)
52
+ parser.add_argument("--stage-root", default=None)
53
+ parser.add_argument("--session-root", default="/workspace/data/teddybear_raw/session_20260327_165944_bear")
54
+ parser.add_argument("--sync-row-index", type=int, default=0)
55
+ parser.add_argument("--prompt", default="pick up the teddy bear and place it in the red box")
56
+ parser.add_argument("--rollout-steps", type=int, default=24)
57
+ parser.add_argument("--python", default="/workspace/openpi/.venv/bin/python")
58
+ parser.add_argument("--jax-platforms", default="cpu")
59
+ parser.add_argument("--output-json", default="/workspace/kinova_scene_sim/outputs/pi_rollout_preview.json")
60
+ parser.add_argument("--output-gif", default="/workspace/kinova_scene_sim/outputs/pi_rollout_preview.gif")
61
+ parser.add_argument("--fps", type=int, default=4)
62
+ args = parser.parse_args()
63
+
64
+ if args.checkpoint_dir is None:
65
+ if args.step is None:
66
+ raise ValueError("provide either --checkpoint-dir or --step")
67
+ checkpoint_dir = Path(args.checkpoint_root) / str(args.step)
68
+ else:
69
+ checkpoint_dir = Path(args.checkpoint_dir)
70
+
71
+ if args.wait:
72
+ wait_for_checkpoint(checkpoint_dir, args.poll_s)
73
+ elif not checkpoint_ready(checkpoint_dir):
74
+ raise FileNotFoundError(f"checkpoint not ready: {checkpoint_dir}")
75
+
76
+ if args.stage_root is not None:
77
+ checkpoint_dir = stage_checkpoint(checkpoint_dir, Path(args.stage_root))
78
+ print(f"staged checkpoint to {checkpoint_dir}", flush=True)
79
+
80
+ if args.wait_for_pid_exit is not None:
81
+ wait_for_pid_exit(args.wait_for_pid_exit, args.poll_s)
82
+
83
+ rollout_cmd = [
84
+ args.python,
85
+ "/workspace/kinova_scene_sim/rollout_pi_policy.py",
86
+ "--checkpoint-dir",
87
+ str(checkpoint_dir),
88
+ "--session-root",
89
+ args.session_root,
90
+ "--sync-row-index",
91
+ str(args.sync_row_index),
92
+ "--prompt",
93
+ args.prompt,
94
+ "--rollout-steps",
95
+ str(args.rollout_steps),
96
+ "--output-json",
97
+ args.output_json,
98
+ ]
99
+ rollout_env = os.environ.copy()
100
+ rollout_env["JAX_PLATFORMS"] = args.jax_platforms
101
+ subprocess.run(rollout_cmd, check=True, env=rollout_env)
102
+
103
+ render_cmd = [
104
+ sys.executable,
105
+ "/workspace/kinova_scene_sim/render_pose_sequence.py",
106
+ "--session-root",
107
+ args.session_root,
108
+ "--poses-json",
109
+ args.output_json,
110
+ "--output",
111
+ args.output_gif,
112
+ "--fps",
113
+ str(args.fps),
114
+ ]
115
+ subprocess.run(render_cmd, check=True)
116
+ print(f"saved rollout preview gif to {args.output_gif}", flush=True)
117
+
118
+
119
+ if __name__ == "__main__":
120
+ main()
bundle/sim/scene_tools.py ADDED
@@ -0,0 +1,392 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ from __future__ import annotations
2
+
3
+ import json
4
+ from dataclasses import dataclass
5
+ from pathlib import Path
6
+ from typing import Any
7
+
8
+ import cv2
9
+ import numpy as np
10
+ import pandas as pd
11
+ from PIL import Image
12
+
13
+
14
+ # Manually fitted table corners for the synced overhead frame used for episode 0.
15
+ # Order: top-left, top-right, bottom-right, bottom-left.
16
+ TABLE_CORNERS_PX = np.array(
17
+ [
18
+ [192.0, 138.0],
19
+ [1635.0, 46.0],
20
+ [1712.0, 787.0],
21
+ [185.0, 858.0],
22
+ ],
23
+ dtype=np.float64,
24
+ )
25
+
26
+ # Assumed tabletop size for the large brown work surface in the overhead image.
27
+ TABLE_SIZE_M = (1.52, 0.76)
28
+
29
+ # Tuned against the pre-grasp motion silhouette.
30
+ CAMERA_FOCAL_PX = 650.0
31
+ ROBOT_BASE_WORLD = np.array([0.50, 0.45, -0.45], dtype=np.float64)
32
+ ROBOT_BASE_YAW_RAD = -2.0
33
+
34
+ # Kinova tool-center offset relative to the interface frame from FK.
35
+ TOOL_OFFSET_M = 0.12
36
+
37
+
38
+ @dataclass(frozen=True)
39
+ class SceneCalibration:
40
+ session_root: Path
41
+ sync_row_index: int
42
+ azure_rgb_seq: int
43
+ azure_depth_seq: int
44
+ robot_seq: int
45
+ rgb_path: Path
46
+ depth_path: Path
47
+ rgb: np.ndarray
48
+ depth: np.ndarray
49
+ sync_row: dict[str, Any]
50
+ camera_matrix: np.ndarray
51
+ rvec: np.ndarray
52
+ tvec: np.ndarray
53
+ table_corners_px: np.ndarray
54
+ table_size_m: tuple[float, float]
55
+ robot_base_world: np.ndarray
56
+ robot_base_yaw_rad: float
57
+ box_mask: np.ndarray
58
+ teddy_mask: np.ndarray
59
+ box_world_polygon: np.ndarray
60
+ teddy_world_center: np.ndarray
61
+ teddy_world_extent: np.ndarray
62
+ table_depth_mm: float
63
+ box_height_m: float
64
+ teddy_height_m: float
65
+
66
+
67
+ def _to_rgb(path: Path) -> np.ndarray:
68
+ return np.array(Image.open(path).convert("RGB"))
69
+
70
+
71
+ def _to_depth(path: Path) -> np.ndarray:
72
+ return np.array(Image.open(path))
73
+
74
+
75
+ def load_sync_dataframe(session_root: Path) -> pd.DataFrame:
76
+ return pd.read_csv(session_root / "sync_index.csv")
77
+
78
+
79
+ def load_scene_calibration(session_root: str | Path, sync_row_index: int = 0) -> SceneCalibration:
80
+ session_root = Path(session_root)
81
+ sync = load_sync_dataframe(session_root)
82
+ row = sync.iloc[sync_row_index]
83
+
84
+ azure_rgb_seq = int(row["azure_rgb_seq"])
85
+ azure_depth_seq = int(row["azure_depth_seq"])
86
+ robot_seq = int(row["robot_seq"])
87
+
88
+ rgb_path = session_root / row["azure_rgb_file"]
89
+ depth_path = session_root / row["azure_depth_file"]
90
+ rgb = _to_rgb(rgb_path)
91
+ depth = _to_depth(depth_path)
92
+
93
+ camera_matrix, rvec, tvec = solve_table_camera(TABLE_CORNERS_PX, TABLE_SIZE_M, CAMERA_FOCAL_PX)
94
+ box_mask = detect_red_box(rgb)
95
+ teddy_mask = detect_teddy(rgb)
96
+ box_world_polygon = image_mask_to_world_polygon(box_mask, camera_matrix, rvec, tvec)
97
+ teddy_world_center, teddy_world_extent = mask_centroid_and_extent_world(teddy_mask, camera_matrix, rvec, tvec)
98
+
99
+ table_depth_mm = estimate_table_depth_mm(depth)
100
+ box_height_m = estimate_height_from_depth(rgb, depth, box_mask, table_depth_mm)
101
+ teddy_height_m = estimate_height_from_depth(rgb, depth, teddy_mask, table_depth_mm)
102
+
103
+ return SceneCalibration(
104
+ session_root=session_root,
105
+ sync_row_index=sync_row_index,
106
+ azure_rgb_seq=azure_rgb_seq,
107
+ azure_depth_seq=azure_depth_seq,
108
+ robot_seq=robot_seq,
109
+ rgb_path=rgb_path,
110
+ depth_path=depth_path,
111
+ rgb=rgb,
112
+ depth=depth,
113
+ sync_row=row.to_dict(),
114
+ camera_matrix=camera_matrix,
115
+ rvec=rvec,
116
+ tvec=tvec,
117
+ table_corners_px=TABLE_CORNERS_PX.copy(),
118
+ table_size_m=TABLE_SIZE_M,
119
+ robot_base_world=ROBOT_BASE_WORLD.copy(),
120
+ robot_base_yaw_rad=float(ROBOT_BASE_YAW_RAD),
121
+ box_mask=box_mask,
122
+ teddy_mask=teddy_mask,
123
+ box_world_polygon=box_world_polygon,
124
+ teddy_world_center=teddy_world_center,
125
+ teddy_world_extent=teddy_world_extent,
126
+ table_depth_mm=table_depth_mm,
127
+ box_height_m=box_height_m,
128
+ teddy_height_m=teddy_height_m,
129
+ )
130
+
131
+
132
+ def solve_table_camera(
133
+ table_corners_px: np.ndarray, table_size_m: tuple[float, float], focal_px: float
134
+ ) -> tuple[np.ndarray, np.ndarray, np.ndarray]:
135
+ width_m, height_m = table_size_m
136
+ object_points = np.array(
137
+ [
138
+ [-width_m / 2, -height_m / 2, 0.0],
139
+ [width_m / 2, -height_m / 2, 0.0],
140
+ [width_m / 2, height_m / 2, 0.0],
141
+ [-width_m / 2, height_m / 2, 0.0],
142
+ ],
143
+ dtype=np.float64,
144
+ )
145
+ camera_matrix = np.array(
146
+ [[focal_px, 0.0, 960.0], [0.0, focal_px, 540.0], [0.0, 0.0, 1.0]],
147
+ dtype=np.float64,
148
+ )
149
+ ok, rvec, tvec = cv2.solvePnP(object_points, table_corners_px, camera_matrix, None, flags=cv2.SOLVEPNP_IPPE)
150
+ if not ok:
151
+ raise RuntimeError("solvePnP failed for table camera fit")
152
+ return camera_matrix, rvec, tvec
153
+
154
+
155
+ def detect_red_box(rgb: np.ndarray) -> np.ndarray:
156
+ hsv = cv2.cvtColor(rgb, cv2.COLOR_RGB2HSV)
157
+ h, s, v = hsv[..., 0], hsv[..., 1], hsv[..., 2]
158
+ mask = (((h < 12) | (h > 170)) & (s > 60) & (v > 80)).astype(np.uint8)
159
+ num, labels, stats, centers = cv2.connectedComponentsWithStats(mask, connectivity=8)
160
+ best = None
161
+ best_area = -1
162
+ for i in range(1, num):
163
+ x, y, w, h_box, area = stats[i]
164
+ cx, cy = centers[i]
165
+ if area > 50_000 and x > 900 and y < 700 and area > best_area:
166
+ best_area = int(area)
167
+ best = labels == i
168
+ if best is None:
169
+ raise RuntimeError("failed to detect red box component")
170
+ return best
171
+
172
+
173
+ def detect_teddy(rgb: np.ndarray) -> np.ndarray:
174
+ hsv = cv2.cvtColor(rgb, cv2.COLOR_RGB2HSV)
175
+ h, s, v = hsv[..., 0], hsv[..., 1], hsv[..., 2]
176
+ mask = ((h > 5) & (h < 22) & (s > 15) & (s < 120) & (v > 110) & (v < 245)).astype(np.uint8)
177
+ num, labels, stats, centers = cv2.connectedComponentsWithStats(mask, connectivity=8)
178
+ best = None
179
+ best_area = -1
180
+ for i in range(1, num):
181
+ x, y, w, h_box, area = stats[i]
182
+ cx, cy = centers[i]
183
+ if 5_000 < area < 50_000 and 850 < cx < 1250 and 350 < cy < 700 and area > best_area:
184
+ best_area = int(area)
185
+ best = labels == i
186
+ if best is None:
187
+ raise RuntimeError("failed to detect teddy component")
188
+ return best
189
+
190
+
191
+ def estimate_table_depth_mm(depth: np.ndarray) -> float:
192
+ center_region = depth[150:430, 120:520]
193
+ valid = center_region[center_region > 0]
194
+ if len(valid) == 0:
195
+ raise RuntimeError("no valid table depth values")
196
+ return float(np.percentile(valid, 50))
197
+
198
+
199
+ def estimate_height_from_depth(rgb: np.ndarray, depth: np.ndarray, rgb_mask: np.ndarray, table_depth_mm: float) -> float:
200
+ ys, xs = np.where(rgb_mask)
201
+ if len(xs) == 0:
202
+ return 0.0
203
+ xd = np.clip((xs * depth.shape[1] / rgb.shape[1]).astype(int), 0, depth.shape[1] - 1)
204
+ yd = np.clip((ys * depth.shape[0] / rgb.shape[0]).astype(int), 0, depth.shape[0] - 1)
205
+ values = depth[yd, xd]
206
+ values = values[values > 0]
207
+ if len(values) == 0:
208
+ return 0.0
209
+ # Use a low percentile to reduce the effect of table pixels around the object.
210
+ object_depth_mm = float(np.percentile(values, 10))
211
+ return max(0.0, (table_depth_mm - object_depth_mm) / 1000.0)
212
+
213
+
214
+ def image_mask_to_world_polygon(mask: np.ndarray, camera_matrix: np.ndarray, rvec: np.ndarray, tvec: np.ndarray) -> np.ndarray:
215
+ points = np.column_stack(np.where(mask > 0))[:, ::-1].astype(np.float64)
216
+ rect = cv2.minAreaRect(points.astype(np.float32))
217
+ corners = cv2.boxPoints(rect).astype(np.float64)
218
+ return pixels_to_world_on_table(corners, camera_matrix, rvec, tvec)
219
+
220
+
221
+ def mask_centroid_and_extent_world(
222
+ mask: np.ndarray, camera_matrix: np.ndarray, rvec: np.ndarray, tvec: np.ndarray
223
+ ) -> tuple[np.ndarray, np.ndarray]:
224
+ points = np.column_stack(np.where(mask > 0))[:, ::-1].astype(np.float64)
225
+ world_points = pixels_to_world_on_table(points, camera_matrix, rvec, tvec)
226
+ center = world_points.mean(axis=0)
227
+ extent = world_points.max(axis=0) - world_points.min(axis=0)
228
+ return center, extent
229
+
230
+
231
+ def pixels_to_world_on_table(
232
+ pixels_uv: np.ndarray, camera_matrix: np.ndarray, rvec: np.ndarray, tvec: np.ndarray
233
+ ) -> np.ndarray:
234
+ rotation, _ = cv2.Rodrigues(rvec)
235
+ camera_position = (-rotation.T @ tvec).reshape(3)
236
+ inv_camera = np.linalg.inv(camera_matrix)
237
+ world_points = []
238
+ for u, v in pixels_uv:
239
+ ray_cam = inv_camera @ np.array([u, v, 1.0], dtype=np.float64)
240
+ ray_cam /= np.linalg.norm(ray_cam)
241
+ ray_world = rotation.T @ ray_cam
242
+ if abs(ray_world[2]) < 1e-8:
243
+ continue
244
+ scale = -camera_position[2] / ray_world[2]
245
+ world_points.append(camera_position + scale * ray_world)
246
+ if not world_points:
247
+ raise RuntimeError("failed to back-project pixels to the table plane")
248
+ return np.stack(world_points, axis=0)
249
+
250
+
251
+ def create_background_inpaint(rgb: np.ndarray) -> np.ndarray:
252
+ mask = np.zeros(rgb.shape[:2], dtype=np.uint8)
253
+ polygon = np.array(
254
+ [[1080, 520], [1919, 520], [1919, 1079], [980, 1079], [980, 850], [1080, 760]],
255
+ dtype=np.int32,
256
+ )
257
+ cv2.fillPoly(mask, [polygon], 255)
258
+ cv2.rectangle(mask, (1120, 300), (1450, 680), 0, -1)
259
+ cv2.rectangle(mask, (860, 350), (1180, 700), 0, -1)
260
+ return cv2.cvtColor(cv2.inpaint(cv2.cvtColor(rgb, cv2.COLOR_RGB2BGR), mask, 7, cv2.INPAINT_TELEA), cv2.COLOR_BGR2RGB)
261
+
262
+
263
+ def kinova_fk_points_world(q_deg: np.ndarray, base_world: np.ndarray, base_yaw_rad: float) -> np.ndarray:
264
+ points, _ = kinova_fk_points_and_tool_pose(q_deg)
265
+ cy, sy = np.cos(base_yaw_rad), np.sin(base_yaw_rad)
266
+ base_rotation = np.array([[cy, -sy, 0.0], [sy, cy, 0.0], [0.0, 0.0, 1.0]], dtype=np.float64)
267
+ return points @ base_rotation.T + base_world.reshape(1, 3)
268
+
269
+
270
+ def kinova_fk_points_and_tool_pose(q_deg: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
271
+ q = np.deg2rad(np.asarray(q_deg, dtype=np.float64))
272
+ params = [
273
+ (np.pi, 0.0, 0.0, 0.0),
274
+ (np.pi / 2, 0.0, -(0.1564 + 0.1284), q[0]),
275
+ (np.pi / 2, 0.0, -(0.0054 + 0.0064), q[1] + np.pi),
276
+ (np.pi / 2, 0.0, -(0.2104 + 0.2104), q[2] + np.pi),
277
+ (np.pi / 2, 0.0, -(0.0064 + 0.0064), q[3] + np.pi),
278
+ (np.pi / 2, 0.0, -(0.2084 + 0.1059), q[4] + np.pi),
279
+ (np.pi / 2, 0.0, 0.0, q[5] + np.pi),
280
+ (np.pi, 0.0, -(0.1059 + 0.0615), q[6] + np.pi),
281
+ ]
282
+
283
+ def dh(alpha: float, a: float, d: float, theta: float) -> np.ndarray:
284
+ ca, sa = np.cos(alpha), np.sin(alpha)
285
+ ct, st = np.cos(theta), np.sin(theta)
286
+ return np.array(
287
+ [
288
+ [ct, -st * ca, st * sa, a * ct],
289
+ [st, ct * ca, -ct * sa, a * st],
290
+ [0.0, sa, ca, d],
291
+ [0.0, 0.0, 0.0, 1.0],
292
+ ],
293
+ dtype=np.float64,
294
+ )
295
+
296
+ transform = np.eye(4, dtype=np.float64)
297
+ points = []
298
+ for alpha, a, d, theta in params:
299
+ transform = transform @ dh(alpha, a, d, theta)
300
+ points.append(transform[:3, 3].copy())
301
+
302
+ tool_transform = transform.copy()
303
+ tool_transform[:3, 3] = tool_transform[:3, 3] + tool_transform[:3, 2] * TOOL_OFFSET_M
304
+ points.append(tool_transform[:3, 3].copy())
305
+ return np.stack(points, axis=0), tool_transform
306
+
307
+
308
+ def project_world_points(points_world: np.ndarray, camera_matrix: np.ndarray, rvec: np.ndarray, tvec: np.ndarray) -> tuple[np.ndarray, np.ndarray]:
309
+ image_points, _ = cv2.projectPoints(points_world.astype(np.float64), rvec, tvec, camera_matrix, None)
310
+ rotation, _ = cv2.Rodrigues(rvec)
311
+ camera_points = (rotation @ points_world.T + tvec).T
312
+ return image_points[:, 0, :], camera_points[:, 2]
313
+
314
+
315
+ def draw_robot(
316
+ image: np.ndarray,
317
+ q_deg: np.ndarray,
318
+ camera_matrix: np.ndarray,
319
+ rvec: np.ndarray,
320
+ tvec: np.ndarray,
321
+ base_world: np.ndarray,
322
+ base_yaw_rad: float,
323
+ color: tuple[int, int, int] = (232, 242, 250),
324
+ alpha: float = 1.0,
325
+ ) -> np.ndarray:
326
+ canvas = image.copy()
327
+ points_world = kinova_fk_points_world(q_deg, base_world, base_yaw_rad)
328
+ uv, z = project_world_points(points_world, camera_matrix, rvec, tvec)
329
+
330
+ overlay = canvas.copy()
331
+ for p0, p1, depth_value in zip(uv[:-1], uv[1:], z[:-1]):
332
+ thickness = max(10, int(35 / max(depth_value, 0.25)))
333
+ cv2.line(overlay, tuple(np.round(p0).astype(int)), tuple(np.round(p1).astype(int)), color, thickness)
334
+ for point, depth_value in zip(uv, z):
335
+ radius = max(8, int(18 / max(depth_value, 0.25)))
336
+ cv2.circle(overlay, tuple(np.round(point).astype(int)), radius, color, -1)
337
+ if alpha >= 1.0:
338
+ return overlay
339
+ return cv2.addWeighted(overlay, alpha, canvas, 1.0 - alpha, 0.0)
340
+
341
+
342
+ def render_scene(
343
+ calibration: SceneCalibration,
344
+ q_deg: np.ndarray,
345
+ background: np.ndarray | None = None,
346
+ color: tuple[int, int, int] = (232, 242, 250),
347
+ alpha: float = 1.0,
348
+ ) -> np.ndarray:
349
+ if background is None:
350
+ background = create_background_inpaint(calibration.rgb)
351
+ return draw_robot(
352
+ background,
353
+ q_deg,
354
+ calibration.camera_matrix,
355
+ calibration.rvec,
356
+ calibration.tvec,
357
+ calibration.robot_base_world,
358
+ calibration.robot_base_yaw_rad,
359
+ color=color,
360
+ alpha=alpha,
361
+ )
362
+
363
+
364
+ def scene_to_jsonable(calibration: SceneCalibration) -> dict[str, Any]:
365
+ return {
366
+ "session_root": str(calibration.session_root),
367
+ "sync_row_index": calibration.sync_row_index,
368
+ "azure_rgb_seq": calibration.azure_rgb_seq,
369
+ "azure_depth_seq": calibration.azure_depth_seq,
370
+ "robot_seq": calibration.robot_seq,
371
+ "rgb_path": str(calibration.rgb_path),
372
+ "depth_path": str(calibration.depth_path),
373
+ "table_corners_px": calibration.table_corners_px.tolist(),
374
+ "table_size_m": list(calibration.table_size_m),
375
+ "camera_focal_px": float(calibration.camera_matrix[0, 0]),
376
+ "rvec": calibration.rvec.reshape(-1).tolist(),
377
+ "tvec": calibration.tvec.reshape(-1).tolist(),
378
+ "robot_base_world": calibration.robot_base_world.tolist(),
379
+ "robot_base_yaw_rad": float(calibration.robot_base_yaw_rad),
380
+ "sync_row": calibration.sync_row,
381
+ "table_depth_mm": float(calibration.table_depth_mm),
382
+ "box_height_m": float(calibration.box_height_m),
383
+ "teddy_height_m": float(calibration.teddy_height_m),
384
+ "box_world_polygon": calibration.box_world_polygon.tolist(),
385
+ "teddy_world_center": calibration.teddy_world_center.tolist(),
386
+ "teddy_world_extent": calibration.teddy_world_extent.tolist(),
387
+ }
388
+
389
+
390
+ def save_scene_json(calibration: SceneCalibration, path: str | Path) -> None:
391
+ path = Path(path)
392
+ path.write_text(json.dumps(scene_to_jsonable(calibration), indent=2))
bundle/train_teddybear_pi05.sh ADDED
@@ -0,0 +1,13 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ #!/usr/bin/env bash
2
+ set -euo pipefail
3
+
4
+ OPENPI_ROOT="${1:-$HOME/workspace/teddybear_openpi/openpi}"
5
+ cd "$OPENPI_ROOT"
6
+
7
+ export OPENPI_TORCH_DATALOADER_MP_CONTEXT=default
8
+
9
+ .venv/bin/python -u scripts/train.py \
10
+ pi05_kinova_teddybear \
11
+ --exp-name=teddybear_kinova_ft_v4_b24_w12_fork \
12
+ --batch-size 24 \
13
+ --num-workers 12