Skip to main content

thrustlab — official Python SDK for the ThrustLab API

PyPI Python License

The official Python client for ThrustLab — electric-UAV powertrain simulation as an API.

Install

pip install thrustlab

Requires Python 3.10+.

Quickstart

from thrustlab import Client

client = Client()  # reads $THRUSTLAB_API_KEY (never hard-code the key)

# Create a project
project = client.projects.create(name="my project")

# Run a single-point simulation and wait for the result.
# A rotor group carries the motor + propeller + throttle (0–100); the battery
# and flight condition are top-level. Resolve component IDs from the catalog
# (client.components.find(name=...)) or paste them directly.
sim = client.simulations.create(
    project_id=project["id"],
    battery_component_id="comp_batt_xxx",
    airspeed_m_s=0.0,
    density_kg_m3=1.225,
    battery_charge_pct=100,
    rotor_groups=[
        {
            "label": "main",
            "count": 4,
            "motor_component_id": "comp_motor_xxx",
            "propeller_component_id": "comp_prop_xxx",
            "throttle_pct": 70,
        }
    ],
)
result = client.simulations.wait(sim["id"], timeout=300)

# Canonical snake_case result: per-rotor group under "1"/"2"/…, roll-ups
# under "All" (a sibling `display_labels` map carries the human labels).
print(result["result"]["1"]["thrust_n"], result["result"]["All"]["total_thrust_n"])

Runnable end-to-end examples for every simulation type live in examples/: simulations/run_sync.py, sweeps/run_and_poll.py, and dynamic/run_and_poll.py.

FMU export and SITL

Export a completed simulation as an FMI 3.0 co-simulation FMU:

job_id = client.fmu.export(sim_id)["id"]
client.fmu.wait(job_id)
client.fmu.download(job_id, "powertrain.fmu")

The FMU exposes per-rotor inputs and outputs, battery and thermal state, and a validity envelope; it runs in any FMI 3.0 co-simulation host and is verified in Simulink.

thrustlab-sitl, installed with the SDK, flies the FMU in ArduPilot SITL or Betaflight SITL (--target betaflight). See thrustlab/sitl/README.md for the full documentation.

thrustlab-sitl --fmu powertrain.fmu --vehicle quad_x.yaml --target betaflight

See examples/fmu/ for bundled ready-to-fly FMUs with quadcopter, Y6 coax, and tilt-tricopter missions, an endurance study, and replay rendering.

Offline propeller estimate

thrustlab.estimate is the ThrustLab propeller equation: thrust, torque and power from the printed size, with no account and no network.

from thrustlab.estimate import from_label

point = from_label(diameter_in=10, pitch_in=5, rpm=8000, airspeed_mps=12.0)
print(point.T, point.Q, point.P_shaft)   # N, N m, W
thrustlab-estimate --diameter 10 --pitch 5 --rpm 8000 --airspeed 0:30:5

It is the closed form of the simulator's Fast propeller model. The simulator adds the motor, ESC, battery and thermal coupling; the Full model adds the measured blade geometry.

Why the SDK (and not urllib / wget)?

The SDK gives you automatic retries with backoff, idempotency keys, cursor pagination, polling helpers, webhook signature verification, and typed errors. It is built on httpx and sends its own thrustlab-python/<version> User-Agent.

If you hand-roll a client anyway, use an HTTP library with a descriptive User-Agent (httpx, requests, or curl). ThrustLab's edge protection screens non-browser User-Agents such as stdlib Python-urllib/* and wget: API paths under /v1/ are exempt from the screening, but every other route blocks these at the edge with an opaque error 1010 page — the request never reaches ThrustLab, so no JSON error envelope is possible there.

Configuration

Setting Constructor arg Env var Default
API key api_key= THRUSTLAB_API_KEY (required)
Base URL base_url= THRUSTLAB_BASE_URL https://thrustlab.com
Timeout timeout= — 30 (seconds)
Max retries max_retries= — 3

Resources

Every /v1/ route family is exposed as an attribute on the client:

client.users
client.projects
client.simulations
client.sweeps
client.dynamic_simulations
client.components
client.submissions
client.starred_components
client.compute_units
client.webhook_endpoints
client.fmu

Error handling

from thrustlab import Client
from thrustlab.exceptions import (
    AuthenticationError,
    ValidationError,
    RateLimitError,
    NotFoundError,
)

