sstsr 2.0.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- sstsr-2.0.0.dist-info/METADATA +318 -0
- sstsr-2.0.0.dist-info/RECORD +31 -0
- sstsr-2.0.0.dist-info/WHEEL +4 -0
- sstsr-2.0.0.dist-info/licenses/LICENSE +24 -0
- tsr/__init__.py +104 -0
- tsr/core/__init__.py +35 -0
- tsr/core/tsr.py +550 -0
- tsr/core/tsr_chain.py +249 -0
- tsr/core/utils.py +108 -0
- tsr/hands/__init__.py +30 -0
- tsr/hands/base.py +652 -0
- tsr/hands/parallel_jaw.py +1302 -0
- tsr/hands/registry.py +92 -0
- tsr/io.py +99 -0
- tsr/placement/__init__.py +20 -0
- tsr/placement/_stable_poses.py +166 -0
- tsr/placement/stable_placer.py +309 -0
- tsr/sampling.py +251 -0
- tsr/template.py +157 -0
- tsr/templates/README.md +60 -0
- tsr/templates/grasps/mug_handle_grasp.yaml +54 -0
- tsr/templates/grasps/screwdriver_grasp.yaml +54 -0
- tsr/templates/places/mug_on_table.yaml +52 -0
- tsr/templates/places/toolchest_drop.yaml +55 -0
- tsr/templates/tasks/drive_screw.yaml +55 -0
- tsr/templates/tasks/mug_pour_into_sink.yaml +55 -0
- tsr/templates/tasks/mug_transport_upright.yaml +55 -0
- tsr/tsr.py +12 -0
- tsr/tsr_chain.py +12 -0
- tsr/utils.py +24 -0
- tsr/viz.py +685 -0
|
@@ -0,0 +1,318 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: sstsr
|
|
3
|
+
Version: 2.0.0
|
|
4
|
+
Summary: Task Space Regions for grasp and placement planning (import as `tsr`)
|
|
5
|
+
Project-URL: Homepage, https://github.com/personalrobotics/tsr
|
|
6
|
+
Project-URL: Repository, https://github.com/personalrobotics/tsr
|
|
7
|
+
Project-URL: Issues, https://github.com/personalrobotics/tsr/issues
|
|
8
|
+
Author-email: Siddhartha Srinivasa <siddhartha.srinivasa@gmail.com>
|
|
9
|
+
Maintainer-email: Siddhartha Srinivasa <siddhartha.srinivasa@gmail.com>
|
|
10
|
+
License-Expression: BSD-2-Clause
|
|
11
|
+
License-File: LICENSE
|
|
12
|
+
Keywords: motion-planning,robotics,task-space-regions,tsr
|
|
13
|
+
Classifier: Development Status :: 4 - Beta
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: Intended Audience :: Science/Research
|
|
16
|
+
Classifier: License :: OSI Approved :: BSD License
|
|
17
|
+
Classifier: Operating System :: OS Independent
|
|
18
|
+
Classifier: Programming Language :: Python :: 3
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
22
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
23
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
24
|
+
Classifier: Topic :: Scientific/Engineering
|
|
25
|
+
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
|
26
|
+
Requires-Python: >=3.10
|
|
27
|
+
Requires-Dist: numpy>=1.24.0
|
|
28
|
+
Requires-Dist: pyyaml>=6.0.1
|
|
29
|
+
Requires-Dist: scipy>=1.10.0
|
|
30
|
+
Provides-Extra: test
|
|
31
|
+
Requires-Dist: build>=1.0.0; extra == 'test'
|
|
32
|
+
Requires-Dist: hypothesis>=6.112; extra == 'test'
|
|
33
|
+
Requires-Dist: pytest-cov>=4.0.0; extra == 'test'
|
|
34
|
+
Requires-Dist: pytest>=7.0.0; extra == 'test'
|
|
35
|
+
Provides-Extra: viz
|
|
36
|
+
Requires-Dist: matplotlib>=3.8.0; extra == 'viz'
|
|
37
|
+
Requires-Dist: pillow>=10.3.0; extra == 'viz'
|
|
38
|
+
Requires-Dist: pyvista>=0.43.0; extra == 'viz'
|
|
39
|
+
Description-Content-Type: text/markdown
|
|
40
|
+
|
|
41
|
+
# Task Space Regions (TSR)
|
|
42
|
+
|
|
43
|
+
A Python library for pose-constrained manipulation planning using Task Space Regions.
|
|
44
|
+
|
|
45
|
+
TSRs encode *any* manipulation constraint as a bounded region in SE(3): grasping,
|
|
46
|
+
placing, transporting, pouring, tool use, and more. A planner samples from a TSR
|
|
47
|
+
to get valid end-effector poses satisfying the constraint.
|
|
48
|
+
|
|
49
|
+
Based on the IJRR paper ["Task Space Regions: A Framework for Pose-Constrained Manipulation Planning"](https://www.ri.cmu.edu/pub_files/2011/10/dmitry_ijrr10-1.pdf) by Berenson, Srinivasa, and Kuffner.
|
|
50
|
+
|
|
51
|
+
## Gallery
|
|
52
|
+
|
|
53
|
+
### Grasps
|
|
54
|
+
|
|
55
|
+

|
|
56
|
+
|
|
57
|
+
### Stable placements
|
|
58
|
+
|
|
59
|
+

|
|
60
|
+
|
|
61
|
+
*Cylinder, box, sphere, and torus in every stable pose on a table surface.*
|
|
62
|
+
|
|
63
|
+

|
|
64
|
+
|
|
65
|
+
*L-shape, T-shape, and a mug (cylinder + handle) — `place_mesh` applied to arbitrary vertex clouds. Each object is shown in all stable orientations above the 5° margin threshold.*
|
|
66
|
+
|
|
67
|
+
## Installation
|
|
68
|
+
|
|
69
|
+
The distribution is named **`sstsr`** on PyPI; the import name is `tsr`.
|
|
70
|
+
|
|
71
|
+
```bash
|
|
72
|
+
pip install sstsr # or: uv add sstsr
|
|
73
|
+
```
|
|
74
|
+
```python
|
|
75
|
+
import tsr # the import name is unchanged
|
|
76
|
+
```
|
|
77
|
+
|
|
78
|
+
For visualization support:
|
|
79
|
+
```bash
|
|
80
|
+
pip install "sstsr[viz]" # or: uv add "sstsr[viz]"
|
|
81
|
+
```
|
|
82
|
+
|
|
83
|
+
For development:
|
|
84
|
+
```bash
|
|
85
|
+
git clone https://github.com/personalrobotics/tsr.git
|
|
86
|
+
cd tsr
|
|
87
|
+
uv sync --extra test
|
|
88
|
+
```
|
|
89
|
+
|
|
90
|
+
## Quick Start
|
|
91
|
+
|
|
92
|
+
### Load templates for a full manipulation task
|
|
93
|
+
|
|
94
|
+
Templates are YAML files that encode pose constraints for each step of a task.
|
|
95
|
+
The library ships with two narratives:
|
|
96
|
+
|
|
97
|
+
```python
|
|
98
|
+
from tsr import load_package_template
|
|
99
|
+
import numpy as np
|
|
100
|
+
|
|
101
|
+
# --- Tool use: screwdriver ---
|
|
102
|
+
grasp = load_package_template("grasps", "screwdriver_grasp.yaml")
|
|
103
|
+
drive = load_package_template("tasks", "drive_screw.yaml")
|
|
104
|
+
drop = load_package_template("places", "toolchest_drop.yaml")
|
|
105
|
+
|
|
106
|
+
screwdriver_pose = np.eye(4)
|
|
107
|
+
screwdriver_pose[:3, 3] = [0.4, 0.1, 0.02]
|
|
108
|
+
|
|
109
|
+
gripper_poses = grasp.sample(screwdriver_pose)
|
|
110
|
+
|
|
111
|
+
# --- Everyday manipulation: mug of water ---
|
|
112
|
+
pick = load_package_template("grasps", "mug_handle_grasp.yaml")
|
|
113
|
+
carry = load_package_template("tasks", "mug_transport_upright.yaml")
|
|
114
|
+
pour = load_package_template("tasks", "mug_pour_into_sink.yaml")
|
|
115
|
+
place = load_package_template("places", "mug_on_table.yaml")
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
### Generate templates from object geometry
|
|
119
|
+
|
|
120
|
+
#### Grasping
|
|
121
|
+
|
|
122
|
+
`ParallelJawGripper` generates TSR templates directly from shape parameters.
|
|
123
|
+
Pre-configured subclasses are provided for common grippers:
|
|
124
|
+
|
|
125
|
+
| Class | `finger_length` | `max_aperture` | Notes |
|
|
126
|
+
|---|---|---|---|
|
|
127
|
+
| `Robotiq2F140` | 55 mm | 140 mm | Robotiq 2F-140 parallel gripper |
|
|
128
|
+
| `FrankaHand` | 44.5 mm | 80 mm | Franka Emika Panda hand |
|
|
129
|
+
|
|
130
|
+
```python
|
|
131
|
+
import numpy as np
|
|
132
|
+
from tsr.hands import ParallelJawGripper, Robotiq2F140, FrankaHand
|
|
133
|
+
|
|
134
|
+
# Use a pre-configured gripper for a known hardware platform
|
|
135
|
+
gripper = Robotiq2F140()
|
|
136
|
+
gripper = FrankaHand()
|
|
137
|
+
|
|
138
|
+
# Or configure manually for custom hardware
|
|
139
|
+
gripper = ParallelJawGripper(finger_length=0.055, max_aperture=0.140)
|
|
140
|
+
|
|
141
|
+
# Cylinder — side + top + bottom: 4*k templates (default k=3: 12 total)
|
|
142
|
+
templates = gripper.grasp_cylinder(
|
|
143
|
+
cylinder_radius=0.040, # 4 cm radius
|
|
144
|
+
cylinder_height=0.120, # 12 cm tall
|
|
145
|
+
reference="mug",
|
|
146
|
+
)
|
|
147
|
+
|
|
148
|
+
# Box — all six faces, two finger orientations per face: up to 2*6*k templates
|
|
149
|
+
templates = gripper.grasp_box(box_x=0.08, box_y=0.06, box_z=0.18, reference="box")
|
|
150
|
+
|
|
151
|
+
# Sphere — full SO(3) approach: k templates
|
|
152
|
+
templates = gripper.grasp_sphere(object_radius=0.040, reference="ball")
|
|
153
|
+
|
|
154
|
+
# Torus — side (all minor angles) + span (if aperture allows)
|
|
155
|
+
templates = gripper.grasp_torus(
|
|
156
|
+
torus_radius=0.035, # major radius R: center to tube center
|
|
157
|
+
tube_radius=0.015, # minor radius r: tube cross-section
|
|
158
|
+
reference="handle",
|
|
159
|
+
)
|
|
160
|
+
|
|
161
|
+
# Instantiate at a specific object pose and sample
|
|
162
|
+
mug_pose = np.eye(4)
|
|
163
|
+
mug_pose[:3, 3] = [0.5, 0.0, 0.0] # mug at x=0.5m
|
|
164
|
+
|
|
165
|
+
grasp_poses = [t.sample(mug_pose) for t in templates]
|
|
166
|
+
```
|
|
167
|
+
|
|
168
|
+
#### Placing
|
|
169
|
+
|
|
170
|
+
`StablePlacer` generates one TSR template per stable resting pose on a flat surface:
|
|
171
|
+
|
|
172
|
+
```python
|
|
173
|
+
import numpy as np
|
|
174
|
+
from tsr.placement import StablePlacer
|
|
175
|
+
|
|
176
|
+
placer = StablePlacer(table_x=0.60, table_y=0.40)
|
|
177
|
+
|
|
178
|
+
# Analytic primitives
|
|
179
|
+
templates = placer.place_cylinder(cylinder_radius=0.040, cylinder_height=0.120, subject="mug")
|
|
180
|
+
templates = placer.place_box(lx=0.08, ly=0.06, lz=0.18, subject="box") # up to 3 poses
|
|
181
|
+
templates = placer.place_sphere(radius=0.040, subject="ball")
|
|
182
|
+
templates = placer.place_torus(major_radius=0.035, minor_radius=0.015, subject="ring")
|
|
183
|
+
|
|
184
|
+
# Arbitrary mesh — pass any (N, 3) vertex cloud + centre of mass
|
|
185
|
+
vertices = np.array([...]) # (N, 3) points
|
|
186
|
+
com = np.array([cx, cy, cz])
|
|
187
|
+
templates = placer.place_mesh(vertices, com, subject="widget",
|
|
188
|
+
min_margin_deg=5.0) # discard marginal poses
|
|
189
|
+
|
|
190
|
+
# Each template encodes one stable orientation; sample a table pose for it
|
|
191
|
+
table_pose = np.eye(4)
|
|
192
|
+
table_pose[2, 3] = 0.75 # table surface at z = 0.75 m
|
|
193
|
+
|
|
194
|
+
for t in templates:
|
|
195
|
+
pose = t.sample(table_pose)
|
|
196
|
+
print(t, "→ COM z =", pose[2, 3])
|
|
197
|
+
```
|
|
198
|
+
|
|
199
|
+
Stability is determined by the COM-projection criterion: a face is stable if the
|
|
200
|
+
centre of mass projects inside the support polygon formed by that face's contact
|
|
201
|
+
region. The stability margin is `arctan(d_min / h_com)` where `d_min` is the
|
|
202
|
+
minimum distance from the COM projection to any edge of the polygon.
|
|
203
|
+
|
|
204
|
+
### Work directly with TSRs
|
|
205
|
+
|
|
206
|
+
```python
|
|
207
|
+
from tsr import TSR
|
|
208
|
+
import numpy as np
|
|
209
|
+
|
|
210
|
+
# A TSR is defined by three components:
|
|
211
|
+
# T0_w : 4×4 transform — world frame to TSR frame
|
|
212
|
+
# Tw_e : 4×4 transform — TSR frame to end-effector at Bw=0
|
|
213
|
+
# Bw : 6×2 bounds — [x, y, z, roll, pitch, yaw]
|
|
214
|
+
|
|
215
|
+
# Example: keep a mug upright — free xy/yaw, small pitch/roll
|
|
216
|
+
T0_w = np.eye(4)
|
|
217
|
+
Tw_e = np.eye(4)
|
|
218
|
+
Bw = np.zeros((6, 2))
|
|
219
|
+
Bw[0, :] = [-2.0, 2.0] # x: anywhere in workspace
|
|
220
|
+
Bw[1, :] = [-2.0, 2.0] # y: anywhere in workspace
|
|
221
|
+
Bw[2, :] = [ 0.5, 1.5] # z: transport height
|
|
222
|
+
Bw[3, :] = [-0.26, 0.26] # roll: ±15°
|
|
223
|
+
Bw[4, :] = [-0.26, 0.26] # pitch: ±15°
|
|
224
|
+
Bw[5, :] = [-np.pi, np.pi] # yaw: free
|
|
225
|
+
|
|
226
|
+
tsr = TSR(T0_w=T0_w, Tw_e=Tw_e, Bw=Bw)
|
|
227
|
+
|
|
228
|
+
pose = tsr.sample() # random SE(3) pose in the region
|
|
229
|
+
distance, _ = tsr.distance(pose) # distance to nearest valid pose
|
|
230
|
+
is_valid = tsr.contains(pose) # containment check
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
### Save and load templates
|
|
234
|
+
|
|
235
|
+
```python
|
|
236
|
+
from tsr import TSRTemplate, save_template, load_template
|
|
237
|
+
import numpy as np
|
|
238
|
+
|
|
239
|
+
template = TSRTemplate(
|
|
240
|
+
T_ref_tsr=np.eye(4),
|
|
241
|
+
Tw_e=Tw_e,
|
|
242
|
+
Bw=Bw,
|
|
243
|
+
task="transport",
|
|
244
|
+
subject="mug",
|
|
245
|
+
reference="world",
|
|
246
|
+
name="Mug Transport Upright",
|
|
247
|
+
description="Keep mug upright during transport, ±15° tilt tolerance",
|
|
248
|
+
)
|
|
249
|
+
|
|
250
|
+
save_template(template, "my_template.yaml")
|
|
251
|
+
template = load_template("my_template.yaml")
|
|
252
|
+
|
|
253
|
+
# Bind to an object pose at runtime
|
|
254
|
+
tsr = template.instantiate(np.eye(4))
|
|
255
|
+
```
|
|
256
|
+
|
|
257
|
+
## End-effector frame convention
|
|
258
|
+
|
|
259
|
+
All templates in this library use a canonical end-effector frame:
|
|
260
|
+
|
|
261
|
+
```
|
|
262
|
+
z = approach direction (toward contact surface)
|
|
263
|
+
y = opening / spread direction (finger opening for grippers, tool axis for others)
|
|
264
|
+
x = right-hand normal (x = y × z)
|
|
265
|
+
```
|
|
266
|
+
|
|
267
|
+
AnyGrasp / GraspNet uses `x = approach` — convert with:
|
|
268
|
+
```python
|
|
269
|
+
R_convert = np.array([[0, 0, -1], [0, 1, 0], [1, 0, 0]])
|
|
270
|
+
```
|
|
271
|
+
|
|
272
|
+
## TSR Chains
|
|
273
|
+
|
|
274
|
+
For coupled multi-body constraints (e.g., door opening, bimanual transport):
|
|
275
|
+
|
|
276
|
+
```python
|
|
277
|
+
from tsr import TSRChain
|
|
278
|
+
|
|
279
|
+
chain = TSRChain(TSRs=[hinge_tsr, handle_tsr])
|
|
280
|
+
pose = chain.sample()
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
## Visualization
|
|
284
|
+
|
|
285
|
+
```python
|
|
286
|
+
from tsr.viz import TSRVisualizer, cylinder_renderer, parallel_jaw_renderer, plasma_colors
|
|
287
|
+
|
|
288
|
+
poses = [t.sample(mug_pose) for t in templates]
|
|
289
|
+
colors = plasma_colors(len(templates))
|
|
290
|
+
|
|
291
|
+
TSRVisualizer(
|
|
292
|
+
title="Cylinder Grasp Templates",
|
|
293
|
+
focus=(0., 0., 0.06),
|
|
294
|
+
).render(
|
|
295
|
+
reference_renderer=cylinder_renderer(radius=0.04, height=0.12),
|
|
296
|
+
subject_renderer=parallel_jaw_renderer(finger_length=0.055, half_aperture=0.07),
|
|
297
|
+
poses=poses,
|
|
298
|
+
colors=colors,
|
|
299
|
+
out="grasp_viz.png",
|
|
300
|
+
)
|
|
301
|
+
```
|
|
302
|
+
|
|
303
|
+
Requires the `viz` extra: `uv sync --extra viz`.
|
|
304
|
+
|
|
305
|
+
## Documentation
|
|
306
|
+
|
|
307
|
+
- **[Tutorial](docs/tutorial.md)** — TSR theory, math, and worked examples
|
|
308
|
+
- **[Examples](examples/)** — Runnable scripts (`uv run python examples/<script>.py`)
|
|
309
|
+
|
|
310
|
+
## Testing
|
|
311
|
+
|
|
312
|
+
```bash
|
|
313
|
+
uv run pytest tests/ -v
|
|
314
|
+
```
|
|
315
|
+
|
|
316
|
+
## License
|
|
317
|
+
|
|
318
|
+
BSD-2-Clause — see LICENSE file.
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
tsr/__init__.py,sha256=DyDsghINgL32BvUXfpL4ha5REqDv2m65d6Vot5q4tao,3123
|
|
2
|
+
tsr/io.py,sha256=Idz-WTx9S6vHgDhDtKfxPQ-zKX1aS32zaXIgOpxbYlE,3641
|
|
3
|
+
tsr/sampling.py,sha256=OAd4HuHXB2K0oBCfPlgWAefVtSBNmR_BLVYluFattI4,9330
|
|
4
|
+
tsr/template.py,sha256=6AGX4_VTq_Kx3dtSPoSgQV5DAiLSUCyGdFIb3JeEx5c,5491
|
|
5
|
+
tsr/tsr.py,sha256=shVgAeoVZOjhYSG0ni8BvHTMl1fwW7ZjbfP6nUeeYCc,370
|
|
6
|
+
tsr/tsr_chain.py,sha256=a8XR1-MB7uQHTo1NFj5X6C-fGxxZq4nJAPdOzrKVDuY,392
|
|
7
|
+
tsr/utils.py,sha256=jYBOmGBG8SJlM9DNDz8H5tVhrCOdSgJ_pAXMKAaGnyA,546
|
|
8
|
+
tsr/viz.py,sha256=fnQ71qFDE8DSXPhoMOzAagyQzxWDMxhMRmHQDrIqoMs,23026
|
|
9
|
+
tsr/core/__init__.py,sha256=diN8q5DK-IXMaHd-ujTZ-g6NluvCNikR6QuVJ0-WHu0,952
|
|
10
|
+
tsr/core/tsr.py,sha256=b_aXQlhmdEVvN9ZJF2g6soCDWE2G1gf2FdBcrksDNdk,21775
|
|
11
|
+
tsr/core/tsr_chain.py,sha256=aZYAIZWyFr9Q2hVtBzqldDj_mZJS6vcfodwwdrOKBDA,8655
|
|
12
|
+
tsr/core/utils.py,sha256=eTePgeaCP31A_gN1G54xhFfluv7K8jLhORHb5NkB1x0,3467
|
|
13
|
+
tsr/hands/__init__.py,sha256=4Tu3eae6Y8pGyVQ_Jcgqq55UDJNAA4L2dnNqCWY8JFY,891
|
|
14
|
+
tsr/hands/base.py,sha256=pYJBruv2NB1lq4blfO07BvLygwKP046ILErkhG-2WWM,25992
|
|
15
|
+
tsr/hands/parallel_jaw.py,sha256=mvwewuVHHucqCh5uoI_s5m-xsWWO6FBU_JXHjm2BXzE,48753
|
|
16
|
+
tsr/hands/registry.py,sha256=W_NW5oH3lIEZ--uB8OrFH6-e08qsTxUVmbwqTVTumec,3881
|
|
17
|
+
tsr/placement/__init__.py,sha256=Hyg0YXIACgIAp9oXKunKpJodNt_97WEi8HMXhKGjjjo,579
|
|
18
|
+
tsr/placement/_stable_poses.py,sha256=nchSC2FygISBKyCd2T7066DLi6vr1Cd9-ykT9vgJIi0,6471
|
|
19
|
+
tsr/placement/stable_placer.py,sha256=Xpg_9jVehcj7gXiF6ddaldB99m6YxurRHq0m4Yo02zI,11682
|
|
20
|
+
tsr/templates/README.md,sha256=6g96Okg29hed0tZBsYx3C0gnsQhVG3lutelmvKFLLp0,2059
|
|
21
|
+
tsr/templates/grasps/mug_handle_grasp.yaml,sha256=5cTgOjvHJe0__ktKZSyQZ0VoNq8An6klws9Jr8Y5vuU,546
|
|
22
|
+
tsr/templates/grasps/screwdriver_grasp.yaml,sha256=H75b_HUETx0LXmVnR--YvtW0qu7AOUdMMWA97mFEEIQ,572
|
|
23
|
+
tsr/templates/places/mug_on_table.yaml,sha256=1VoKshxoZT7yiG9L1PMqJLWXdGD1ikGzjDbwLkv1ies,519
|
|
24
|
+
tsr/templates/places/toolchest_drop.yaml,sha256=gu81vy5OcxtWoe40xSd_u7sIQT5ZwM53JJecDhMQNG8,761
|
|
25
|
+
tsr/templates/tasks/drive_screw.yaml,sha256=rh6U3GkXJ-Ng_ZtX4xXq3XNfYA_enstrY9Tm7dgIqo4,697
|
|
26
|
+
tsr/templates/tasks/mug_pour_into_sink.yaml,sha256=BOwNwpnUkcMMk9c8QibMC5q86Vx4kqGc4IMH7iwvig8,714
|
|
27
|
+
tsr/templates/tasks/mug_transport_upright.yaml,sha256=wM2Ns3L84Qyn_f6vLeKhOLK3cLpJH_-dgdRJWvMi_F0,751
|
|
28
|
+
sstsr-2.0.0.dist-info/METADATA,sha256=dok81wfFTioCoWWbHnfE4NPUbB5VHRJ8GR8X08VI8UM,10181
|
|
29
|
+
sstsr-2.0.0.dist-info/WHEEL,sha256=THafob7ofN-NsuMN7Mg4qZyHaQI7KkD-QlcQatYhXPo,87
|
|
30
|
+
sstsr-2.0.0.dist-info/licenses/LICENSE,sha256=IJQAUlQgzVn5wagmuyH6I6-iEjAMVWMNqN1sNJmh0LY,1333
|
|
31
|
+
sstsr-2.0.0.dist-info/RECORD,,
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
BSD 2-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2025, Siddhartha Srinivasa and contributors to TSR
|
|
4
|
+
|
|
5
|
+
Redistribution and use in source and binary forms, with or without
|
|
6
|
+
modification, are permitted provided that the following conditions are met:
|
|
7
|
+
|
|
8
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
9
|
+
list of conditions and the following disclaimer.
|
|
10
|
+
|
|
11
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
12
|
+
this list of conditions and the following disclaimer in the documentation
|
|
13
|
+
and/or other materials provided with the distribution.
|
|
14
|
+
|
|
15
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
16
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
17
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
18
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
19
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
20
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
21
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
22
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
23
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
24
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
tsr/__init__.py
ADDED
|
@@ -0,0 +1,104 @@
|
|
|
1
|
+
# SPDX-License-Identifier: BSD-2-Clause
|
|
2
|
+
# Authors: Siddhartha Srinivasa and contributors to TSR
|
|
3
|
+
|
|
4
|
+
"""TSR — Task Space Regions for robotics.
|
|
5
|
+
|
|
6
|
+
Robot-agnostic Task Space Region (TSR) functionality for pose-constrained
|
|
7
|
+
manipulation planning. The package is layered:
|
|
8
|
+
|
|
9
|
+
* **core** — the pure-math heart: :class:`TSR`, :class:`TSRChain`, and SE(3)
|
|
10
|
+
helpers. Robot-agnostic, NumPy/SciPy only.
|
|
11
|
+
* **template** — :class:`TSRTemplate`: a reusable, serialisable, scene-agnostic
|
|
12
|
+
recipe that instantiates to a concrete TSR at a reference pose.
|
|
13
|
+
* **factories** — domain knowledge that *produces* templates:
|
|
14
|
+
:class:`ParallelJawGripper` (and ready-made hands) for grasps, and
|
|
15
|
+
:class:`StablePlacer` for placements.
|
|
16
|
+
* **services** — :mod:`tsr.io` (persistence), sampling helpers, and the
|
|
17
|
+
optional :mod:`tsr.viz` renderer (install with the ``viz`` extra).
|
|
18
|
+
|
|
19
|
+
The spine: a factory produces recipes; a recipe instantiates to math::
|
|
20
|
+
|
|
21
|
+
from tsr import ParallelJawGripper
|
|
22
|
+
gripper = ParallelJawGripper(finger_length=0.055, max_aperture=0.140)
|
|
23
|
+
templates = gripper.grasp_cylinder(cylinder_radius=0.04, cylinder_height=0.12)
|
|
24
|
+
tsr = templates[0].instantiate(object_pose_in_world)
|
|
25
|
+
pose = tsr.sample() # a valid grasp pose
|
|
26
|
+
assert tsr.contains(pose)
|
|
27
|
+
"""
|
|
28
|
+
|
|
29
|
+
# --- Layer 0: core math -------------------------------------------------------
|
|
30
|
+
from .core import (
|
|
31
|
+
EPSILON,
|
|
32
|
+
TSR,
|
|
33
|
+
TSRChain,
|
|
34
|
+
geodesic_distance,
|
|
35
|
+
geodesic_error,
|
|
36
|
+
rotation_angle,
|
|
37
|
+
wrap_to_interval,
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
# --- Layer 1: the reusable recipe ---------------------------------------------
|
|
41
|
+
from .template import TSRTemplate
|
|
42
|
+
|
|
43
|
+
# --- Layer 2: factories (domain knowledge -> recipes) -------------------------
|
|
44
|
+
from .hands import FrankaHand, GripperBase, ParallelJawGripper, Robotiq2F85, Robotiq2F140
|
|
45
|
+
from .placement import StablePlacer
|
|
46
|
+
|
|
47
|
+
# --- Layer 3: services --------------------------------------------------------
|
|
48
|
+
from .io import (
|
|
49
|
+
get_package_templates,
|
|
50
|
+
list_available_templates,
|
|
51
|
+
load_package_template,
|
|
52
|
+
load_package_templates_by_category,
|
|
53
|
+
load_template,
|
|
54
|
+
load_template_collection,
|
|
55
|
+
save_template,
|
|
56
|
+
save_template_collection,
|
|
57
|
+
)
|
|
58
|
+
from .sampling import (
|
|
59
|
+
choose_tsr,
|
|
60
|
+
choose_tsr_index,
|
|
61
|
+
instantiate_templates,
|
|
62
|
+
sample_from_templates,
|
|
63
|
+
sample_from_tsrs,
|
|
64
|
+
weights_from_tsrs,
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
__version__ = "2.0.0"
|
|
68
|
+
|
|
69
|
+
__all__ = [
|
|
70
|
+
# core
|
|
71
|
+
"TSR",
|
|
72
|
+
"TSRChain",
|
|
73
|
+
"wrap_to_interval",
|
|
74
|
+
"rotation_angle",
|
|
75
|
+
"geodesic_error",
|
|
76
|
+
"geodesic_distance",
|
|
77
|
+
"EPSILON",
|
|
78
|
+
# template
|
|
79
|
+
"TSRTemplate",
|
|
80
|
+
# factories
|
|
81
|
+
"GripperBase",
|
|
82
|
+
"ParallelJawGripper",
|
|
83
|
+
"Robotiq2F85",
|
|
84
|
+
"Robotiq2F140",
|
|
85
|
+
"FrankaHand",
|
|
86
|
+
"StablePlacer",
|
|
87
|
+
# sampling helpers
|
|
88
|
+
"choose_tsr",
|
|
89
|
+
"choose_tsr_index",
|
|
90
|
+
"instantiate_templates",
|
|
91
|
+
"sample_from_tsrs",
|
|
92
|
+
"sample_from_templates",
|
|
93
|
+
"weights_from_tsrs",
|
|
94
|
+
# template I/O
|
|
95
|
+
"save_template",
|
|
96
|
+
"save_template_collection",
|
|
97
|
+
"load_template",
|
|
98
|
+
"load_template_collection",
|
|
99
|
+
"load_package_template",
|
|
100
|
+
"load_package_templates_by_category",
|
|
101
|
+
"list_available_templates",
|
|
102
|
+
"get_package_templates",
|
|
103
|
+
"__version__",
|
|
104
|
+
]
|
tsr/core/__init__.py
ADDED
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
# SPDX-License-Identifier: BSD-2-Clause
|
|
2
|
+
# Authors: Siddhartha Srinivasa and contributors to TSR
|
|
3
|
+
|
|
4
|
+
"""tsr.core — the pure-math heart of the package.
|
|
5
|
+
|
|
6
|
+
Layer 0 of the architecture: robot-agnostic SE(3) geometry with no dependencies
|
|
7
|
+
beyond NumPy (and SciPy for the optional optimiser paths). Nothing in this
|
|
8
|
+
subpackage imports from the convenience layers above it (templates, factories,
|
|
9
|
+
io, sampling, viz); that invariant is enforced by
|
|
10
|
+
``tests/tsr/test_architecture.py``.
|
|
11
|
+
|
|
12
|
+
The public symbols are re-exported at the top level (``from tsr import TSR``);
|
|
13
|
+
import them from here when you want only the kernel.
|
|
14
|
+
"""
|
|
15
|
+
|
|
16
|
+
from .tsr import NANBW, TSR
|
|
17
|
+
from .tsr_chain import TSRChain
|
|
18
|
+
from .utils import (
|
|
19
|
+
EPSILON,
|
|
20
|
+
geodesic_distance,
|
|
21
|
+
geodesic_error,
|
|
22
|
+
rotation_angle,
|
|
23
|
+
wrap_to_interval,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
__all__ = [
|
|
27
|
+
"TSR",
|
|
28
|
+
"TSRChain",
|
|
29
|
+
"NANBW",
|
|
30
|
+
"EPSILON",
|
|
31
|
+
"wrap_to_interval",
|
|
32
|
+
"rotation_angle",
|
|
33
|
+
"geodesic_error",
|
|
34
|
+
"geodesic_distance",
|
|
35
|
+
]
|