dexverse-cli 0.1.3__tar.gz → 0.1.3.post2__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {dexverse_cli-0.1.3 → dexverse_cli-0.1.3.post2}/.gitignore +12 -12
- {dexverse_cli-0.1.3 → dexverse_cli-0.1.3.post2}/.python-version +1 -1
- {dexverse_cli-0.1.3 → dexverse_cli-0.1.3.post2}/PKG-INFO +3 -1
- {dexverse_cli-0.1.3 → dexverse_cli-0.1.3.post2}/pyproject.toml +68 -68
- {dexverse_cli-0.1.3 → dexverse_cli-0.1.3.post2}/src/dexverse_cli/README.md +109 -107
- dexverse_cli-0.1.3.post2/src/dexverse_cli/__init__.py +1 -0
- {dexverse_cli-0.1.3 → dexverse_cli-0.1.3.post2}/src/dexverse_cli/alignment.py +45 -45
- {dexverse_cli-0.1.3 → dexverse_cli-0.1.3.post2}/src/dexverse_cli/cli.py +194 -187
- {dexverse_cli-0.1.3 → dexverse_cli-0.1.3.post2}/src/dexverse_cli/download.py +476 -458
- {dexverse_cli-0.1.3 → dexverse_cli-0.1.3.post2}/src/dexverse_cli/hdf5_schema.py +519 -519
- {dexverse_cli-0.1.3 → dexverse_cli-0.1.3.post2}/src/dexverse_cli/http.py +416 -416
- {dexverse_cli-0.1.3 → dexverse_cli-0.1.3.post2}/src/dexverse_cli/jetson_encoder.py +168 -168
- {dexverse_cli-0.1.3 → dexverse_cli-0.1.3.post2}/src/dexverse_cli/manifest.py +274 -271
- {dexverse_cli-0.1.3 → dexverse_cli-0.1.3.post2}/src/dexverse_cli/pack.py +167 -167
- {dexverse_cli-0.1.3 → dexverse_cli-0.1.3.post2}/src/dexverse_cli/raw_schema.py +418 -418
- {dexverse_cli-0.1.3 → dexverse_cli-0.1.3.post2}/src/dexverse_cli/state.py +141 -141
- {dexverse_cli-0.1.3 → dexverse_cli-0.1.3.post2}/src/dexverse_cli/transaction.py +126 -126
- {dexverse_cli-0.1.3 → dexverse_cli-0.1.3.post2}/src/dexverse_cli/unpack.py +185 -185
- {dexverse_cli-0.1.3 → dexverse_cli-0.1.3.post2}/src/dexverse_cli/unversioned_hdf5.py +321 -321
- {dexverse_cli-0.1.3 → dexverse_cli-0.1.3.post2}/uv.lock +1 -1
- dexverse_cli-0.1.3/src/dexverse_cli/__init__.py +0 -1
|
@@ -1,12 +1,12 @@
|
|
|
1
|
-
.venv/
|
|
2
|
-
.venv-smoke/
|
|
3
|
-
.venv-smoke-*/
|
|
4
|
-
.smoke-work/
|
|
5
|
-
.artifact-inspect/
|
|
6
|
-
.manifest/
|
|
7
|
-
.pytest_cache/
|
|
8
|
-
.mypy_cache/
|
|
9
|
-
.ruff_cache/
|
|
10
|
-
__pycache__/
|
|
11
|
-
*.py[cod]
|
|
12
|
-
dist/
|
|
1
|
+
.venv/
|
|
2
|
+
.venv-smoke/
|
|
3
|
+
.venv-smoke-*/
|
|
4
|
+
.smoke-work/
|
|
5
|
+
.artifact-inspect/
|
|
6
|
+
.manifest/
|
|
7
|
+
.pytest_cache/
|
|
8
|
+
.mypy_cache/
|
|
9
|
+
.ruff_cache/
|
|
10
|
+
__pycache__/
|
|
11
|
+
*.py[cod]
|
|
12
|
+
dist/
|
|
@@ -1 +1 @@
|
|
|
1
|
-
3.10
|
|
1
|
+
3.10
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.5
|
|
2
2
|
Name: dexverse-cli
|
|
3
|
-
Version: 0.1.3
|
|
3
|
+
Version: 0.1.3.post2
|
|
4
4
|
Summary: Download, pack, and unpack DexVerse datasets
|
|
5
5
|
Requires-Python: >=3.10
|
|
6
6
|
Requires-Dist: av<17,>=14
|
|
@@ -43,6 +43,8 @@ type manifest.json | dexverse-dl download --manifest - --out ./dataset
|
|
|
43
43
|
A manifest is either a JSON file list or an object containing `files`. Each
|
|
44
44
|
file requires `download_url` and `file_name`. Optional fields are
|
|
45
45
|
`storage_path`, `file_size`, `sha256`, `meta_data`, and `data_protocol`.
|
|
46
|
+
Unknown top-level keys next to `files` (for example the `query_conditions` /
|
|
47
|
+
`export_info` blocks written by the web batch export) are ignored.
|
|
46
48
|
`data_protocol` is retained in the downloaded metadata sidecar. Downloaded metadata is
|
|
47
49
|
stored in a versioned sidecar and becomes `task_instruction.json` when the
|
|
48
50
|
corresponding HDF5 file is unpacked; only top-level `data_protocol` is removed
|
|
@@ -1,68 +1,68 @@
|
|
|
1
|
-
[build-system]
|
|
2
|
-
requires = ["hatchling>=1.27"]
|
|
3
|
-
build-backend = "hatchling.build"
|
|
4
|
-
|
|
5
|
-
[project]
|
|
6
|
-
name = "dexverse-cli"
|
|
7
|
-
version = "0.1.3"
|
|
8
|
-
description = "Download, pack, and unpack DexVerse datasets"
|
|
9
|
-
readme = "src/dexverse_cli/README.md"
|
|
10
|
-
requires-python = ">=3.10"
|
|
11
|
-
dependencies = [
|
|
12
|
-
"av>=14,<17",
|
|
13
|
-
"h5py>=3.11,<4",
|
|
14
|
-
"httpx>=0.28,<1",
|
|
15
|
-
"numpy>=1.26,<3",
|
|
16
|
-
"pillow>=10,<13",
|
|
17
|
-
"rich>=13.9,<15",
|
|
18
|
-
"typer>=0.16,<1",
|
|
19
|
-
]
|
|
20
|
-
|
|
21
|
-
[project.optional-dependencies]
|
|
22
|
-
jetson = [
|
|
23
|
-
"PyGObject>=3.42,<4; platform_system == 'Linux'",
|
|
24
|
-
]
|
|
25
|
-
|
|
26
|
-
[project.scripts]
|
|
27
|
-
dexverse-dl = "dexverse_cli.cli:app"
|
|
28
|
-
|
|
29
|
-
[dependency-groups]
|
|
30
|
-
dev = [
|
|
31
|
-
"mypy>=1.15,<2",
|
|
32
|
-
"pytest>=8.3,<10",
|
|
33
|
-
"ruff>=0.11,<1",
|
|
34
|
-
]
|
|
35
|
-
|
|
36
|
-
[tool.hatch.build.targets.wheel]
|
|
37
|
-
packages = ["src/dexverse_cli"]
|
|
38
|
-
|
|
39
|
-
[tool.hatch.build.targets.sdist]
|
|
40
|
-
include = [
|
|
41
|
-
"/pyproject.toml",
|
|
42
|
-
"/uv.lock",
|
|
43
|
-
"/.python-version",
|
|
44
|
-
"/src/dexverse_cli",
|
|
45
|
-
]
|
|
46
|
-
|
|
47
|
-
[tool.pytest.ini_options]
|
|
48
|
-
addopts = "-ra"
|
|
49
|
-
testpaths = ["tests"]
|
|
50
|
-
|
|
51
|
-
[tool.ruff]
|
|
52
|
-
target-version = "py310"
|
|
53
|
-
line-length = 120
|
|
54
|
-
|
|
55
|
-
[tool.ruff.lint]
|
|
56
|
-
select = ["E", "F", "I", "UP", "B", "SIM", "RUF", "TID252"]
|
|
57
|
-
|
|
58
|
-
[tool.ruff.lint.flake8-tidy-imports]
|
|
59
|
-
ban-relative-imports = "all"
|
|
60
|
-
|
|
61
|
-
[tool.ruff.lint.per-file-ignores]
|
|
62
|
-
"tests/**/*.py" = ["TID252"]
|
|
63
|
-
|
|
64
|
-
[tool.mypy]
|
|
65
|
-
python_version = "3.10"
|
|
66
|
-
strict = true
|
|
67
|
-
warn_unreachable = true
|
|
68
|
-
ignore_missing_imports = true
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["hatchling>=1.27"]
|
|
3
|
+
build-backend = "hatchling.build"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "dexverse-cli"
|
|
7
|
+
version = "0.1.3.post2"
|
|
8
|
+
description = "Download, pack, and unpack DexVerse datasets"
|
|
9
|
+
readme = "src/dexverse_cli/README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
dependencies = [
|
|
12
|
+
"av>=14,<17",
|
|
13
|
+
"h5py>=3.11,<4",
|
|
14
|
+
"httpx>=0.28,<1",
|
|
15
|
+
"numpy>=1.26,<3",
|
|
16
|
+
"pillow>=10,<13",
|
|
17
|
+
"rich>=13.9,<15",
|
|
18
|
+
"typer>=0.16,<1",
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
[project.optional-dependencies]
|
|
22
|
+
jetson = [
|
|
23
|
+
"PyGObject>=3.42,<4; platform_system == 'Linux'",
|
|
24
|
+
]
|
|
25
|
+
|
|
26
|
+
[project.scripts]
|
|
27
|
+
dexverse-dl = "dexverse_cli.cli:app"
|
|
28
|
+
|
|
29
|
+
[dependency-groups]
|
|
30
|
+
dev = [
|
|
31
|
+
"mypy>=1.15,<2",
|
|
32
|
+
"pytest>=8.3,<10",
|
|
33
|
+
"ruff>=0.11,<1",
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
[tool.hatch.build.targets.wheel]
|
|
37
|
+
packages = ["src/dexverse_cli"]
|
|
38
|
+
|
|
39
|
+
[tool.hatch.build.targets.sdist]
|
|
40
|
+
include = [
|
|
41
|
+
"/pyproject.toml",
|
|
42
|
+
"/uv.lock",
|
|
43
|
+
"/.python-version",
|
|
44
|
+
"/src/dexverse_cli",
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
[tool.pytest.ini_options]
|
|
48
|
+
addopts = "-ra"
|
|
49
|
+
testpaths = ["tests"]
|
|
50
|
+
|
|
51
|
+
[tool.ruff]
|
|
52
|
+
target-version = "py310"
|
|
53
|
+
line-length = 120
|
|
54
|
+
|
|
55
|
+
[tool.ruff.lint]
|
|
56
|
+
select = ["E", "F", "I", "UP", "B", "SIM", "RUF", "TID252"]
|
|
57
|
+
|
|
58
|
+
[tool.ruff.lint.flake8-tidy-imports]
|
|
59
|
+
ban-relative-imports = "all"
|
|
60
|
+
|
|
61
|
+
[tool.ruff.lint.per-file-ignores]
|
|
62
|
+
"tests/**/*.py" = ["TID252"]
|
|
63
|
+
|
|
64
|
+
[tool.mypy]
|
|
65
|
+
python_version = "3.10"
|
|
66
|
+
strict = true
|
|
67
|
+
warn_unreachable = true
|
|
68
|
+
ignore_missing_imports = true
|
|
@@ -1,107 +1,109 @@
|
|
|
1
|
-
# dexverse-cli
|
|
2
|
-
|
|
3
|
-
`dexverse-cli` downloads DexVerse dataset manifests over HTTP(S), packs strict
|
|
4
|
-
raw sessions into versioned HDF5 files, and unpacks HDF5 sessions. It requires
|
|
5
|
-
Python 3.10 or newer.
|
|
6
|
-
|
|
7
|
-
## Install
|
|
8
|
-
|
|
9
|
-
```console
|
|
10
|
-
pip install dexverse-cli
|
|
11
|
-
```
|
|
12
|
-
|
|
13
|
-
## Download
|
|
14
|
-
|
|
15
|
-
Read a manifest from a file:
|
|
16
|
-
|
|
17
|
-
```console
|
|
18
|
-
dexverse-dl download --manifest manifest.json --out ./dataset
|
|
19
|
-
```
|
|
20
|
-
|
|
21
|
-
Or pipe a short-lived manifest directly to stdin:
|
|
22
|
-
|
|
23
|
-
```console
|
|
24
|
-
type manifest.json | dexverse-dl download --manifest - --out ./dataset
|
|
25
|
-
```
|
|
26
|
-
|
|
27
|
-
A manifest is either a JSON file list or an object containing `files`. Each
|
|
28
|
-
file requires `download_url` and `file_name`. Optional fields are
|
|
29
|
-
`storage_path`, `file_size`, `sha256`, `meta_data`, and `data_protocol`.
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
Pack
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
```
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
Unpack
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
```
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
```
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
Convert
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
```
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
```
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
1
|
+
# dexverse-cli
|
|
2
|
+
|
|
3
|
+
`dexverse-cli` downloads DexVerse dataset manifests over HTTP(S), packs strict
|
|
4
|
+
raw sessions into versioned HDF5 files, and unpacks HDF5 sessions. It requires
|
|
5
|
+
Python 3.10 or newer.
|
|
6
|
+
|
|
7
|
+
## Install
|
|
8
|
+
|
|
9
|
+
```console
|
|
10
|
+
pip install dexverse-cli
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
## Download
|
|
14
|
+
|
|
15
|
+
Read a manifest from a file:
|
|
16
|
+
|
|
17
|
+
```console
|
|
18
|
+
dexverse-dl download --manifest manifest.json --out ./dataset
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
Or pipe a short-lived manifest directly to stdin:
|
|
22
|
+
|
|
23
|
+
```console
|
|
24
|
+
type manifest.json | dexverse-dl download --manifest - --out ./dataset
|
|
25
|
+
```
|
|
26
|
+
|
|
27
|
+
A manifest is either a JSON file list or an object containing `files`. Each
|
|
28
|
+
file requires `download_url` and `file_name`. Optional fields are
|
|
29
|
+
`storage_path`, `file_size`, `sha256`, `meta_data`, and `data_protocol`.
|
|
30
|
+
Unknown top-level keys next to `files` (for example the `query_conditions` /
|
|
31
|
+
`export_info` blocks written by the web batch export) are ignored.
|
|
32
|
+
`data_protocol` is retained in the downloaded metadata sidecar. Downloaded metadata is
|
|
33
|
+
stored in a versioned sidecar and becomes `task_instruction.json` when the
|
|
34
|
+
corresponding HDF5 file is unpacked; only top-level `data_protocol` is removed
|
|
35
|
+
from that algorithm-facing projection.
|
|
36
|
+
|
|
37
|
+
Downloads use bounded parallelism, retries, and compatible partial-file resume.
|
|
38
|
+
Within a manifest, the first occurrence of a target path keeps its name; later
|
|
39
|
+
occurrences receive `-1`, `-2`, etc. before the final extension (for example,
|
|
40
|
+
`episode1.hdf5`, `episode1-1.hdf5`, `episode1-2.hdf5`). Numbering skips names and
|
|
41
|
+
paths already claimed by other entries, including partial files and metadata.
|
|
42
|
+
Different relative directories remain independent. Names are assigned in manifest
|
|
43
|
+
order, with Windows case-insensitive matching, before any downloads start.
|
|
44
|
+
Rerunning the same manifest preserves the assigned names for skipping and resume;
|
|
45
|
+
existing files on disk do not trigger new suffixes. This is not cross-batch name
|
|
46
|
+
allocation: changing the manifest entries or their order can change the mapping.
|
|
47
|
+
When `sha256` is present it is always checked before the final file is replaced.
|
|
48
|
+
TLS certificate verification is disabled by default for internal endpoints;
|
|
49
|
+
pass `--secure` to enable certificate verification.
|
|
50
|
+
|
|
51
|
+
## Pack
|
|
52
|
+
|
|
53
|
+
Pack one raw session, or the immediate session directories under a parent:
|
|
54
|
+
|
|
55
|
+
```console
|
|
56
|
+
dexverse-dl pack --input ./raw/session --output ./packed --format jpeg
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
JPEG is the platform-independent default. Packing validates the complete raw
|
|
60
|
+
inventory, every image, all camera stream relationships, and pose data before
|
|
61
|
+
transactionally replacing an output. Camera and pose counts may differ; pose is
|
|
62
|
+
linearly aligned to the deterministic reference camera timeline.
|
|
63
|
+
|
|
64
|
+
Jetson MP4 packing is optional:
|
|
65
|
+
|
|
66
|
+
```console
|
|
67
|
+
pip install "dexverse-cli[jetson]"
|
|
68
|
+
dexverse-dl pack --input ./raw/session --output ./packed --format video
|
|
69
|
+
```
|
|
70
|
+
|
|
71
|
+
The Python extra does not install native Jetson GStreamer components. Video
|
|
72
|
+
packing reports an explicit error unless the required hardware pipeline is
|
|
73
|
+
available. JPEG packing, download, help, and unpack do not import GStreamer.
|
|
74
|
+
|
|
75
|
+
## Unpack
|
|
76
|
+
|
|
77
|
+
Unpack one HDF5 file:
|
|
78
|
+
|
|
79
|
+
```console
|
|
80
|
+
dexverse-dl unpack --input ./packed/session.hdf5 --output ./restored
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Or recursively unpack `*.hdf5` files while preserving their relative paths:
|
|
84
|
+
|
|
85
|
+
```console
|
|
86
|
+
dexverse-dl unpack --input-dir ./packed --output ./restored
|
|
87
|
+
```
|
|
88
|
+
|
|
89
|
+
Unpacking validates the complete versioned schema before transactionally
|
|
90
|
+
publishing a restored session. It also retains the supported unversioned HDF5
|
|
91
|
+
read path.
|
|
92
|
+
|
|
93
|
+
## Convert
|
|
94
|
+
|
|
95
|
+
Convert one supported HDF5 file:
|
|
96
|
+
|
|
97
|
+
```console
|
|
98
|
+
dexverse-dl convert --input ./dataset/session.hdf5 --output ./restored
|
|
99
|
+
```
|
|
100
|
+
|
|
101
|
+
Or recursively convert `*.hdf5` files while preserving their relative paths:
|
|
102
|
+
|
|
103
|
+
```console
|
|
104
|
+
dexverse-dl convert --input-dir ./dataset --output ./restored
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
`convert` is the compatibility alias for `unpack`; it retains the same options,
|
|
108
|
+
target mapping, legacy HDF5 support, exit codes, and `converted=...` summary.
|
|
109
|
+
Batches continue after an item failure but exit with status 1 if any item fails.
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
__version__ = "0.1.3.post2"
|
|
@@ -1,45 +1,45 @@
|
|
|
1
|
-
from __future__ import annotations
|
|
2
|
-
|
|
3
|
-
from dataclasses import dataclass
|
|
4
|
-
|
|
5
|
-
import numpy as np
|
|
6
|
-
import numpy.typing as npt
|
|
7
|
-
|
|
8
|
-
from dexverse_cli.raw_schema import RawSessionV1
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
@dataclass(frozen=True, slots=True)
|
|
12
|
-
class AlignedPoseV1:
|
|
13
|
-
data: npt.NDArray[np.float32]
|
|
14
|
-
timestamps: npt.NDArray[np.uint64]
|
|
15
|
-
columns: tuple[str, ...]
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
class PackAlignmentPolicyV1:
|
|
19
|
-
"""Linearly align pose values to the deterministic reference camera timeline."""
|
|
20
|
-
|
|
21
|
-
name = "linear_pose_to_reference_camera_v1"
|
|
22
|
-
|
|
23
|
-
def align(self, session: RawSessionV1) -> AlignedPoseV1:
|
|
24
|
-
target = np.asarray(
|
|
25
|
-
[record.timestamp for record in session.records_by_camera[session.reference_camera]],
|
|
26
|
-
dtype=np.float64,
|
|
27
|
-
)
|
|
28
|
-
timestamps = np.asarray(
|
|
29
|
-
[record.timestamp_ns for record in session.records_by_camera[session.reference_camera]],
|
|
30
|
-
dtype=np.uint64,
|
|
31
|
-
)
|
|
32
|
-
columns = session.pose_columns
|
|
33
|
-
result = np.empty((target.size, len(columns)), dtype=np.float32)
|
|
34
|
-
source_times = np.asarray([frame.timestamp for frame in session.pose_frames], dtype=np.float64)
|
|
35
|
-
for column_index, column in enumerate(columns):
|
|
36
|
-
values = np.asarray(
|
|
37
|
-
[frame.data[column] for frame in session.pose_frames],
|
|
38
|
-
dtype=np.float64,
|
|
39
|
-
)
|
|
40
|
-
if values.size == 1:
|
|
41
|
-
aligned = np.full(target.shape, values[0], dtype=np.float64)
|
|
42
|
-
else:
|
|
43
|
-
aligned = np.interp(target, source_times, values)
|
|
44
|
-
result[:, column_index] = aligned.astype(np.float32)
|
|
45
|
-
return AlignedPoseV1(result, timestamps, columns)
|
|
1
|
+
from __future__ import annotations
|
|
2
|
+
|
|
3
|
+
from dataclasses import dataclass
|
|
4
|
+
|
|
5
|
+
import numpy as np
|
|
6
|
+
import numpy.typing as npt
|
|
7
|
+
|
|
8
|
+
from dexverse_cli.raw_schema import RawSessionV1
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
@dataclass(frozen=True, slots=True)
|
|
12
|
+
class AlignedPoseV1:
|
|
13
|
+
data: npt.NDArray[np.float32]
|
|
14
|
+
timestamps: npt.NDArray[np.uint64]
|
|
15
|
+
columns: tuple[str, ...]
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class PackAlignmentPolicyV1:
|
|
19
|
+
"""Linearly align pose values to the deterministic reference camera timeline."""
|
|
20
|
+
|
|
21
|
+
name = "linear_pose_to_reference_camera_v1"
|
|
22
|
+
|
|
23
|
+
def align(self, session: RawSessionV1) -> AlignedPoseV1:
|
|
24
|
+
target = np.asarray(
|
|
25
|
+
[record.timestamp for record in session.records_by_camera[session.reference_camera]],
|
|
26
|
+
dtype=np.float64,
|
|
27
|
+
)
|
|
28
|
+
timestamps = np.asarray(
|
|
29
|
+
[record.timestamp_ns for record in session.records_by_camera[session.reference_camera]],
|
|
30
|
+
dtype=np.uint64,
|
|
31
|
+
)
|
|
32
|
+
columns = session.pose_columns
|
|
33
|
+
result = np.empty((target.size, len(columns)), dtype=np.float32)
|
|
34
|
+
source_times = np.asarray([frame.timestamp for frame in session.pose_frames], dtype=np.float64)
|
|
35
|
+
for column_index, column in enumerate(columns):
|
|
36
|
+
values = np.asarray(
|
|
37
|
+
[frame.data[column] for frame in session.pose_frames],
|
|
38
|
+
dtype=np.float64,
|
|
39
|
+
)
|
|
40
|
+
if values.size == 1:
|
|
41
|
+
aligned = np.full(target.shape, values[0], dtype=np.float64)
|
|
42
|
+
else:
|
|
43
|
+
aligned = np.interp(target, source_times, values)
|
|
44
|
+
result[:, column_index] = aligned.astype(np.float32)
|
|
45
|
+
return AlignedPoseV1(result, timestamps, columns)
|