Metadata-Version: 2.4
Name: pytact
Version: 0.1.0
Summary: Python package for tact, a high contact/tactile fidelity dynamics simulator
License-Expression: MIT
Project-URL: Repository, https://github.com/tzscheng/pytact
Project-URL: Issues, https://github.com/tzscheng/pytact/issues
Classifier: Development Status :: 2 - Pre-Alpha
Classifier: Intended Audience :: Developers
Classifier: Intended Audience :: Science/Research
Classifier: Operating System :: POSIX :: Linux
Classifier: Programming Language :: Python :: 3
Classifier: Programming Language :: Python :: 3.12
Classifier: Programming Language :: Python :: 3.13
Classifier: Topic :: Scientific/Engineering
Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
Classifier: Topic :: Software Development :: Libraries :: Python Modules
Requires-Python: >=3.12
Description-Content-Type: text/markdown
License-File: LICENSE
License-File: docs/THIRD_PARTY_NOTICES
Requires-Dist: numpy>=2.0
Requires-Dist: pyyaml>=6.0
Provides-Extra: ipc
Requires-Dist: pyzmq>=25; extra == "ipc"
Provides-Extra: demos
Requires-Dist: pyzmq>=25; extra == "demos"
Dynamic: license-file

# tact

`tact` is a high contact/tactile fidelity dynamics simulator. It provides
rigid-body dynamics, contact and tactile simulation, YAML scene loading,
rendering, sensors, controllers, and runtime model composition.

<p align="center">
  <img src="docs/gif/tact-demo-0.gif" alt="Articulated pendulum simulation" width="49%">
  <img src="docs/gif/tact-demo-1.gif" alt="Rigid-body contact simulation" width="49%"><br>
  <img src="docs/gif/tact-demo-2.gif" alt="Box-wall impact simulation" width="49%">
  <img src="docs/gif/tact-demo-3.gif" alt="Robot locomotion over terrain" width="49%">
</p>

## Install

Prerequisites:

- Linux
- Python 3.12 or newer

Install the published Python package:

```bash
pip install pytact
```

## Minimal Example

This example is the 2-link manipulator shown in the first animation above. It
defines the model in YAML and runs it in an interactive window. Create
`minimal.yaml`:

```yaml
sim: {solver: lcp, dt: 0.002, g: [0, 0, -9.81]}
view: {target: [0, 0, -1], distance: 3, yaw: 0, pitch: 0}
lights: [{pos: [7, 7, 7], target: [0, 0, 0], ortho: 5.0, shadow: true}]

bodies:
  - name: link1
    joint: {type: rev, parent: root, euler: [0, 90, 0], damping: 0.2, q0: 45}
    inertial: {mass: 1.0, tensor: [diag, 0.004, 0.004, 0.004], pos: [0.5, 0, 0]}
    shapes: [{type: capsule, pos: [0.5, 0, 0], euler: [0, 90, 0], param: [0.02, 0.5], rgba: [0.4, 0.4, 0.4, 1.0]}]

  - name: link2
    joint: {type: rev, parent: link1, pos: [1.0, 0, 0], damping: 0.2, q0: 45}
    inertial: {mass: 1.0, tensor: [diag, 0.002, 0.002, 0.002], pos: [0.5, 0, 0]}
    shapes:
      - {type: capsule, pos: [0.5, 0, 0], euler: [0, 90, 0], param: [0.02, 0.5], rgba: [0.4, 0.4, 0.4, 1.0]}
      - {type: sphere, pos: [1.0, 0, 0], param: [0.08], rgba: [0.9, 0.4, 0.4, 1.0]}

feeds:
  - jointpos: [link1, link2]
  - jointvel: [link1, link2]
```

Create `minimal.py` in the same directory:

```python
import numpy as np
import tact

env = tact.Env("minimal", render=True, redraw=8)
tau = np.zeros(env.dof)
cnt = 0

while True:
    y = env.step(tau)
    if cnt % 100 == 0:
        q = y[: env.dof]
        qd = y[env.dof :]
        print(f"{cnt:04d} q={q.round(4)} qd={qd.round(4)} y={y.round(4)}")
    cnt += 1
```

Run it from the directory containing both files:

```bash
python minimal.py
```

The simulation step can also be expressed as steps per second: `sps: 240` is
equivalent to `dt: 1/240`. If both are present, `dt` takes precedence.

The complete files for this example are available in
[`demos/minimal/`](demos/minimal/).

## Development

The project uses three related names:

| Name | Role |
| --- | --- |
| `tact` | Simulator identity, C library name, and Python import namespace |
| `pytact` | Python distribution installed with `pip install pytact` |
| `libtact.so` | Native shared library used by Python and standalone C programs |

### Source layout

```text
native/              C engine sources and public header tact.h
native/lib/          native C shared library output from make
native/demos/basic/  minimal standalone C demo using compiled .bin models
demos/               checkout-only examples for GitHub users
tact/                Python package source
local/               local development docs and tests (not distributed)
```

From a checkout, `make` builds the native C library at `native/lib/libtact.so`
and copies that same library to the package-local `tact/bin/libtact.so` used by
Python, then builds the native demo. `make package-lib` performs only the native
library build plus package-local copy, without building demos. Python packaging
uses that same `make package-lib` path, so editable installs and normal local
builds share one C build recipe.

For PyPI release artifacts, build through the manylinux container path:

```bash
make dist-pypi
```

That target creates the sdist with `uv build --sdist`, then builds the wheel with
`cibuildwheel` inside the configured manylinux image. Do not upload the local
`linux_x86_64` wheel from `uv build --wheel`; PyPI accepts the repaired
`manylinux_*_x86_64` wheel produced by `make dist-pypi`.

### Third-party software

Parts of the convex collision implementation are derived from
[libccd](https://github.com/danfis/libccd), licensed under the BSD 3-Clause
License. See [`docs/THIRD_PARTY_NOTICES`](docs/THIRD_PARTY_NOTICES).
