reality 0.1.0__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.
- reality-0.1.0/.github/workflows/ci.yml +78 -0
- reality-0.1.0/.gitignore +11 -0
- reality-0.1.0/API_DESIGN.md +169 -0
- reality-0.1.0/ARCHITECTURE.md +118 -0
- reality-0.1.0/CHANGELOG.md +17 -0
- reality-0.1.0/CONTRIBUTING.md +24 -0
- reality-0.1.0/FUTURES_AUDIT.md +56 -0
- reality-0.1.0/FUTURES_RESULTS.json +92 -0
- reality-0.1.0/LICENSE +173 -0
- reality-0.1.0/PKG-INFO +245 -0
- reality-0.1.0/PROJECT.md +63 -0
- reality-0.1.0/README.md +210 -0
- reality-0.1.0/REALITY_AUDIT.md +497 -0
- reality-0.1.0/REALITY_GPU_AUDIT.md +225 -0
- reality-0.1.0/REALITY_GPU_RESULTS.json +137 -0
- reality-0.1.0/RELEASE_AUDIT.md +66 -0
- reality-0.1.0/RELEASE_RESULTS.json +173 -0
- reality-0.1.0/ROADMAP.md +75 -0
- reality-0.1.0/benchmarks/articulation.py +25 -0
- reality-0.1.0/benchmarks/batch_branches.py +37 -0
- reality-0.1.0/benchmarks/branching_1000_objects.py +73 -0
- reality-0.1.0/benchmarks/explore_scaling.py +69 -0
- reality-0.1.0/benchmarks/futures_scaling.py +57 -0
- reality-0.1.0/benchmarks/gpu_branch_scaling.py +97 -0
- reality-0.1.0/benchmarks/graph_200_objects.py +38 -0
- reality-0.1.0/benchmarks/navigation_scaling.py +76 -0
- reality-0.1.0/benchmarks/physics_cpu.py +58 -0
- reality-0.1.0/examples/articulation.py +31 -0
- reality-0.1.0/examples/batch_branches.py +21 -0
- reality-0.1.0/examples/game_level_clearance.py +38 -0
- reality-0.1.0/examples/mechanism_feasibility.py +25 -0
- reality-0.1.0/examples/navigation.py +21 -0
- reality-0.1.0/examples/navigation_branch.py +29 -0
- reality-0.1.0/examples/parallel_futures.py +53 -0
- reality-0.1.0/examples/physics.py +24 -0
- reality-0.1.0/examples/query_room.py +9 -0
- reality-0.1.0/examples/relationships.py +8 -0
- reality-0.1.0/examples/robot_planning.py +38 -0
- reality-0.1.0/examples/room_layout_optimization.py +33 -0
- reality-0.1.0/examples/visibility.py +11 -0
- reality-0.1.0/notebooks/reality_gpu_validation.ipynb +249 -0
- reality-0.1.0/pyproject.toml +71 -0
- reality-0.1.0/src/reality/__init__.py +128 -0
- reality-0.1.0/src/reality/__main__.py +12 -0
- reality-0.1.0/src/reality/_accelerators.py +63 -0
- reality-0.1.0/src/reality/_articulation.py +274 -0
- reality-0.1.0/src/reality/_batch.py +598 -0
- reality-0.1.0/src/reality/_branch.py +661 -0
- reality-0.1.0/src/reality/_explore.py +227 -0
- reality-0.1.0/src/reality/_graph.py +383 -0
- reality-0.1.0/src/reality/_loaders.py +190 -0
- reality-0.1.0/src/reality/_metadata.py +264 -0
- reality-0.1.0/src/reality/_models.py +303 -0
- reality-0.1.0/src/reality/_navigation.py +594 -0
- reality-0.1.0/src/reality/_physics.py +114 -0
- reality-0.1.0/src/reality/_state.py +215 -0
- reality-0.1.0/src/reality/_warp_ops.py +574 -0
- reality-0.1.0/src/reality/_world.py +945 -0
- reality-0.1.0/src/reality/backends/__init__.py +5 -0
- reality-0.1.0/src/reality/backends/base.py +37 -0
- reality-0.1.0/src/reality/backends/mujoco.py +324 -0
- reality-0.1.0/src/reality/experimental/__init__.py +8 -0
- reality-0.1.0/src/reality/experimental/predictor.py +60 -0
- reality-0.1.0/src/reality/predicates.py +103 -0
- reality-0.1.0/src/reality/py.typed +1 -0
- reality-0.1.0/tests/conftest.py +20 -0
- reality-0.1.0/tests/test_articulation.py +123 -0
- reality-0.1.0/tests/test_batch.py +55 -0
- reality-0.1.0/tests/test_branching.py +195 -0
- reality-0.1.0/tests/test_cli.py +10 -0
- reality-0.1.0/tests/test_explore.py +94 -0
- reality-0.1.0/tests/test_futures.py +102 -0
- reality-0.1.0/tests/test_gpu.py +94 -0
- reality-0.1.0/tests/test_graph.py +109 -0
- reality-0.1.0/tests/test_loaders.py +115 -0
- reality-0.1.0/tests/test_models.py +57 -0
- reality-0.1.0/tests/test_navigation.py +189 -0
- reality-0.1.0/tests/test_physics.py +175 -0
- reality-0.1.0/tests/test_world.py +66 -0
- reality-0.1.0/tools/futures_audit.py +374 -0
- reality-0.1.0/tools/generate_explore_dataset.py +39 -0
- reality-0.1.0/tools/reality_audit.py +529 -0
- reality-0.1.0/tools/reality_gpu_audit.py +415 -0
- reality-0.1.0/tools/release_audit.py +261 -0
- reality-0.1.0/tools/train_explore_predictor.py +29 -0
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
push:
|
|
6
|
+
branches: [main]
|
|
7
|
+
tags: ["v*"]
|
|
8
|
+
workflow_dispatch:
|
|
9
|
+
inputs:
|
|
10
|
+
publish:
|
|
11
|
+
description: Publish the current package version to PyPI
|
|
12
|
+
required: true
|
|
13
|
+
type: boolean
|
|
14
|
+
default: false
|
|
15
|
+
|
|
16
|
+
permissions:
|
|
17
|
+
contents: read
|
|
18
|
+
|
|
19
|
+
jobs:
|
|
20
|
+
test:
|
|
21
|
+
runs-on: ubuntu-latest
|
|
22
|
+
strategy:
|
|
23
|
+
fail-fast: false
|
|
24
|
+
matrix:
|
|
25
|
+
python-version: ["3.11", "3.12", "3.13"]
|
|
26
|
+
steps:
|
|
27
|
+
- uses: actions/checkout@v4
|
|
28
|
+
- uses: actions/setup-python@v5
|
|
29
|
+
with:
|
|
30
|
+
python-version: ${{ matrix.python-version }}
|
|
31
|
+
- run: python -m pip install --upgrade pip
|
|
32
|
+
- run: python -m pip install -e ".[dev,physics]"
|
|
33
|
+
- run: ruff format --check .
|
|
34
|
+
- run: ruff check .
|
|
35
|
+
# Run the strict static check once on the oldest supported interpreter.
|
|
36
|
+
# Runtime and packaging checks still run across the complete 3.11–3.13 matrix.
|
|
37
|
+
- name: Type check (mypy)
|
|
38
|
+
if: matrix.python-version == '3.11'
|
|
39
|
+
run: python -m mypy --no-incremental --follow-imports=skip --config-file pyproject.toml src/reality
|
|
40
|
+
- run: pytest
|
|
41
|
+
- run: python -m build
|
|
42
|
+
- run: python -m venv .release-venv
|
|
43
|
+
- run: .release-venv/bin/python -m pip install dist/*.whl
|
|
44
|
+
- run: .release-venv/bin/python -c "import reality; print(reality.__name__)"
|
|
45
|
+
|
|
46
|
+
cuda:
|
|
47
|
+
# Enable only after configuring a self-hosted NVIDIA runner with this repository
|
|
48
|
+
# variable. The CPU job above remains the required portable release gate.
|
|
49
|
+
if: ${{ vars.REALITY_CUDA_RUNNER == 'true' }}
|
|
50
|
+
runs-on: [self-hosted, linux, x64, gpu]
|
|
51
|
+
steps:
|
|
52
|
+
- uses: actions/checkout@v4
|
|
53
|
+
- uses: actions/setup-python@v5
|
|
54
|
+
with:
|
|
55
|
+
python-version: "3.11"
|
|
56
|
+
- run: python -m pip install --upgrade pip
|
|
57
|
+
- run: python -m pip install -e ".[dev,gpu]"
|
|
58
|
+
- run: python -m pytest tests/test_gpu.py -q
|
|
59
|
+
- run: python tools/futures_audit.py --full --output FUTURES_AUDIT.md
|
|
60
|
+
|
|
61
|
+
publish:
|
|
62
|
+
name: Publish to PyPI
|
|
63
|
+
if: github.event_name == 'workflow_dispatch' && inputs.publish || startsWith(github.ref, 'refs/tags/v')
|
|
64
|
+
needs: test
|
|
65
|
+
runs-on: ubuntu-latest
|
|
66
|
+
environment: pypi
|
|
67
|
+
permissions:
|
|
68
|
+
contents: read
|
|
69
|
+
id-token: write
|
|
70
|
+
steps:
|
|
71
|
+
- uses: actions/checkout@v4
|
|
72
|
+
- uses: actions/setup-python@v5
|
|
73
|
+
with:
|
|
74
|
+
python-version: "3.11"
|
|
75
|
+
- run: python -m pip install --upgrade build
|
|
76
|
+
- run: python -m build
|
|
77
|
+
- name: Publish package distributions to PyPI
|
|
78
|
+
uses: pypa/gh-action-pypi-publish@release/v1
|
reality-0.1.0/.gitignore
ADDED
|
@@ -0,0 +1,169 @@
|
|
|
1
|
+
# API design
|
|
2
|
+
|
|
3
|
+
## Stable surface
|
|
4
|
+
|
|
5
|
+
```python
|
|
6
|
+
import reality
|
|
7
|
+
|
|
8
|
+
world = reality.load("room.glb")
|
|
9
|
+
object_ = world.object("Chair")
|
|
10
|
+
result = world.distance("Chair", "Table")
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
`World.object()` accepts an object id, a unique name, or a registered `WorldObject`. Duplicate names are permitted but require lookup by id.
|
|
14
|
+
|
|
15
|
+
`WorldObject` exposes `name`, `id`, `transform`, `position`, `rotation`, `scale`, `bounds`, and `mesh`. Bounds are world-space AABBs; `local_bounds` retains the geometry before applying its transform. Rotations are XYZ Euler angles in radians.
|
|
16
|
+
|
|
17
|
+
All predicate methods accept two object references. `near` additionally accepts `within`, defaulting to `1.0` in `World.units`. `distance` returns `PredicateResult[float]`; the remaining methods return `PredicateResult[bool]`.
|
|
18
|
+
|
|
19
|
+
## Graph and visibility
|
|
20
|
+
|
|
21
|
+
```python
|
|
22
|
+
visibility = world.visible("Television", from_="Sofa")
|
|
23
|
+
assert visibility.value
|
|
24
|
+
print(visibility.visibility_fraction)
|
|
25
|
+
print([object_.name for object_ in visibility.occluding_objects])
|
|
26
|
+
|
|
27
|
+
for edge in world.relationships("Cup"):
|
|
28
|
+
print(edge.source.name, edge.type.value, edge.target.name)
|
|
29
|
+
```
|
|
30
|
+
|
|
31
|
+
`RelationshipType` includes `near`, `above`, `below`, `inside`, `contains`, `intersects`, `touching`, and `visible_from`. Graph construction records true deterministic spatial relationships. A successful `visible()` query additionally records a directed `visible_from` relationship from target to viewer.
|
|
32
|
+
|
|
33
|
+
Moving an object is explicit: `world.move("Chair", x=1.0)` or `world.update_transform("Chair", transform)`. Those methods only invalidate and refresh graph edges incident to the changed object.
|
|
34
|
+
|
|
35
|
+
## Result contract
|
|
36
|
+
|
|
37
|
+
`PredicateResult` has `value`, `measurement`, `units`, `reason`, `evidence`, and `objects`. `distance` is an alias for `measurement`, making this ergonomic:
|
|
38
|
+
|
|
39
|
+
```python
|
|
40
|
+
result = world.distance("Chair", "Table")
|
|
41
|
+
assert result.value == result.distance
|
|
42
|
+
```
|
|
43
|
+
|
|
44
|
+
Evidence always includes the world-space bounds involved. The immutable mapping prevents a caller accidentally altering an already-returned result.
|
|
45
|
+
|
|
46
|
+
For a visibility result, evidence additionally contains `visibility_fraction`, `occluding_objects`, and `sample_count`; the first two are surfaced as convenience properties.
|
|
47
|
+
|
|
48
|
+
## Snapshots, branches, and consequences
|
|
49
|
+
|
|
50
|
+
```python
|
|
51
|
+
before = world.snapshot()
|
|
52
|
+
future = world.branch()
|
|
53
|
+
future.move("Shelf", x=1.0)
|
|
54
|
+
future.rotate("Shelf", z=0.25)
|
|
55
|
+
future.scale("Shelf", x=1.1)
|
|
56
|
+
|
|
57
|
+
report = future.consequences()
|
|
58
|
+
for consequence in report:
|
|
59
|
+
print(consequence)
|
|
60
|
+
|
|
61
|
+
payload = report.to_dict()
|
|
62
|
+
json_text = report.to_json()
|
|
63
|
+
```
|
|
64
|
+
|
|
65
|
+
`move` and `rotate` are additive; `scale` is multiplicative. Each call records an ordered, UTC-timestamped change with old/new transforms and the supplied parameters. An unchanged object returned by a branch is the same immutable `WorldObject` instance as in the snapshot. A changed object is a new value object that retains the same opaque mesh reference.
|
|
66
|
+
|
|
67
|
+
`world.compare(branch_a, branch_b)` compares sibling branches. It rejects branches from another world lineage.
|
|
68
|
+
|
|
69
|
+
## Agents and navigation
|
|
70
|
+
|
|
71
|
+
```python
|
|
72
|
+
person = world.agent(
|
|
73
|
+
name="Person",
|
|
74
|
+
position=(0.0, 0.0, 0.0),
|
|
75
|
+
height=1.75,
|
|
76
|
+
radius=0.30,
|
|
77
|
+
step_height=0.15,
|
|
78
|
+
)
|
|
79
|
+
|
|
80
|
+
path = person.path_to("Exit")
|
|
81
|
+
reachability = world.reachable("Person", "Exit")
|
|
82
|
+
passage = person.can_pass("Door")
|
|
83
|
+
clearance = person.clearance_to("Exit")
|
|
84
|
+
```
|
|
85
|
+
|
|
86
|
+
`PathResult` contains `reachable`, path `points`, `distance`, `minimum_clearance`, `narrowest_point`, `blocked_by`, `reason`, and evidence. Path minimum clearance is free space from the agent body to the nearest inflated obstacle. `ReachabilityResult` adds required diameter and estimated available corridor width. Passage checks compare agent diameter and height with the opening AABB. Results expose `value` aliases where predicate-style use is convenient.
|
|
87
|
+
|
|
88
|
+
Agent category names have no behavioral meaning. Only dimensions and optional movement constraints affect navigation.
|
|
89
|
+
|
|
90
|
+
## Articulation
|
|
91
|
+
|
|
92
|
+
`World.articulate`, `can_open`, `can_extend`, and the `ArticulatedObject` handle return a
|
|
93
|
+
`MotionResult` with requested/maximum motion, blockers, units, reason, samples, and
|
|
94
|
+
evidence. Configuration is explicit, deterministic metadata. `reality.load` reads the
|
|
95
|
+
same schema from a `.reality.json` sidecar, glTF/GLB `extras.reality`, or an explicit
|
|
96
|
+
`metadata=` mapping. The schema supports `units`, `objects.<name>.articulation`, and
|
|
97
|
+
`objects.<name>.physics`; malformed or unknown fields raise `SceneMetadataError` rather
|
|
98
|
+
than being guessed or ignored. The object reference must resolve to a unique loaded
|
|
99
|
+
object. Later metadata sources override earlier articulation/physics fields; `units`
|
|
100
|
+
labels coordinates and never triggers implicit rescaling.
|
|
101
|
+
|
|
102
|
+
## Physics
|
|
103
|
+
|
|
104
|
+
`PhysicalProperties` describes mass, static/dynamic state, box collision shape,
|
|
105
|
+
friction, restitution, and center-of-mass offset. `simulate`, `drop`, `push`, `contacts`,
|
|
106
|
+
and `stable` return backend-neutral typed results. Simulation-observed consequences are
|
|
107
|
+
labeled separately from direct and downstream deterministic consequences. MuJoCo uses
|
|
108
|
+
oriented boxes built from local bounds and maps dynamic position and orientation back
|
|
109
|
+
to `Transform`. It caches immutable compiled topology per world/backend and creates a
|
|
110
|
+
fresh simulation state for every call, preserving branch isolation. Performance timing
|
|
111
|
+
and cache reuse are reported in `SimulationResult.evidence`.
|
|
112
|
+
|
|
113
|
+
## Branch batches
|
|
114
|
+
|
|
115
|
+
`World.branches(count)` returns a `BranchBatch`; `randomize("Object.position", ...)`
|
|
116
|
+
stores compact translation deltas and `evaluate(predicates=("collision",))` runs the CPU
|
|
117
|
+
reference batch. CUDA selection is capability-checked and never silently falls back.
|
|
118
|
+
|
|
119
|
+
`World.futures(count)` returns the named `Futures` form for large alternate-world search:
|
|
120
|
+
|
|
121
|
+
```python
|
|
122
|
+
from reality.predicates import collision, distance, maximize, no_collision
|
|
123
|
+
|
|
124
|
+
futures = world.futures(10_000).randomize_position(
|
|
125
|
+
"Table", x=(-1.0, 1.0), y=(-0.5, 0.5), z=(0.0, 0.0), seed=7
|
|
126
|
+
)
|
|
127
|
+
evaluation = futures.evaluate([collision("Table", "Chair"), distance("Table", "Chair")])
|
|
128
|
+
ranked = evaluation.rank(
|
|
129
|
+
constraints=[no_collision("Table", "Chair")],
|
|
130
|
+
objectives=[maximize(distance("Table", "Chair"))],
|
|
131
|
+
)
|
|
132
|
+
candidate = ranked.best(1)[0]
|
|
133
|
+
branch = candidate.materialize()
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
`PredicateSpec` values are typed and reusable. `where()` applies hard `Condition`
|
|
137
|
+
constraints; `rank()` applies weighted `Objective` values; candidates stay compact until
|
|
138
|
+
`materialize()` or `consequences()` is called. `collision` and `distance` use world AABBs,
|
|
139
|
+
and batch `visibility` is a deterministic AABB ray experiment. Batched rotations/scales
|
|
140
|
+
are accepted and retained for future kernels, but currently raise `NotImplementedError`
|
|
141
|
+
when evaluated with non-default values. `BatchEvaluation.to_dict()` and
|
|
142
|
+
`RankedFutures.to_dict()` provide machine-readable summaries.
|
|
143
|
+
|
|
144
|
+
## Exact exploration
|
|
145
|
+
|
|
146
|
+
`World.explore()` is a convenience layer over `Futures`; it does not introduce a second
|
|
147
|
+
optimizer or different predicate semantics.
|
|
148
|
+
|
|
149
|
+
```python
|
|
150
|
+
result = world.explore(
|
|
151
|
+
possibilities=100_000,
|
|
152
|
+
changes=[reality.position("Shelf", x=(-1.0, 1.0))],
|
|
153
|
+
constraints=[no_collision("Shelf", "Door")],
|
|
154
|
+
objectives=[maximize(distance("Shelf", "Door"))],
|
|
155
|
+
seed=42,
|
|
156
|
+
best=10,
|
|
157
|
+
)
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
`PositionSearchChange` declares inclusive coordinate ranges. Candidate sampling is
|
|
161
|
+
deterministic for a seed, constraints are exact hard filters, and objective ties are
|
|
162
|
+
broken by candidate index. `ExplorationResult` exposes backend, counts, scores, compact
|
|
163
|
+
deltas, predicate evidence, `best()`, `to_dict()`, and `to_json()`. Returned candidates
|
|
164
|
+
remain lazy `FutureCandidate` values until `materialize()` is called.
|
|
165
|
+
|
|
166
|
+
`backend="auto"` selects CUDA only after the accelerator capability check succeeds;
|
|
167
|
+
`backend="cpu"` forces the NumPy reference path. CUDA evaluates the same documented
|
|
168
|
+
AABB semantics as CPU. Any future learned prioritizer is experimental, opt-in, and may
|
|
169
|
+
only order candidates before exact validation; it never changes valid/invalid results.
|
|
@@ -0,0 +1,118 @@
|
|
|
1
|
+
# Architecture
|
|
2
|
+
|
|
3
|
+
```
|
|
4
|
+
public API: reality.load, World, WorldObject, Transform, Bounds, PredicateResult
|
|
5
|
+
|
|
|
6
|
+
backend-neutral core
|
|
7
|
+
|
|
|
8
|
+
RealityGraph (edges reference WorldObjects)
|
|
9
|
+
|
|
|
10
|
+
snapshots -> branch delta/graph overlay -> consequences
|
|
11
|
+
|
|
|
12
|
+
Trimesh loader adapter (today)
|
|
13
|
+
```
|
|
14
|
+
|
|
15
|
+
`_models.py` contains immutable data/value objects. `World` owns lookup indexes and evaluates spatial predicates using the world-space axis-aligned bounds of its objects. `_loaders.py` is the only module that imports Trimesh; it turns a Trimesh scene graph into `WorldObject` instances while retaining the source mesh as an opaque reference.
|
|
16
|
+
|
|
17
|
+
This split means a future USD, Omniverse, renderer, or physics adapter can produce the same core objects without changing application code. Exact mesh queries should arrive as explicitly named capabilities rather than silently changing the existing AABB semantics.
|
|
18
|
+
|
|
19
|
+
The Z axis is vertical for `above` and `below`. The default coordinate unit is metres (`m`), configurable when constructing a `World`.
|
|
20
|
+
|
|
21
|
+
## Reality Graph and updates
|
|
22
|
+
|
|
23
|
+
`World.graph` is a `RealityGraph` built from known deterministic spatial facts. `Relationship` stores references to the already-loaded `WorldObject` instances, never copied mesh data. `world.relationships("Cup")` returns all incident graph edges.
|
|
24
|
+
|
|
25
|
+
The graph indexes each edge by both object ids. `World.update_transform()` and `World.move()` invalidate only edges incident to the changed object, then recompute that object against the rest of the scene. Relationships entirely between unaffected objects stay in place. Visibility edges are query-driven and are invalidated with either involved object; they are deliberately not eagerly recomputed.
|
|
26
|
+
|
|
27
|
+
Visibility casts rays from the viewer AABB centre to the target centre and corners, treating all other world AABBs as occluders. It returns the visible sample fraction and the objects that blocked at least one ray. This is deterministic but conservative/approximate compared with future mesh-exact visibility.
|
|
28
|
+
|
|
29
|
+
## Snapshots and persistent branches
|
|
30
|
+
|
|
31
|
+
`World.snapshot()` returns an immutable `WorldSnapshot`. Its object tuple, lookup indexes, relationships, and known visibility results are stable views. Because `WorldObject`, transforms, and bounds are immutable, snapshots safely retain references to existing objects and opaque mesh data instead of copying geometry.
|
|
32
|
+
|
|
33
|
+
`World.branch()` creates a `WorldBranch` over a cached snapshot. The branch maintains:
|
|
34
|
+
|
|
35
|
+
- an object-id-to-replacement delta for changed objects;
|
|
36
|
+
- an ordered `ChangeSet` containing `MoveObject`, `RotateObject`, and `ScaleObject` records;
|
|
37
|
+
- a `RealityGraph` overlay that points at snapshot edges and stores only recalculated edges;
|
|
38
|
+
- `GraphUpdateStats` for predicates present before changes, invalidated, recalculated, and reused.
|
|
39
|
+
|
|
40
|
+
On a transform change, only pairs involving the changed object are recalculated. Base graph edges between unchanged objects remain the same Python objects. Known visibility queries are recalculated because any moved object may become or cease to be an occluder; such a result is classified as downstream when neither visibility endpoint moved.
|
|
41
|
+
|
|
42
|
+
Branches use the exact snapshot they were created from, so later mutations to the source `World` cannot alter an existing branch.
|
|
43
|
+
|
|
44
|
+
## Consequence comparison
|
|
45
|
+
|
|
46
|
+
`WorldBranch.consequences()` compares its current state with its base snapshot. It evaluates distance and existing graph predicates only across the union of changed-object dependency frontiers, then compares known visibility results. `World.compare(a, b)` applies the same engine to two sibling branches.
|
|
47
|
+
|
|
48
|
+
`ConsequenceSet` contains typed `Consequence` records plus the branch `ChangeSet` and recomputation instrumentation. `to_dict()` and `to_json()` intentionally serialize object identity and geometric evidence without attempting to serialize backend mesh instances.
|
|
49
|
+
|
|
50
|
+
## Navigation backend
|
|
51
|
+
|
|
52
|
+
The initial navigation backend is deliberately replaceable and CPU-only. Each query projects relevant world AABBs onto an XY occupancy grid, expands obstacles by the querying agent’s radius, and runs deterministic 8-connected A*. Z is up; the agent position’s Z value is its foot/ground elevation. Geometry blocks movement when it overlaps the volume between step height and agent height.
|
|
53
|
+
|
|
54
|
+
The grid covers the start/target rectangle plus `World.navigation_margin` (2 m by default), at `World.navigation_resolution` (0.25 m by default). The target object is treated as a destination marker and excluded from obstacles. This finite query envelope is an explicit assumption: callers needing larger detours should increase the margin.
|
|
55
|
+
|
|
56
|
+
`max_slope` is retained in the agent model and evidence, but the current projected grid is flat and does not yet evaluate terrain slope. `can_pass()` interprets an opening object’s largest horizontal AABB extent as aperture width and its Z extent as aperture height.
|
|
57
|
+
|
|
58
|
+
Navigation queries are lazy and cached by agent/target id. Their `reachable_by`, `unreachable_by`, and `blocks_path_of` edges are stored in the Reality Graph only after a query. Any object move invalidates known navigation queries because any object may become an obstacle; only those known queries are recalculated. Branch consequence analysis compares their reachability and minimum-clearance results as downstream state.
|
|
59
|
+
|
|
60
|
+
`PathResult.export_debug()` writes a standalone SVG: green is query-local walkable space, red rectangles are radius-inflated obstacle regions, the blue polyline is the path, and a dashed line indicates a blocked direct route.
|
|
61
|
+
|
|
62
|
+
## Articulation and replaceable physics
|
|
63
|
+
|
|
64
|
+
`_metadata.py` validates the portable, explicit Reality metadata schema. `_loaders.py`
|
|
65
|
+
collects glTF/GLB `extras.reality`, an optional `.reality.json` sidecar, and caller
|
|
66
|
+
metadata in that precedence order. It applies validated articulation and physical
|
|
67
|
+
properties after geometry loading. This keeps mesh import backend-neutral and avoids
|
|
68
|
+
inventing physical semantics from names or topology.
|
|
69
|
+
|
|
70
|
+
`_articulation.py` stores explicit revolute/prismatic joints. It samples swept
|
|
71
|
+
world-AABBs at 1 degree or 0.01 m by default and binary-refines the first collision to
|
|
72
|
+
0.01 degree or 0.0001 m. Conservative AABBs can produce mesh-shape false positives;
|
|
73
|
+
features thinner than a sampling interval can be missed. Known motion queries are lazy
|
|
74
|
+
graph dependencies and are recalculated after relevant geometry changes.
|
|
75
|
+
|
|
76
|
+
`backends/base.py` defines Reality's narrow `PhysicsBackend` protocol.
|
|
77
|
+
`backends/mujoco.py` is the CPU reference: explicit properties become headless MuJoCo
|
|
78
|
+
oriented box rigid bodies, including transform rotation and center-of-mass offsets.
|
|
79
|
+
Compiled topology is cached in the world-local backend; every run creates new MuJoCo
|
|
80
|
+
state and initializes dynamic body poses, so cached models never share branch state.
|
|
81
|
+
When a solve changes several bodies, `RealityGraph.refresh_objects()` updates their
|
|
82
|
+
combined dependency frontier once instead of recalculating changed/changed pairs and
|
|
83
|
+
lazy query invalidation per body. Current limitations include box-only collision shapes,
|
|
84
|
+
a z=0 plane, no simulated joints, and no literal restitution-to-MuJoCo mapping.
|
|
85
|
+
|
|
86
|
+
## Batched branch memory layout and CUDA boundary
|
|
87
|
+
|
|
88
|
+
`_batch.py` keeps one shared snapshot, immutable base bounds, and one dense
|
|
89
|
+
`branch_count x 3` float64 translation array per changed object. It never builds a
|
|
90
|
+
complete `World` per alternative. `World.futures()` is the large-search spelling;
|
|
91
|
+
`World.branches()` remains compatible with the earlier API. Future candidates are lazy
|
|
92
|
+
views and selected candidates alone materialize copy-on-write `WorldBranch` instances.
|
|
93
|
+
Vectorized CPU collision, AABB distance, and deterministic bounding-volume visibility
|
|
94
|
+
are implemented, with typed predicate specifications, constraints, and ranking.
|
|
95
|
+
`_warp_ops.py` adds custom Warp kernels for branch/object transforms, AABB overlap, AABB
|
|
96
|
+
distance, and centre-to-centre AABB visibility, each with a separate NumPy oracle and
|
|
97
|
+
explicit CUDA synchronization. `_accelerators.py` probes optional Warp lazily. CUDA is
|
|
98
|
+
considered validated only after launches and CPU/GPU parity tests succeed on that host;
|
|
99
|
+
the audit reports `PARTIAL` when CUDA is absent rather than inferring a result. The
|
|
100
|
+
visibility kernel deliberately has the same conservative AABB semantics as the CPU
|
|
101
|
+
batch path—it is not triangle-mesh ray tracing. Graph and explanation logic remains
|
|
102
|
+
CPU-resident by design.
|
|
103
|
+
|
|
104
|
+
## Exact search and optional learning
|
|
105
|
+
|
|
106
|
+
`_explore.py` composes the existing compact `Futures` representation: it samples one
|
|
107
|
+
deterministic delta matrix per declared change, invokes typed predicates in a batch,
|
|
108
|
+
applies exact conditions, ranks stable objective scores, and returns lazy candidates.
|
|
109
|
+
No candidate branch or mesh copy exists until a selected `FutureCandidate` is
|
|
110
|
+
materialized. GPU predicate arrays currently transfer per evaluation; immutable scene
|
|
111
|
+
arrays are not yet retained across independent calls, and ranking/filter reduction stays
|
|
112
|
+
on CPU so its evidence remains inspectable. Those are measured limitations, not hidden
|
|
113
|
+
fallbacks.
|
|
114
|
+
|
|
115
|
+
`reality.experimental` contains an optional scikit-learn prioritizer. Dataset generation
|
|
116
|
+
uses Reality's exact results as ground truth. The predictor can only propose a candidate
|
|
117
|
+
order; downstream code must run `Futures.evaluate()`/`World.explore()` exact validation
|
|
118
|
+
before accepting a result.
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes are documented here. This project follows Semantic Versioning from
|
|
4
|
+
its first public release.
|
|
5
|
+
|
|
6
|
+
## 0.1.0 — Unreleased
|
|
7
|
+
|
|
8
|
+
- Deterministic world loading and AABB spatial predicates.
|
|
9
|
+
- Reality Graph, visibility evidence, snapshots, copy-on-write branches, and consequences.
|
|
10
|
+
- Navigation, articulation, metadata ingestion, and optional CPU MuJoCo simulation.
|
|
11
|
+
- Compact Futures plus `World.explore()` exact layout search.
|
|
12
|
+
- Optional Warp kernels with CPU-oracle validation and optional learned candidate prioritization.
|
|
13
|
+
|
|
14
|
+
## Release policy
|
|
15
|
+
|
|
16
|
+
Public APIs documented in `API_DESIGN.md` are additive within the 0.1 series. Geometry and
|
|
17
|
+
visibility semantics remain explicit: AABB predicates never silently become mesh-exact.
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# Contributing
|
|
2
|
+
|
|
3
|
+
Thanks for improving `reality`. This project uses Python 3.11+ and a `src/` layout.
|
|
4
|
+
|
|
5
|
+
## Setup
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
git clone https://github.com/reality-python/reality.git
|
|
9
|
+
cd reality
|
|
10
|
+
python -m pip install -e ".[dev]"
|
|
11
|
+
```
|
|
12
|
+
|
|
13
|
+
Before opening a pull request, run:
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
ruff format --check .
|
|
17
|
+
ruff check .
|
|
18
|
+
python -m mypy src/reality
|
|
19
|
+
pytest
|
|
20
|
+
```
|
|
21
|
+
|
|
22
|
+
Keep public APIs typed and documented. Add focused tests for changes in geometric semantics, including result measurements and evidence. Preserve the backend-neutral public model: imports of a backend belong in an adapter, not `World` or the value objects.
|
|
23
|
+
|
|
24
|
+
By contributing, you agree that contributions are provided under the Apache-2.0 license.
|
|
@@ -0,0 +1,56 @@
|
|
|
1
|
+
# Futures audit
|
|
2
|
+
|
|
3
|
+
Status: **PARTIAL**
|
|
4
|
+
|
|
5
|
+
This report was generated by `python tools/futures_audit.py --full --output FUTURES_AUDIT.md`.
|
|
6
|
+
|
|
7
|
+
## Reproducibility
|
|
8
|
+
|
|
9
|
+
- Revision: `e15e0dc390792784295ce0de8fc89c766119f1fa`
|
|
10
|
+
- Python: `3.11.9`
|
|
11
|
+
- Platform: `Windows-10-10.0.26200-SP0`
|
|
12
|
+
- Scene objects: `1000`
|
|
13
|
+
- Futures: `10000`
|
|
14
|
+
- CUDA: `CUDA driver/device is unavailable.`
|
|
15
|
+
|
|
16
|
+
## GPU Validation
|
|
17
|
+
|
|
18
|
+
- CUDA available: `False`
|
|
19
|
+
- CUDA device: `unavailable`
|
|
20
|
+
- Custom Warp kernels tested: `none`
|
|
21
|
+
- CPU/GPU parity status: **NOT_RUN**
|
|
22
|
+
- GPU test count/pass count: `0` / `0`
|
|
23
|
+
- GPU execution actually used: `False`
|
|
24
|
+
|
|
25
|
+
CUDA validation could not be performed: CUDA driver/device is unavailable.
|
|
26
|
+
|
|
27
|
+
## Compact state evidence
|
|
28
|
+
|
|
29
|
+
- Shared snapshot: `True`
|
|
30
|
+
- Measured NumPy delta bytes: `240000`
|
|
31
|
+
- Logical float64 delta payload: `240000`
|
|
32
|
+
- 10k evaluation seconds: `0.659171`
|
|
33
|
+
- Candidates without collision: `10000`
|
|
34
|
+
|
|
35
|
+
## Scaling
|
|
36
|
+
|
|
37
|
+
| futures | creation seconds | distance seconds | delta bytes |
|
|
38
|
+
|---:|---:|---:|---:|
|
|
39
|
+
| 100 | 0.001881 | 0.000137 | 2400 |
|
|
40
|
+
| 1000 | 0.001212 | 0.000225 | 24000 |
|
|
41
|
+
| 10000 | 0.001903 | 0.002073 | 240000 |
|
|
42
|
+
| 50000 | 0.002214 | 0.010108 | 1200000 |
|
|
43
|
+
| 100000 | 0.005615 | 0.030814 | 2400000 |
|
|
44
|
+
|
|
45
|
+
## CPU/GPU boundary
|
|
46
|
+
|
|
47
|
+
Visibility is a deterministic AABB bounding-volume experiment, not exact mesh occlusion.
|
|
48
|
+
|
|
49
|
+
Future GPU work should keep immutable bounds resident, batch ray and broad-phase kernels, and
|
|
50
|
+
perform filtering/ranking reductions before transferring selected candidates to Python.
|
|
51
|
+
|
|
52
|
+
## Limitations
|
|
53
|
+
|
|
54
|
+
- CUDA validation could not be performed: CUDA driver/device is unavailable.
|
|
55
|
+
- Visibility uses deterministic AABB ray tests, not exact triangle-mesh rays.
|
|
56
|
+
- Batched rotation and scale are stored but predicate evaluation is not implemented yet.
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
{
|
|
2
|
+
"status": "PARTIAL",
|
|
3
|
+
"revision": "e15e0dc390792784295ce0de8fc89c766119f1fa",
|
|
4
|
+
"python": "3.11.9",
|
|
5
|
+
"platform": "Windows-10-10.0.26200-SP0",
|
|
6
|
+
"cuda": {
|
|
7
|
+
"installed": true,
|
|
8
|
+
"version": "1.17.0",
|
|
9
|
+
"cuda_available": false,
|
|
10
|
+
"devices": [
|
|
11
|
+
"cpu"
|
|
12
|
+
],
|
|
13
|
+
"reason": "CUDA driver/device is unavailable."
|
|
14
|
+
},
|
|
15
|
+
"gpu_validation": {
|
|
16
|
+
"cuda_available": false,
|
|
17
|
+
"device": null,
|
|
18
|
+
"custom_warp_kernels_tested": [],
|
|
19
|
+
"kernel_parity_count": 0,
|
|
20
|
+
"kernel_parity_pass_count": 0,
|
|
21
|
+
"gpu_test_count": 0,
|
|
22
|
+
"gpu_pass_count": 0,
|
|
23
|
+
"cpu_gpu_parity": "NOT_RUN",
|
|
24
|
+
"gpu_execution_used": false,
|
|
25
|
+
"failures": [],
|
|
26
|
+
"pytest": {
|
|
27
|
+
"status": "NOT_RUN",
|
|
28
|
+
"count": 0,
|
|
29
|
+
"passed": 0,
|
|
30
|
+
"failed": 0,
|
|
31
|
+
"skipped": 0
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"scene_objects": 1000,
|
|
35
|
+
"futures": 10000,
|
|
36
|
+
"delta_bytes": 240000,
|
|
37
|
+
"logical_delta_bytes": 240000,
|
|
38
|
+
"evaluation_seconds": 0.6591709999920567,
|
|
39
|
+
"selected_without_collision": 10000,
|
|
40
|
+
"shared_snapshot": true,
|
|
41
|
+
"predicates": [
|
|
42
|
+
"collision",
|
|
43
|
+
"distance",
|
|
44
|
+
"visibility"
|
|
45
|
+
],
|
|
46
|
+
"visibility_is_bounding_volume": true,
|
|
47
|
+
"limitations": [
|
|
48
|
+
"CUDA validation could not be performed: CUDA driver/device is unavailable.",
|
|
49
|
+
"Visibility uses deterministic AABB ray tests, not exact triangle-mesh rays.",
|
|
50
|
+
"Batched rotation and scale are stored but predicate evaluation is not implemented yet."
|
|
51
|
+
],
|
|
52
|
+
"gpu_acceleration_next": [
|
|
53
|
+
"Keep AABB centers/extents resident on GPU across many candidate batches.",
|
|
54
|
+
"Move visibility ray batches and broad-phase pair culling to Warp kernels.",
|
|
55
|
+
"Add GPU reduction kernels for filtering and ranking to reduce host transfers."
|
|
56
|
+
],
|
|
57
|
+
"scaling": [
|
|
58
|
+
{
|
|
59
|
+
"futures": 100,
|
|
60
|
+
"creation_seconds": 0.0018807000014930964,
|
|
61
|
+
"distance_seconds": 0.00013670000771526247,
|
|
62
|
+
"delta_bytes": 2400
|
|
63
|
+
},
|
|
64
|
+
{
|
|
65
|
+
"futures": 1000,
|
|
66
|
+
"creation_seconds": 0.0012117000005673617,
|
|
67
|
+
"distance_seconds": 0.00022480000916402787,
|
|
68
|
+
"delta_bytes": 24000
|
|
69
|
+
},
|
|
70
|
+
{
|
|
71
|
+
"futures": 10000,
|
|
72
|
+
"creation_seconds": 0.0019033999997191131,
|
|
73
|
+
"distance_seconds": 0.0020733999990625307,
|
|
74
|
+
"delta_bytes": 240000
|
|
75
|
+
},
|
|
76
|
+
{
|
|
77
|
+
"futures": 50000,
|
|
78
|
+
"creation_seconds": 0.002214100008131936,
|
|
79
|
+
"distance_seconds": 0.010108400005265139,
|
|
80
|
+
"delta_bytes": 1200000
|
|
81
|
+
},
|
|
82
|
+
{
|
|
83
|
+
"futures": 100000,
|
|
84
|
+
"creation_seconds": 0.005615399990347214,
|
|
85
|
+
"distance_seconds": 0.030813899997156113,
|
|
86
|
+
"delta_bytes": 2400000
|
|
87
|
+
}
|
|
88
|
+
],
|
|
89
|
+
"cpu_distance_oracle": [
|
|
90
|
+
1.0
|
|
91
|
+
]
|
|
92
|
+
}
|