client = Client()
try:
    client.simulations.create(project_id="proj_xxx", rotor_groups=[...], ...)
except ValidationError as exc:
    print(f"bad request: {exc.code} ({exc.param}): {exc.message}")
except RateLimitError as exc:
    print(f"rate limited; retry after {exc.retry_after}s")
except NotFoundError as exc:
    print(f"not found: {exc.message}")
except AuthenticationError as exc:
    print(f"auth failed: {exc.message}")

Every error carries .code, .type, .request_id, .http_status, and .message. ValidationError additionally exposes .param. See thrustlab.com/docs/guides/errors for the full code reference.

Pagination

List endpoints return a CursorPager — a lazy iterator that fetches the next page only when needed:

# Iterate all pages automatically
for project in client.projects.list():
    print(project["id"])

# Materialise the first page only
first_page = list(client.projects.list(limit=20))

Async polling

simulations.wait(), sweeps.wait(), and dynamic_simulations.wait() block until the resource reaches a terminal state (completed, failed, or canceled — one 'l' on the wire) or the timeout fires. On timeout the returned dict carries the SDK-side sentinel status="timed_out" (never a server state):

sweep = client.sweeps.create(...)
result = client.sweeps.wait(sweep["id"], timeout=600, poll_interval=2.0)
if result["status"] == "completed":
    for point in client.sweeps.list_points(sweep["id"]):
        print(point["rotors"]["1"]["thrust_n"])

Webhooks

from thrustlab import Webhook
from thrustlab.exceptions import SignatureVerificationError

WEBHOOK_SECRET = "whsec_..."

@app.post("/webhooks/thrustlab")
async def handle(request):
    payload = await request.body()
    sig    = request.headers["Thrustlab-Signature"]
    try:
        event = Webhook.verify(payload, sig, WEBHOOK_SECRET)
    except SignatureVerificationError:
        return Response(status_code=400)
    if event.type == "simulation.succeeded":
        print(event.data)

Retries

The client automatically retries on 429 (rate limit) and 5xx responses using exponential backoff with jitter. Set max_retries=0 to disable:

client = Client(max_retries=0)

License

Apache-2.0. See LICENSE and NOTICE.

Metadata

Release files for thrustlab 0.7.0

For a detailed explanation of source distributions (sdists) and built distributions (wheels), please see the package formats documentation.

Source distribution (sdist)

Source distribution for thrustlab 0.7.0
File Size Uploaded
thrustlab-0.7.0.tar.gz 519.0 kB Details

Built distribution (wheel)

Table of built distributions (wheels) for thrustlab 0.7.0
File Interpreter ABI Platform
thrustlab-0.7.0-py3-none-any.whl Python 3 none any Details

Total release size: 1.0 MB

Release files / thrustlab-0.7.0.tar.gz

Download URL thrustlab-0.7.0.tar.gz
Size 519.0 kB
Tags Source
SHA-256 checksum
How to use checksums
d646988119ec3a644343d31a53434b5cff85be8c99096eaa93708e9a4a772117
BLAKE2b-256 checksum
How to use checksums
30cb9c20589db0b995902b77e382c6d228673d778c67c4352b6c3dc77a338a8a
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.9

Release files / thrustlab-0.7.0-py3-none-any.whl

Download URL thrustlab-0.7.0-py3-none-any.whl
Size 521.9 kB
Tags Python 3
SHA-256 checksum
How to use checksums
bb0357f64d1a46d5893c5121c87713ad242e9ab76a9b52610daa36147ba64fdd
BLAKE2b-256 checksum
How to use checksums
d4b6a90930a0128cc691542a4036266a582d51cfb978f8228b0b743f33d738bf
Upload date
Uploaded using Trusted Publishing?
What is trusted publishing?
No
Uploaded via twine/7.0.0 CPython/3.11.9

Release history Release notifications | RSS feed

This release

0.7.0 This release

2 release files

0.6.0

2 release files

0.5.0

2 release files

0.4.0

2 release files

0.3.2

2 release files

0.3.1

2 release files

0.3.0

2 release files

0.1.1

2 release files

Anthropic, PBC Visionary sponsor Bloomberg Visionary sponsor Hudson River Trading Visionary sponsor Meta Visionary sponsor NVIDIA Visionary sponsor Microsoft Sustainability sponsor Depot Continuous Integration AWS Cloud computing and Security Sponsor Datadog Monitoring Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page