long-tamp 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.
- long_tamp-0.1.0/LICENSE +21 -0
- long_tamp-0.1.0/PKG-INFO +225 -0
- long_tamp-0.1.0/README.md +177 -0
- long_tamp-0.1.0/pyproject.toml +126 -0
- long_tamp-0.1.0/setup.cfg +4 -0
- long_tamp-0.1.0/src/long_tamp/__init__.py +124 -0
- long_tamp-0.1.0/src/long_tamp/backends/__init__.py +66 -0
- long_tamp-0.1.0/src/long_tamp/backends/_hpp_libs.py +96 -0
- long_tamp-0.1.0/src/long_tamp/backends/_urdf_paths.py +89 -0
- long_tamp-0.1.0/src/long_tamp/backends/base.py +545 -0
- long_tamp-0.1.0/src/long_tamp/backends/pyhpp.py +2827 -0
- long_tamp-0.1.0/src/long_tamp/cli/__init__.py +265 -0
- long_tamp-0.1.0/src/long_tamp/cli/config_loader.py +89 -0
- long_tamp-0.1.0/src/long_tamp/cli/interactive_pickers.py +335 -0
- long_tamp-0.1.0/src/long_tamp/config/__init__.py +35 -0
- long_tamp-0.1.0/src/long_tamp/config/base_config.py +341 -0
- long_tamp-0.1.0/src/long_tamp/config/yaml_loader.py +456 -0
- long_tamp-0.1.0/src/long_tamp/logging/__init__.py +41 -0
- long_tamp-0.1.0/src/long_tamp/logging/log_loader.py +205 -0
- long_tamp-0.1.0/src/long_tamp/logging/run_logger.py +336 -0
- long_tamp-0.1.0/src/long_tamp/logging/schema.py +143 -0
- long_tamp-0.1.0/src/long_tamp/logging/setup.py +100 -0
- long_tamp-0.1.0/src/long_tamp/planning/__init__.py +76 -0
- long_tamp-0.1.0/src/long_tamp/planning/config.py +619 -0
- long_tamp-0.1.0/src/long_tamp/planning/constraints.py +955 -0
- long_tamp-0.1.0/src/long_tamp/planning/graph.py +1367 -0
- long_tamp-0.1.0/src/long_tamp/planning/grasp_state.py +443 -0
- long_tamp-0.1.0/src/long_tamp/planning/path_io.py +232 -0
- long_tamp-0.1.0/src/long_tamp/planning/path_recorder.py +668 -0
- long_tamp-0.1.0/src/long_tamp/planning/path_replay.py +315 -0
- long_tamp-0.1.0/src/long_tamp/planning/planner.py +73 -0
- long_tamp-0.1.0/src/long_tamp/planning/scene.py +479 -0
- long_tamp-0.1.0/src/long_tamp/planning/sequential_graph_factory.py +353 -0
- long_tamp-0.1.0/src/long_tamp/planning/sequential_grasp_filter.py +328 -0
- long_tamp-0.1.0/src/long_tamp/tasks/__init__.py +33 -0
- long_tamp-0.1.0/src/long_tamp/tasks/base.py +965 -0
- long_tamp-0.1.0/src/long_tamp/tasks/block_recovery.py +396 -0
- long_tamp-0.1.0/src/long_tamp/tasks/grasp_sequence.py +4827 -0
- long_tamp-0.1.0/src/long_tamp/tasks/interactive_grasp_sequence_builder.py +599 -0
- long_tamp-0.1.0/src/long_tamp/tasks/mission_checkpoint.py +151 -0
- long_tamp-0.1.0/src/long_tamp/tasks/sequence_orchestrator.py +314 -0
- long_tamp-0.1.0/src/long_tamp/tasks/task_planning/__init__.py +16 -0
- long_tamp-0.1.0/src/long_tamp/tasks/task_planning/capabilities.py +82 -0
- long_tamp-0.1.0/src/long_tamp/tasks/task_planning/compiler.py +112 -0
- long_tamp-0.1.0/src/long_tamp/tasks/task_planning/host.py +135 -0
- long_tamp-0.1.0/src/long_tamp/tasks/task_planning/model.py +192 -0
- long_tamp-0.1.0/src/long_tamp/tasks/task_planning/session.py +149 -0
- long_tamp-0.1.0/src/long_tamp/utils/__init__.py +49 -0
- long_tamp-0.1.0/src/long_tamp/utils/interactive.py +248 -0
- long_tamp-0.1.0/src/long_tamp/utils/transforms.py +267 -0
- long_tamp-0.1.0/src/long_tamp/version.py +3 -0
- long_tamp-0.1.0/src/long_tamp/visualization/__init__.py +64 -0
- long_tamp-0.1.0/src/long_tamp/visualization/live_graph_viz.py +581 -0
- long_tamp-0.1.0/src/long_tamp/visualization/video_recorder.py +399 -0
- long_tamp-0.1.0/src/long_tamp/visualization/viz.py +987 -0
- long_tamp-0.1.0/src/long_tamp.egg-info/PKG-INFO +225 -0
- long_tamp-0.1.0/src/long_tamp.egg-info/SOURCES.txt +97 -0
- long_tamp-0.1.0/src/long_tamp.egg-info/dependency_links.txt +1 -0
- long_tamp-0.1.0/src/long_tamp.egg-info/requires.txt +29 -0
- long_tamp-0.1.0/src/long_tamp.egg-info/top_level.txt +1 -0
- long_tamp-0.1.0/tests/test_backend_optimizer_timeout.py +41 -0
- long_tamp-0.1.0/tests/test_block_recovery.py +257 -0
- long_tamp-0.1.0/tests/test_config_seed.py +40 -0
- long_tamp-0.1.0/tests/test_core.py +114 -0
- long_tamp-0.1.0/tests/test_graph_factory_visited_memo.py +289 -0
- long_tamp-0.1.0/tests/test_grasp_release_capabilities.py +264 -0
- long_tamp-0.1.0/tests/test_grasp_release_use_case_twin.py +200 -0
- long_tamp-0.1.0/tests/test_grasp_sequence_helpers.py +158 -0
- long_tamp-0.1.0/tests/test_grasp_sequence_logging.py +327 -0
- long_tamp-0.1.0/tests/test_grasp_sequence_phase_q_hints.py +372 -0
- long_tamp-0.1.0/tests/test_grasp_sequence_resume_state.py +187 -0
- long_tamp-0.1.0/tests/test_grasp_state_copy.py +76 -0
- long_tamp-0.1.0/tests/test_logging_setup.py +99 -0
- long_tamp-0.1.0/tests/test_lookahead_also_reachable.py +219 -0
- long_tamp-0.1.0/tests/test_mission_checkpoint.py +79 -0
- long_tamp-0.1.0/tests/test_path_recorder.py +789 -0
- long_tamp-0.1.0/tests/test_path_replay.py +262 -0
- long_tamp-0.1.0/tests/test_plan_phase_edges_generation_retry.py +261 -0
- long_tamp-0.1.0/tests/test_planning_helpers.py +270 -0
- long_tamp-0.1.0/tests/test_problem_distance_refresh.py +68 -0
- long_tamp-0.1.0/tests/test_pruned_recursion.py +306 -0
- long_tamp-0.1.0/tests/test_pyhpp.py +646 -0
- long_tamp-0.1.0/tests/test_refactored_modules.py +316 -0
- long_tamp-0.1.0/tests/test_release_frozen_arms.py +230 -0
- long_tamp-0.1.0/tests/test_resume_start_config.py +142 -0
- long_tamp-0.1.0/tests/test_run_logger.py +348 -0
- long_tamp-0.1.0/tests/test_sequence_orchestrator.py +384 -0
- long_tamp-0.1.0/tests/test_sequential_filter.py +306 -0
- long_tamp-0.1.0/tests/test_task_base_helpers.py +591 -0
- long_tamp-0.1.0/tests/test_task_plan_compiler.py +187 -0
- long_tamp-0.1.0/tests/test_task_planning_host.py +17 -0
- long_tamp-0.1.0/tests/test_task_planning_ir.py +134 -0
- long_tamp-0.1.0/tests/test_task_planning_session.py +92 -0
- long_tamp-0.1.0/tests/test_twin_examples.py +100 -0
- long_tamp-0.1.0/tests/test_twin_regrasp_bt_session.py +136 -0
- long_tamp-0.1.0/tests/test_urdf_mesh_paths.py +59 -0
- long_tamp-0.1.0/tests/test_video_output_dir_default.py +110 -0
- long_tamp-0.1.0/tests/test_viewers.py +459 -0
- long_tamp-0.1.0/tests/test_yaml_loader_paths.py +64 -0
long_tamp-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025 CNRS
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
long_tamp-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,225 @@
|
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
|
+
Name: long-tamp
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Long-TAMP - Manipulation Planning Framework
|
|
5
|
+
Author-email: Thanh Nguyen <dvtnguyen@laas.fr>
|
|
6
|
+
Maintainer-email: Thanh Nguyen <dvtnguyen@laas.fr>
|
|
7
|
+
License: MIT
|
|
8
|
+
Project-URL: Homepage, https://github.com/thanhndv212/long-tamp
|
|
9
|
+
Project-URL: Documentation, https://long-tamp.readthedocs.io
|
|
10
|
+
Project-URL: Repository, https://github.com/thanhndv212/long-tamp
|
|
11
|
+
Project-URL: Issues, https://github.com/thanhndv212/long-tamp/issues
|
|
12
|
+
Keywords: robotics,manipulation,motion-planning,hpp,agimus
|
|
13
|
+
Classifier: Development Status :: 3 - Alpha
|
|
14
|
+
Classifier: Intended Audience :: Science/Research
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Programming Language :: Python :: 3
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Topic :: Scientific/Engineering
|
|
20
|
+
Requires-Python: >=3.10
|
|
21
|
+
Description-Content-Type: text/markdown
|
|
22
|
+
License-File: LICENSE
|
|
23
|
+
Requires-Dist: numpy>=1.26
|
|
24
|
+
Requires-Dist: pyyaml>=5.1
|
|
25
|
+
Requires-Dist: pin>=2.6
|
|
26
|
+
Requires-Dist: viser
|
|
27
|
+
Requires-Dist: trimesh
|
|
28
|
+
Requires-Dist: pycollada
|
|
29
|
+
Provides-Extra: hpp
|
|
30
|
+
Requires-Dist: hpp-python>=9.0.2; extra == "hpp"
|
|
31
|
+
Requires-Dist: hpp-gepetto-viewer>=9.0.2; extra == "hpp"
|
|
32
|
+
Provides-Extra: toppra
|
|
33
|
+
Requires-Dist: hpp-toppra>=9.0.2; extra == "toppra"
|
|
34
|
+
Provides-Extra: dev
|
|
35
|
+
Requires-Dist: pytest>=6.0; extra == "dev"
|
|
36
|
+
Requires-Dist: pytest-cov; extra == "dev"
|
|
37
|
+
Requires-Dist: black; extra == "dev"
|
|
38
|
+
Requires-Dist: ruff; extra == "dev"
|
|
39
|
+
Requires-Dist: sphinx; extra == "dev"
|
|
40
|
+
Requires-Dist: sphinx-rtd-theme; extra == "dev"
|
|
41
|
+
Provides-Extra: docs
|
|
42
|
+
Requires-Dist: mkdocs>=1.6; extra == "docs"
|
|
43
|
+
Requires-Dist: mkdocs-material>=9.5; extra == "docs"
|
|
44
|
+
Requires-Dist: mkdocs-include-markdown-plugin>=7.0; extra == "docs"
|
|
45
|
+
Provides-Extra: all
|
|
46
|
+
Requires-Dist: long-tamp[dev,docs]; extra == "all"
|
|
47
|
+
Dynamic: license-file
|
|
48
|
+
|
|
49
|
+
# Long-TAMP - Long-Horizon Task-and-Motion Planning
|
|
50
|
+
|
|
51
|
+
Long-horizon, multi-arm task-and-motion planning (TAMP) for manipulation, built on HPP (Humanoid Path Planner).
|
|
52
|
+
|
|
53
|
+
`long_tamp` plans **long, multi-step manipulation sequences** for **several robot arms** on **many movable objects** in a shared scene. **Motion planning** is HPP's constraint-graph planner, driven through a plain-Python task API. **Task planning** is a declarative task plan compiled to **BehaviorTree.CPP**, for standalone, ROS-free mission execution (see *Task Planning* below).
|
|
54
|
+
|
|
55
|
+
## Capabilities
|
|
56
|
+
|
|
57
|
+
- **Long-horizon sequence planning.** `GraspSequencePlanner` chains an arbitrary number of grasp/place/hand-over phases, each with its own minimal phase-local constraint graph, so planning cost grows **linearly (O(N))** with the number of grasps instead of combinatorially (**O(N!)**).
|
|
58
|
+
- **Multiple robots & objects.** The scene composes several arms into one shared, mutually-collision-aware planning model — able to act independently, cooperate, or hand off objects — alongside any number of free-flying objects/tools, with grasp legality data-driven via `VALID_PAIRS` so adding one is a config change.
|
|
59
|
+
- **Reproducibility, introspection & crash recovery.** Crash-safe JSONL run logging plus a path-capture mechanism (`PathRecorder`) record every phase/edge/path so a run can be replayed, continuity-checked, and checkpointed/resumed rather than replanned from scratch.
|
|
60
|
+
- **Declarative task planning → BehaviorTree.CPP.** A versioned, capability-checked task plan (`tasks/task_planning/`) compiles deterministically to a BehaviorTree.CPP tree, run by a standalone C++ host through an embedded-CPython bridge with no ROS and no network hop (see *Task Planning* below).
|
|
61
|
+
- **Scene visualization.** Interactive 3D viewers: browser-based **viser** (default, no X11) or **gepetto-viewer** (Qt).
|
|
62
|
+
|
|
63
|
+
## Installation
|
|
64
|
+
|
|
65
|
+
`long_tamp` has two dependency tiers: a pure-Python tier, and the HPP native bindings
|
|
66
|
+
(`hpp-python`, `hpp-toppra`, `hpp-gepetto-viewer`) — C++ extension modules.
|
|
67
|
+
|
|
68
|
+
| Platform | Pure-Python tier (`pip install -e .`) | HPP native bindings |
|
|
69
|
+
|---|---|---|
|
|
70
|
+
| Linux x86_64/aarch64 | ✅ PyPI | ✅ PyPI — `pip install -e ".[hpp,toppra]"` |
|
|
71
|
+
| macOS | ✅ PyPI | ❌ no wheels (PyPI, conda-forge, robotpkg) — needs Docker/Linux |
|
|
72
|
+
| Windows | untested | untested — likely needs Docker/WSL2 |
|
|
73
|
+
|
|
74
|
+
On Linux, everything installs from PyPI in one command, no system packages or Docker
|
|
75
|
+
required. Elsewhere, the pure-Python tier still installs natively via pip, but the planner
|
|
76
|
+
itself needs a Linux environment for the native bindings — see
|
|
77
|
+
[`docs/INSTALL.md`](docs/INSTALL.md) for the robotpkg/source-build/Docker fallback, the
|
|
78
|
+
CMake install path, the NumPy ABI pitfall (robotpkg wants NumPy 1.x, the PyPI wheels want
|
|
79
|
+
NumPy 2.x — don't mix them), and runtime backend detection.
|
|
80
|
+
|
|
81
|
+
## Usage
|
|
82
|
+
|
|
83
|
+
Writing a task means implementing `ManipulationTask`'s lifecycle contract (`get_objects()`,
|
|
84
|
+
`create_constraints()`, `create_graph()`, `build_initial_config()`,
|
|
85
|
+
`generate_configurations()`, then `setup()` / `run()`) — either by hand, or, for new tasks,
|
|
86
|
+
via a declarative YAML config (recommended). Full, runnable examples live in
|
|
87
|
+
[`docs/usage/standalone-usage.md`](docs/usage/standalone-usage.md) §§4–6 rather than
|
|
88
|
+
duplicated here, alongside multi-phase sequences, resume/replay/checkpoints, and backend
|
|
89
|
+
selection.
|
|
90
|
+
|
|
91
|
+
- **Start from a template**: `script/templates/task_config_template.yaml` +
|
|
92
|
+
`task_my_task.py` — copy, fill in the `<PLACEHOLDER>`s, run.
|
|
93
|
+
- **Read a real, minimal example**: `script/twin/task_lift_ball.py` (bimanual scene).
|
|
94
|
+
|
|
95
|
+
## Package structure & architecture
|
|
96
|
+
|
|
97
|
+
`tasks/` orchestrates `planning/`, which is backend-agnostic and depends only on `backends/`
|
|
98
|
+
(the one place HPP-specific bindings are imported); `config/`, `logging/`, `visualization/`,
|
|
99
|
+
`utils/`, and `cli/` are horizontal support layers used from `tasks/` and `script/`.
|
|
100
|
+
|
|
101
|
+
```mermaid
|
|
102
|
+
flowchart TB
|
|
103
|
+
script["script/<br/>end-user task scripts<br/>(one per robot/mission)"]
|
|
104
|
+
tasks["tasks/<br/>ManipulationTask, GraspSequencePlanner,<br/>InteractiveGraspSequenceBuilder"]
|
|
105
|
+
planning["planning/<br/>SceneBuilder, ConstraintBuilder, GraphBuilder,<br/>ConfigGenerator, GraspStateTracker,<br/>SequentialConstraintGraphFactory,<br/>SequentialGraspFilter, path_io,<br/>path_recorder, path_replay"]
|
|
106
|
+
backends["backends/<br/>BackendBase (ABC) → PyHPPBackend<br/>only layer importing pyhpp.*"]
|
|
107
|
+
|
|
108
|
+
config["config/<br/>BaseTaskConfig, YamlTaskLoader"]
|
|
109
|
+
logging_["logging/<br/>RunLogger, JSONL event schema"]
|
|
110
|
+
viz["visualization/<br/>graph diagrams, frame display, video"]
|
|
111
|
+
utils["utils/<br/>transforms, interactive menus"]
|
|
112
|
+
cli["cli/<br/>argparse helpers, interactive pickers"]
|
|
113
|
+
|
|
114
|
+
script --> tasks
|
|
115
|
+
tasks --> planning
|
|
116
|
+
planning --> backends
|
|
117
|
+
|
|
118
|
+
tasks -.uses.-> config
|
|
119
|
+
tasks -.uses.-> logging_
|
|
120
|
+
tasks -.uses.-> viz
|
|
121
|
+
script -.uses.-> cli
|
|
122
|
+
cli -.uses.-> utils
|
|
123
|
+
config -.uses.-> utils
|
|
124
|
+
|
|
125
|
+
style backends fill:#4c566a,stroke:#2e3440,color:#fff
|
|
126
|
+
style planning fill:#5e81ac,stroke:#2e3440,color:#fff
|
|
127
|
+
style tasks fill:#81a1c1,stroke:#2e3440,color:#fff
|
|
128
|
+
style script fill:#88c0d0,stroke:#2e3440,color:#000
|
|
129
|
+
```
|
|
130
|
+
|
|
131
|
+
Per-phase planning data flow, the loop every mission ultimately runs through:
|
|
132
|
+
|
|
133
|
+
```mermaid
|
|
134
|
+
flowchart TD
|
|
135
|
+
yaml["YAML config"] -->|YamlTaskLoader| loaded["file_paths, joint_bounds_class, task_config"]
|
|
136
|
+
loaded --> setup["ManipulationTask.setup"]
|
|
137
|
+
|
|
138
|
+
setup --> scene["SceneBuilder<br/>load robots, env, objects"]
|
|
139
|
+
setup --> constraints["ConstraintBuilder /<br/>FactoryConstraintRegistry"]
|
|
140
|
+
setup --> gbuild["GraphBuilder<br/>factory or manual"]
|
|
141
|
+
|
|
142
|
+
scene --> plan["GraspSequencePlanner.plan_sequence"]
|
|
143
|
+
constraints --> plan
|
|
144
|
+
gbuild --> plan
|
|
145
|
+
|
|
146
|
+
plan --> p1["1. build_phase_graph<br/>GraphBuilder plus SequentialConstraintGraphFactory"]
|
|
147
|
+
p1 --> p2["2. GraspStateTracker picks the edge name"]
|
|
148
|
+
p2 --> p3["3. ConfigGenerator.generate_via_edge builds target config"]
|
|
149
|
+
p3 --> p4["4. backend.solve builds the path, then optimize and time-parameterize"]
|
|
150
|
+
p4 --> p5["5. RunLogger.log phase_end, optional auto-save of path"]
|
|
151
|
+
p5 -->|next phase| p1
|
|
152
|
+
p5 --> result["concatenated multi-phase path, O of N planning cost"]
|
|
153
|
+
```
|
|
154
|
+
|
|
155
|
+
Both diagrams are copied from **[`ARCHITECTURE.md`](ARCHITECTURE.md)**, which is the
|
|
156
|
+
maintained source — it's dated at the top and covers dependency direction and what each
|
|
157
|
+
class does in more depth than fits here. If the two ever disagree, trust `ARCHITECTURE.md`
|
|
158
|
+
and update this copy to match.
|
|
159
|
+
|
|
160
|
+
## Task Planning (BehaviorTree.CPP)
|
|
161
|
+
|
|
162
|
+
Alongside the plain-Python `ManipulationTask` API, `tasks/task_planning/` is a second,
|
|
163
|
+
declarative entry point: a versioned JSON **TaskPlan IR** (`sequence` / `fallback` / `retry` /
|
|
164
|
+
`condition` / `operation` / `transaction` nodes), validated against a `CapabilityRegistry`,
|
|
165
|
+
compiles deterministically to a **BehaviorTree.CPP** tree. A standalone C++ host
|
|
166
|
+
(`examples/behaviortree/`) runs that tree via an in-process, embedded-CPython bridge — one
|
|
167
|
+
process, no ROS, no network hop. It ships with built-in checkpoint/resume and path-capture
|
|
168
|
+
validation for long, restartable missions, and is the intended integration point for a future
|
|
169
|
+
model-proposed (VLM/LLM) plan.
|
|
170
|
+
|
|
171
|
+
| Stage | File |
|
|
172
|
+
|-------|------|
|
|
173
|
+
| IR validation & fingerprinting | `tasks/task_planning/model.py` (`TaskPlan`) |
|
|
174
|
+
| Capability policy | `tasks/task_planning/capabilities.py` (`CapabilityRegistry`) |
|
|
175
|
+
| IR → BT XML compiler | `tasks/task_planning/compiler.py` |
|
|
176
|
+
| C++ host + CPython bridge | `examples/behaviortree/` |
|
|
177
|
+
|
|
178
|
+
Build with `-DBUILD_BEHAVIORTREE_EXAMPLES=ON`. Full IR schema, the compiler's node mapping,
|
|
179
|
+
build/run steps, checkpointing, and how to add a mission or capability:
|
|
180
|
+
[`docs/usage/behaviortree-integration.md`](docs/usage/behaviortree-integration.md).
|
|
181
|
+
|
|
182
|
+
## Run Logging
|
|
183
|
+
|
|
184
|
+
`long_tamp` includes a structured run logger that writes a crash-safe JSONL event
|
|
185
|
+
stream for every planning run — one event per phase/edge attempt, plus a JSON snapshot and a
|
|
186
|
+
replay-ready YAML on close. Use it to replay configurations, debug failures, and audit
|
|
187
|
+
results.
|
|
188
|
+
|
|
189
|
+
Logging is **on by default** for every `ManipulationTask` (`log_dir="auto"` creates
|
|
190
|
+
`/tmp/long_tamp/<task_slug>_<timestamp>/`; pass an explicit path to redirect it, or
|
|
191
|
+
`None` to disable). `RunLogger` also works standalone, independent of `ManipulationTask`.
|
|
192
|
+
|
|
193
|
+
| Event | When emitted |
|
|
194
|
+
|-------|-------------|
|
|
195
|
+
| `run_start` | `ManipulationTask.__init__` (with `log_dir`) |
|
|
196
|
+
| `config_snapshot` | `setup()` — full `BaseTaskConfig` + setup params |
|
|
197
|
+
| `sequence_start` | Start of `plan_sequence()` — all call params + `q_init` |
|
|
198
|
+
| `phase_start` | Before each grasp phase — `gripper`, `handle`, `q_start` |
|
|
199
|
+
| `edge_start` | Before each transition edge attempt |
|
|
200
|
+
| `edge_end` | After each edge — `success`, timing, `q_to` or `error` |
|
|
201
|
+
| `phase_end` | After each phase — timing, `state_after`, saved files |
|
|
202
|
+
| `run_end` | On normal return or `KeyboardInterrupt` |
|
|
203
|
+
|
|
204
|
+
For runnable examples — standalone use, inspecting a log afterward
|
|
205
|
+
(`print_run_summary`/`load_run_log`/`get_replay_config`), and configuring the underlying
|
|
206
|
+
Python `logging` hierarchy — see [`docs/usage/standalone-usage.md`](docs/usage/standalone-usage.md) §10.
|
|
207
|
+
|
|
208
|
+
## Documentation
|
|
209
|
+
|
|
210
|
+
- **Installation**: [`docs/INSTALL.md`](docs/INSTALL.md) — pip (primary), robotpkg/source-build fallback, CMake install path, optional extras, backend detection.
|
|
211
|
+
- **Architecture**: [`ARCHITECTURE.md`](ARCHITECTURE.md) — module layering, dependency direction, data flow. Dated at the top; check it before trusting a claim about what exists.
|
|
212
|
+
- **Usage guide (living reference)**: [`docs/usage/standalone-usage.md`](docs/usage/standalone-usage.md) — writing a task, multi-phase sequences, resume/replay/checkpoints, backends, example scripts.
|
|
213
|
+
- **Development report**: [`docs/legacy/report/development-report.md`](docs/legacy/report/development-report.md) — *why* the framework is built this way: architecture decisions vs. bare HPP, measured before/after numbers, project timeline, and a bugs-found appendix. A point-in-time report, not a living reference.
|
|
214
|
+
- **Design rationale for specific mechanisms**: [`docs/features/`](docs/features/); **upstream HPP defects worked around here**: [`docs/bugs/`](docs/bugs/).
|
|
215
|
+
- **API Reference**: See docstrings in source files.
|
|
216
|
+
- **ROS-free BehaviorTree.CPP integration**: [`docs/usage/behaviortree-integration.md`](docs/usage/behaviortree-integration.md).
|
|
217
|
+
|
|
218
|
+
## License
|
|
219
|
+
|
|
220
|
+
MIT - See [LICENSE](LICENSE) file
|
|
221
|
+
|
|
222
|
+
|
|
223
|
+
---
|
|
224
|
+
|
|
225
|
+
**Last Updated**: 2026-09-02
|
|
@@ -0,0 +1,177 @@
|
|
|
1
|
+
# Long-TAMP - Long-Horizon Task-and-Motion Planning
|
|
2
|
+
|
|
3
|
+
Long-horizon, multi-arm task-and-motion planning (TAMP) for manipulation, built on HPP (Humanoid Path Planner).
|
|
4
|
+
|
|
5
|
+
`long_tamp` plans **long, multi-step manipulation sequences** for **several robot arms** on **many movable objects** in a shared scene. **Motion planning** is HPP's constraint-graph planner, driven through a plain-Python task API. **Task planning** is a declarative task plan compiled to **BehaviorTree.CPP**, for standalone, ROS-free mission execution (see *Task Planning* below).
|
|
6
|
+
|
|
7
|
+
## Capabilities
|
|
8
|
+
|
|
9
|
+
- **Long-horizon sequence planning.** `GraspSequencePlanner` chains an arbitrary number of grasp/place/hand-over phases, each with its own minimal phase-local constraint graph, so planning cost grows **linearly (O(N))** with the number of grasps instead of combinatorially (**O(N!)**).
|
|
10
|
+
- **Multiple robots & objects.** The scene composes several arms into one shared, mutually-collision-aware planning model — able to act independently, cooperate, or hand off objects — alongside any number of free-flying objects/tools, with grasp legality data-driven via `VALID_PAIRS` so adding one is a config change.
|
|
11
|
+
- **Reproducibility, introspection & crash recovery.** Crash-safe JSONL run logging plus a path-capture mechanism (`PathRecorder`) record every phase/edge/path so a run can be replayed, continuity-checked, and checkpointed/resumed rather than replanned from scratch.
|
|
12
|
+
- **Declarative task planning → BehaviorTree.CPP.** A versioned, capability-checked task plan (`tasks/task_planning/`) compiles deterministically to a BehaviorTree.CPP tree, run by a standalone C++ host through an embedded-CPython bridge with no ROS and no network hop (see *Task Planning* below).
|
|
13
|
+
- **Scene visualization.** Interactive 3D viewers: browser-based **viser** (default, no X11) or **gepetto-viewer** (Qt).
|
|
14
|
+
|
|
15
|
+
## Installation
|
|
16
|
+
|
|
17
|
+
`long_tamp` has two dependency tiers: a pure-Python tier, and the HPP native bindings
|
|
18
|
+
(`hpp-python`, `hpp-toppra`, `hpp-gepetto-viewer`) — C++ extension modules.
|
|
19
|
+
|
|
20
|
+
| Platform | Pure-Python tier (`pip install -e .`) | HPP native bindings |
|
|
21
|
+
|---|---|---|
|
|
22
|
+
| Linux x86_64/aarch64 | ✅ PyPI | ✅ PyPI — `pip install -e ".[hpp,toppra]"` |
|
|
23
|
+
| macOS | ✅ PyPI | ❌ no wheels (PyPI, conda-forge, robotpkg) — needs Docker/Linux |
|
|
24
|
+
| Windows | untested | untested — likely needs Docker/WSL2 |
|
|
25
|
+
|
|
26
|
+
On Linux, everything installs from PyPI in one command, no system packages or Docker
|
|
27
|
+
required. Elsewhere, the pure-Python tier still installs natively via pip, but the planner
|
|
28
|
+
itself needs a Linux environment for the native bindings — see
|
|
29
|
+
[`docs/INSTALL.md`](docs/INSTALL.md) for the robotpkg/source-build/Docker fallback, the
|
|
30
|
+
CMake install path, the NumPy ABI pitfall (robotpkg wants NumPy 1.x, the PyPI wheels want
|
|
31
|
+
NumPy 2.x — don't mix them), and runtime backend detection.
|
|
32
|
+
|
|
33
|
+
## Usage
|
|
34
|
+
|
|
35
|
+
Writing a task means implementing `ManipulationTask`'s lifecycle contract (`get_objects()`,
|
|
36
|
+
`create_constraints()`, `create_graph()`, `build_initial_config()`,
|
|
37
|
+
`generate_configurations()`, then `setup()` / `run()`) — either by hand, or, for new tasks,
|
|
38
|
+
via a declarative YAML config (recommended). Full, runnable examples live in
|
|
39
|
+
[`docs/usage/standalone-usage.md`](docs/usage/standalone-usage.md) §§4–6 rather than
|
|
40
|
+
duplicated here, alongside multi-phase sequences, resume/replay/checkpoints, and backend
|
|
41
|
+
selection.
|
|
42
|
+
|
|
43
|
+
- **Start from a template**: `script/templates/task_config_template.yaml` +
|
|
44
|
+
`task_my_task.py` — copy, fill in the `<PLACEHOLDER>`s, run.
|
|
45
|
+
- **Read a real, minimal example**: `script/twin/task_lift_ball.py` (bimanual scene).
|
|
46
|
+
|
|
47
|
+
## Package structure & architecture
|
|
48
|
+
|
|
49
|
+
`tasks/` orchestrates `planning/`, which is backend-agnostic and depends only on `backends/`
|
|
50
|
+
(the one place HPP-specific bindings are imported); `config/`, `logging/`, `visualization/`,
|
|
51
|
+
`utils/`, and `cli/` are horizontal support layers used from `tasks/` and `script/`.
|
|
52
|
+
|
|
53
|
+
```mermaid
|
|
54
|
+
flowchart TB
|
|
55
|
+
script["script/<br/>end-user task scripts<br/>(one per robot/mission)"]
|
|
56
|
+
tasks["tasks/<br/>ManipulationTask, GraspSequencePlanner,<br/>InteractiveGraspSequenceBuilder"]
|
|
57
|
+
planning["planning/<br/>SceneBuilder, ConstraintBuilder, GraphBuilder,<br/>ConfigGenerator, GraspStateTracker,<br/>SequentialConstraintGraphFactory,<br/>SequentialGraspFilter, path_io,<br/>path_recorder, path_replay"]
|
|
58
|
+
backends["backends/<br/>BackendBase (ABC) → PyHPPBackend<br/>only layer importing pyhpp.*"]
|
|
59
|
+
|
|
60
|
+
config["config/<br/>BaseTaskConfig, YamlTaskLoader"]
|
|
61
|
+
logging_["logging/<br/>RunLogger, JSONL event schema"]
|
|
62
|
+
viz["visualization/<br/>graph diagrams, frame display, video"]
|
|
63
|
+
utils["utils/<br/>transforms, interactive menus"]
|
|
64
|
+
cli["cli/<br/>argparse helpers, interactive pickers"]
|
|
65
|
+
|
|
66
|
+
script --> tasks
|
|
67
|
+
tasks --> planning
|
|
68
|
+
planning --> backends
|
|
69
|
+
|
|
70
|
+
tasks -.uses.-> config
|
|
71
|
+
tasks -.uses.-> logging_
|
|
72
|
+
tasks -.uses.-> viz
|
|
73
|
+
script -.uses.-> cli
|
|
74
|
+
cli -.uses.-> utils
|
|
75
|
+
config -.uses.-> utils
|
|
76
|
+
|
|
77
|
+
style backends fill:#4c566a,stroke:#2e3440,color:#fff
|
|
78
|
+
style planning fill:#5e81ac,stroke:#2e3440,color:#fff
|
|
79
|
+
style tasks fill:#81a1c1,stroke:#2e3440,color:#fff
|
|
80
|
+
style script fill:#88c0d0,stroke:#2e3440,color:#000
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
Per-phase planning data flow, the loop every mission ultimately runs through:
|
|
84
|
+
|
|
85
|
+
```mermaid
|
|
86
|
+
flowchart TD
|
|
87
|
+
yaml["YAML config"] -->|YamlTaskLoader| loaded["file_paths, joint_bounds_class, task_config"]
|
|
88
|
+
loaded --> setup["ManipulationTask.setup"]
|
|
89
|
+
|
|
90
|
+
setup --> scene["SceneBuilder<br/>load robots, env, objects"]
|
|
91
|
+
setup --> constraints["ConstraintBuilder /<br/>FactoryConstraintRegistry"]
|
|
92
|
+
setup --> gbuild["GraphBuilder<br/>factory or manual"]
|
|
93
|
+
|
|
94
|
+
scene --> plan["GraspSequencePlanner.plan_sequence"]
|
|
95
|
+
constraints --> plan
|
|
96
|
+
gbuild --> plan
|
|
97
|
+
|
|
98
|
+
plan --> p1["1. build_phase_graph<br/>GraphBuilder plus SequentialConstraintGraphFactory"]
|
|
99
|
+
p1 --> p2["2. GraspStateTracker picks the edge name"]
|
|
100
|
+
p2 --> p3["3. ConfigGenerator.generate_via_edge builds target config"]
|
|
101
|
+
p3 --> p4["4. backend.solve builds the path, then optimize and time-parameterize"]
|
|
102
|
+
p4 --> p5["5. RunLogger.log phase_end, optional auto-save of path"]
|
|
103
|
+
p5 -->|next phase| p1
|
|
104
|
+
p5 --> result["concatenated multi-phase path, O of N planning cost"]
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
Both diagrams are copied from **[`ARCHITECTURE.md`](ARCHITECTURE.md)**, which is the
|
|
108
|
+
maintained source — it's dated at the top and covers dependency direction and what each
|
|
109
|
+
class does in more depth than fits here. If the two ever disagree, trust `ARCHITECTURE.md`
|
|
110
|
+
and update this copy to match.
|
|
111
|
+
|
|
112
|
+
## Task Planning (BehaviorTree.CPP)
|
|
113
|
+
|
|
114
|
+
Alongside the plain-Python `ManipulationTask` API, `tasks/task_planning/` is a second,
|
|
115
|
+
declarative entry point: a versioned JSON **TaskPlan IR** (`sequence` / `fallback` / `retry` /
|
|
116
|
+
`condition` / `operation` / `transaction` nodes), validated against a `CapabilityRegistry`,
|
|
117
|
+
compiles deterministically to a **BehaviorTree.CPP** tree. A standalone C++ host
|
|
118
|
+
(`examples/behaviortree/`) runs that tree via an in-process, embedded-CPython bridge — one
|
|
119
|
+
process, no ROS, no network hop. It ships with built-in checkpoint/resume and path-capture
|
|
120
|
+
validation for long, restartable missions, and is the intended integration point for a future
|
|
121
|
+
model-proposed (VLM/LLM) plan.
|
|
122
|
+
|
|
123
|
+
| Stage | File |
|
|
124
|
+
|-------|------|
|
|
125
|
+
| IR validation & fingerprinting | `tasks/task_planning/model.py` (`TaskPlan`) |
|
|
126
|
+
| Capability policy | `tasks/task_planning/capabilities.py` (`CapabilityRegistry`) |
|
|
127
|
+
| IR → BT XML compiler | `tasks/task_planning/compiler.py` |
|
|
128
|
+
| C++ host + CPython bridge | `examples/behaviortree/` |
|
|
129
|
+
|
|
130
|
+
Build with `-DBUILD_BEHAVIORTREE_EXAMPLES=ON`. Full IR schema, the compiler's node mapping,
|
|
131
|
+
build/run steps, checkpointing, and how to add a mission or capability:
|
|
132
|
+
[`docs/usage/behaviortree-integration.md`](docs/usage/behaviortree-integration.md).
|
|
133
|
+
|
|
134
|
+
## Run Logging
|
|
135
|
+
|
|
136
|
+
`long_tamp` includes a structured run logger that writes a crash-safe JSONL event
|
|
137
|
+
stream for every planning run — one event per phase/edge attempt, plus a JSON snapshot and a
|
|
138
|
+
replay-ready YAML on close. Use it to replay configurations, debug failures, and audit
|
|
139
|
+
results.
|
|
140
|
+
|
|
141
|
+
Logging is **on by default** for every `ManipulationTask` (`log_dir="auto"` creates
|
|
142
|
+
`/tmp/long_tamp/<task_slug>_<timestamp>/`; pass an explicit path to redirect it, or
|
|
143
|
+
`None` to disable). `RunLogger` also works standalone, independent of `ManipulationTask`.
|
|
144
|
+
|
|
145
|
+
| Event | When emitted |
|
|
146
|
+
|-------|-------------|
|
|
147
|
+
| `run_start` | `ManipulationTask.__init__` (with `log_dir`) |
|
|
148
|
+
| `config_snapshot` | `setup()` — full `BaseTaskConfig` + setup params |
|
|
149
|
+
| `sequence_start` | Start of `plan_sequence()` — all call params + `q_init` |
|
|
150
|
+
| `phase_start` | Before each grasp phase — `gripper`, `handle`, `q_start` |
|
|
151
|
+
| `edge_start` | Before each transition edge attempt |
|
|
152
|
+
| `edge_end` | After each edge — `success`, timing, `q_to` or `error` |
|
|
153
|
+
| `phase_end` | After each phase — timing, `state_after`, saved files |
|
|
154
|
+
| `run_end` | On normal return or `KeyboardInterrupt` |
|
|
155
|
+
|
|
156
|
+
For runnable examples — standalone use, inspecting a log afterward
|
|
157
|
+
(`print_run_summary`/`load_run_log`/`get_replay_config`), and configuring the underlying
|
|
158
|
+
Python `logging` hierarchy — see [`docs/usage/standalone-usage.md`](docs/usage/standalone-usage.md) §10.
|
|
159
|
+
|
|
160
|
+
## Documentation
|
|
161
|
+
|
|
162
|
+
- **Installation**: [`docs/INSTALL.md`](docs/INSTALL.md) — pip (primary), robotpkg/source-build fallback, CMake install path, optional extras, backend detection.
|
|
163
|
+
- **Architecture**: [`ARCHITECTURE.md`](ARCHITECTURE.md) — module layering, dependency direction, data flow. Dated at the top; check it before trusting a claim about what exists.
|
|
164
|
+
- **Usage guide (living reference)**: [`docs/usage/standalone-usage.md`](docs/usage/standalone-usage.md) — writing a task, multi-phase sequences, resume/replay/checkpoints, backends, example scripts.
|
|
165
|
+
- **Development report**: [`docs/legacy/report/development-report.md`](docs/legacy/report/development-report.md) — *why* the framework is built this way: architecture decisions vs. bare HPP, measured before/after numbers, project timeline, and a bugs-found appendix. A point-in-time report, not a living reference.
|
|
166
|
+
- **Design rationale for specific mechanisms**: [`docs/features/`](docs/features/); **upstream HPP defects worked around here**: [`docs/bugs/`](docs/bugs/).
|
|
167
|
+
- **API Reference**: See docstrings in source files.
|
|
168
|
+
- **ROS-free BehaviorTree.CPP integration**: [`docs/usage/behaviortree-integration.md`](docs/usage/behaviortree-integration.md).
|
|
169
|
+
|
|
170
|
+
## License
|
|
171
|
+
|
|
172
|
+
MIT - See [LICENSE](LICENSE) file
|
|
173
|
+
|
|
174
|
+
|
|
175
|
+
---
|
|
176
|
+
|
|
177
|
+
**Last Updated**: 2026-09-02
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
[build-system]
|
|
2
|
+
requires = ["setuptools>=45", "wheel"]
|
|
3
|
+
build-backend = "setuptools.build_meta"
|
|
4
|
+
|
|
5
|
+
[project]
|
|
6
|
+
name = "long-tamp"
|
|
7
|
+
version = "0.1.0"
|
|
8
|
+
description = "Long-TAMP - Manipulation Planning Framework"
|
|
9
|
+
readme = "README.md"
|
|
10
|
+
requires-python = ">=3.10"
|
|
11
|
+
license = {text = "MIT"}
|
|
12
|
+
authors = [
|
|
13
|
+
{name = "Thanh Nguyen", email = "dvtnguyen@laas.fr"}
|
|
14
|
+
]
|
|
15
|
+
maintainers = [
|
|
16
|
+
{name = "Thanh Nguyen", email = "dvtnguyen@laas.fr"}
|
|
17
|
+
]
|
|
18
|
+
keywords = ["robotics", "manipulation", "motion-planning", "hpp", "agimus"]
|
|
19
|
+
classifiers = [
|
|
20
|
+
"Development Status :: 3 - Alpha",
|
|
21
|
+
"Intended Audience :: Science/Research",
|
|
22
|
+
"License :: OSI Approved :: MIT License",
|
|
23
|
+
"Programming Language :: Python :: 3",
|
|
24
|
+
"Programming Language :: Python :: 3.10",
|
|
25
|
+
"Programming Language :: Python :: 3.11",
|
|
26
|
+
"Topic :: Scientific/Engineering",
|
|
27
|
+
]
|
|
28
|
+
|
|
29
|
+
# Hard runtime deps.
|
|
30
|
+
# numpy / pyyaml — imported unguarded in core modules (numpy, yaml_loader,
|
|
31
|
+
# utils/transforms).
|
|
32
|
+
# pin (pinocchio) — imported unguarded at module scope in utils/transforms.py
|
|
33
|
+
# (SE3, Quaternion, rpyToMatrix are used directly by its
|
|
34
|
+
# functions, not just for type hints), which every task
|
|
35
|
+
# config transitively imports. `import long_tamp` does not
|
|
36
|
+
# work without it — it is not actually optional.
|
|
37
|
+
# viser / trimesh / pycollada — the browser viewer (pyhpp_viser) is the
|
|
38
|
+
# default viewer, so its PyPI-side deps ship by default. The
|
|
39
|
+
# pyhpp_viser bindings themselves come from hpp-gepetto-viewer
|
|
40
|
+
# (see the [hpp] extra below).
|
|
41
|
+
dependencies = [
|
|
42
|
+
# No upper bound: the PyPI-native HPP stack (see [hpp] extra) is a cmeel
|
|
43
|
+
# build — cmeel-boost (a transitive dep of hpp-python) requires numpy>=2.
|
|
44
|
+
# A robotpkg/source-built HPP environment (see docs/INSTALL.md) is instead
|
|
45
|
+
# compiled against NumPy 1.x — install there with `pip install --no-deps
|
|
46
|
+
# -e .` so this constraint (and the `pin` one below) never gets a chance
|
|
47
|
+
# to pull in a PyPI NumPy 2.x / pinocchio that collides with it.
|
|
48
|
+
"numpy>=1.26",
|
|
49
|
+
"pyyaml>=5.1",
|
|
50
|
+
"pin>=2.6",
|
|
51
|
+
"viser",
|
|
52
|
+
"trimesh",
|
|
53
|
+
"pycollada",
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
[project.optional-dependencies]
|
|
57
|
+
# The full native HPP stack, prebuilt (cmeel) wheels from PyPI — no robotpkg,
|
|
58
|
+
# no source build, no Docker. Linux only today (manylinux_2_28, x86_64/aarch64),
|
|
59
|
+
# Python 3.10-3.14 — see docs/INSTALL.md for the current platform matrix and
|
|
60
|
+
# the robotpkg/source-build fallback for unsupported platforms.
|
|
61
|
+
hpp = [
|
|
62
|
+
"hpp-python>=9.0.2",
|
|
63
|
+
"hpp-gepetto-viewer>=9.0.2",
|
|
64
|
+
]
|
|
65
|
+
|
|
66
|
+
# TOPPRA time-parameterization (optional optimizer). Also a real PyPI (cmeel)
|
|
67
|
+
# wheel now — see docs/INSTALL.md.
|
|
68
|
+
toppra = [
|
|
69
|
+
"hpp-toppra>=9.0.2",
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
dev = [
|
|
73
|
+
"pytest>=6.0",
|
|
74
|
+
"pytest-cov",
|
|
75
|
+
"black",
|
|
76
|
+
"ruff",
|
|
77
|
+
"sphinx",
|
|
78
|
+
"sphinx-rtd-theme",
|
|
79
|
+
]
|
|
80
|
+
|
|
81
|
+
# MkDocs site over docs/ — `mkdocs serve` / `mkdocs build` (see mkdocs.yml).
|
|
82
|
+
docs = [
|
|
83
|
+
"mkdocs>=1.6",
|
|
84
|
+
"mkdocs-material>=9.5",
|
|
85
|
+
"mkdocs-include-markdown-plugin>=7.0",
|
|
86
|
+
]
|
|
87
|
+
|
|
88
|
+
all = [
|
|
89
|
+
"long-tamp[dev,docs]",
|
|
90
|
+
]
|
|
91
|
+
|
|
92
|
+
[project.urls]
|
|
93
|
+
Homepage = "https://github.com/thanhndv212/long-tamp"
|
|
94
|
+
Documentation = "https://long-tamp.readthedocs.io"
|
|
95
|
+
Repository = "https://github.com/thanhndv212/long-tamp"
|
|
96
|
+
Issues = "https://github.com/thanhndv212/long-tamp/issues"
|
|
97
|
+
|
|
98
|
+
[tool.setuptools.packages.find]
|
|
99
|
+
where = ["src"]
|
|
100
|
+
|
|
101
|
+
[tool.setuptools.package-data]
|
|
102
|
+
long_tamp = ["py.typed"]
|
|
103
|
+
|
|
104
|
+
[tool.ruff]
|
|
105
|
+
extend-exclude = ["cmake"]
|
|
106
|
+
line-length = 88
|
|
107
|
+
|
|
108
|
+
[tool.ruff.lint]
|
|
109
|
+
extend-select = ["I", "NPY", "RUF", "UP", "W"]
|
|
110
|
+
|
|
111
|
+
[tool.pytest.ini_options]
|
|
112
|
+
testpaths = ["tests"]
|
|
113
|
+
markers = ["slow_planning: real-scene planning checks run nightly in isolated processes"]
|
|
114
|
+
python_files = "test_*.py"
|
|
115
|
+
python_classes = "Test*"
|
|
116
|
+
python_functions = "test_*"
|
|
117
|
+
addopts = "-v --cov=long_tamp --cov-report=html --cov-report=term"
|
|
118
|
+
|
|
119
|
+
[tool.black]
|
|
120
|
+
line-length = 88
|
|
121
|
+
target-version = ['py310']
|
|
122
|
+
extend-exclude = '''
|
|
123
|
+
/(
|
|
124
|
+
| cmake
|
|
125
|
+
)/
|
|
126
|
+
'''
|