Metadata-Version: 2.4
Name: qhsim
Version: 0.1.2
Summary: Python SDK for simulation-carema.
Author: Qunhe
Requires-Python: >=3.9
Description-Content-Type: text/markdown

# qhsim SDK

Python SDK for the simulation-carema render backend.

## Install

Install the latest published SDK from PyPI:

```bash
python -m pip install -U qhsim
```

Install a specific version:

```bash
python -m pip install qhsim==0.1.1
```

For local development from this repository:

```powershell
cd D:\fengguo\Agent\repo\simulation-carema
python -m pip install -e sdk
```

The package requires Python 3.9 or later.

## Configuration

`user_id` and `design_id` must be the encrypted IDs expected by the backend.

Defaults used by the HTTP backend and demos:

- service base URL: `https://qh-sensor-simulation-prodtest.k8s-txyun-prod.qunhequnhe.com`
- service base prefix: `/qh-sensor-simulation/api/c`
- snapshot type ID: `720`
- HTTPS certificate verification: disabled by default for prodtest self-signed certificates

Enable HTTPS certificate verification explicitly when you have a trusted CA:

```python
simulation_app = SimulationApp(
    user_id="3FO4KV8SHSLV",
    config={
        "verify_ssl": True,
        "cafile": "internal-ca.pem",
    },
)
```

## Quick Start

```python
from qhsim import SimulationApp
from qhsim.core.api import World
from qhsim.core.math import Position, Target
from qhsim.sensors.camera import Camera


simulation_app = SimulationApp(
    user_id="3FO4KV8SHSLV",
    config={"snapshot_type_id": 720},
)

try:
    world = World(simulation_app)
    scene = world.load_scene(design_id="3FO3EEB7MV3B")

    camera = Camera(
        name="camera",
        position=Position(0.0, 238.0, 1300.0),
        target=Target(0.0, 1938.0, 1300.0),
        fov=80.0,
        clarity=1,
    )
    scene.add(camera)
    camera.set_world_pose(
        position=Position(0.0, 238.0, 1600.0),
        target=Target(0.0, 1938.0, 1300.0),
    )

    submitted = world.render(camera)
    print(submitted.task_id)

    final = world.poll_render_result(
        submitted.task_id,
        interval=3.0,
        max_attempts=20000,
    )
    print(final.status)
    print(final.image_urls)
finally:
    simulation_app.close()
```

The SDK calls:

- `GET /qh-sensor-simulation/api/c/scene/models?designId=...`
- `POST /qh-sensor-simulation/api/c/camera/render`
- `GET /qh-sensor-simulation/api/c/camera/render/result?rootTaskId=...`

`user_id` is sent as the required `x-qh-id` header. `design_id` is sent as `designId` in query/body.

## Demos

Run the simple flow from an installed package:

```powershell
python sdk\examples\basic_http_flow.py
```

Run the debug flow, which loads a scene, submits two camera poses, polls until the render result is ready, and prints task/result fields:

```powershell
python sdk\examples\debug_http_render_flow.py
```

Override demo inputs with environment variables:

```powershell
$env:QHSIM_USER_ID="3FO4KV8SHSLV"
$env:QHSIM_DESIGN_ID="3FO3EEB7MV3B"
$env:QHSIM_SNAPSHOT_TYPE_ID="720"
$env:QHSIM_POLL_INTERVAL="3"
$env:QHSIM_POLL_ATTEMPTS="20000"
python sdk\examples\debug_http_render_flow.py
```

Run the concurrent render pressure demo:

```powershell
$env:QHSIM_TASKS="50"
$env:QHSIM_TIMEOUT_SECONDS="1800"
$env:QHSIM_OUTPUT="sdk\examples\concurrent_http_render_results.json"
python sdk\examples\concurrent_http_render_flow.py
```

The concurrent demo writes a JSON summary containing task IDs, camera poses, final status, result readiness, image URLs, COS keys, errors, poll attempts, and durations.

If you run examples directly from a checkout without editable install, set `PYTHONPATH` first:

```powershell
$env:PYTHONPATH="D:\fengguo\Agent\repo\simulation-carema\sdk"
python sdk\examples\debug_http_render_flow.py
```

## Public API

### `qhsim`

- `SimulationApp`: SDK runtime entrypoint.
  - `update()`
  - `close()`
  - `is_running()`

### `qhsim.core`

- `World`
  - `load_scene(design_id)`
  - `render(camera=None)`
  - `get_render_result(task_id)`
  - `poll_render_result(task_id, interval=3.0, max_attempts=20000, print_progress=True, require_result=True)`
- `Scene`
  - `add(obj)`
  - `get_objects()`
  - `get_object(object_id=None, object_name=None)`
- `ModelData`
- `Position`
- `Target`
- `BoundingBox`
- `RenderData`

### `qhsim.sensors`

- `Camera`
  - `set_world_pose(position, target)`
  - `get_world_pose()`
  - `get_history_pose()`
  - `get_history_pos_json()`
  - `to_render_history()`

### `qhsim.backends`

- `HttpBackend`
  - `load_scene(design_id)`
  - `render(design_id, camera_history, camera_name)`
  - `get_render_result(root_task_id)`
- `DEFAULT_BASE_URL`
- `DEFAULT_SERVICE_BASE_PREFIX`
- `DEFAULT_SNAPSHOT_TYPE_ID`

To swap the transport in tests, pass a backend object with `load_scene()`, `render()`, and `get_render_result()`:

```python
simulation_app = SimulationApp(config={"backend": custom_backend})
```

## Publish

The package version is defined in `sdk/pyproject.toml`.

Set a PyPI API token in the current shell, then run the upload script:

```powershell
$env:TWINE_PASSWORD="pypi-..."
python sdk\upload_latest.py
```

The script builds the current version, runs `twine check`, and uploads only the current version's wheel and source distribution.
