Skip to main content

dynos-adaptive-resampling

A worked example: chain an ML-driven resampling step onto a Sentry survey. This package is scaffolding: it ships a stub AdaptiveResampler that you replace with your model, plus the wiring (runnable.py, mission.py) that lets dynos connect find it and that lets the planner sequence "survey, resample, resurvey".

The package contributes one new transition (resample_zone) and one new mission template (build_resample_mission). Everything else is for you to edit.

Install

You will be modifying the source, so install editable:

pip install -e dynos-adaptive-resampling

This pulls in dynos-client, dynos-sentry-domain, and numpy.

What's in this repository

domain.py

Declares resample_zone (transition), ResampleZoneParams (its parameter dataclass), resampling_complete (a fluent the transition adds). Edit if you need new fluents or parameters.

resampler.py

Provides AdaptiveResampler class with @Action(transition=resample_zone). Edit _gather_historic_data and _predict_new_zone or whatever else you need to get your model integrated.

mission.py

Provides build_resample_mission(zone_name) returns a Mission that does survey, resample, resurvey. Edit If you want a different sequence.

runnable.py

Provides AdaptiveResamplingNode, the dynos connect-compatible entry point. You probably don't need to edit this.

How the round-trip works

  1. You launch the resampler as a servant: dynos connect dynos_adaptive_resampling.runnable:AdaptiveResamplingNode. The servant idles, polling the backend for assignments.
  2. From a second terminal you build the mission and call execute_blocks. The first plan block surveys the source zone end-to-end.
  3. The planner reaches resample_zone(source_zone=site_alpha). It dispatches the assignment over HTTP to your servant.
  4. Your AdaptiveResampler runs _gather_historic_data, then _predict_new_zone, and returns the proposed ZoneProposal in telemetry. Writing it back as a new Zone object is a step you wire up (see below); the shipped stub does not create the zone.
  5. Once the new zone exists, the next plan block surveys it. The mission ends with full_abort (controlled ascent).

Heads up: the shipped do_resample only proposes a zone; it does not create it. Until you add the create_object call (shown commented in do_resample), the resampled_<zone> object never exists and the resurvey plan block below fails with "No plan found". Wire that step before running the full round-trip.

Replacing the stub

You will edit resampler.py. Two methods shape the proposal, and you must add the write-back:

_gather_historic_data(zone_name): return whatever your model needs. The shipped stub returns a few synthetic sensor readings ({"longitude", "latitude", "value"}); you replace it with calls to a shared database, ROS bag, the backend API (orch.list_objects(type_filter="zone")), an offline NetCDF, etc.

_predict_new_zone(historic_data): return a ZoneProposal with vertices, altitude, speed, coordinate_frame, and confidence. The shipped stub is a trivial heuristic -- it centers a 100 m x 100 m box on the highest-value reading -- which you replace with your model:

def _predict_new_zone(self, historic_data):
    features = self._extract_features(historic_data["sonar_readings"])
    prediction = self._model.predict(features)
    return ZoneProposal(
        vertices=self._prediction_to_polygon(prediction),  # (lon, lat) corners
        altitude=70.0,
        speed=0.8,
        coordinate_frame="geographic",
        confidence=float(prediction.confidence),
    )

Write-back (required for the resurvey to work): in do_resample, create the proposed zone on the backend before returning. The call is shown commented in the shipped code; give your AdaptiveResampler a backend handle (e.g. a RemoteOrchestrator) and uncomment it:

self._orch.create_object(
    "Zone", f"resampled_{source_zone_name}",
    vertices=proposal.vertices,
    altitude=proposal.altitude,
    speed=proposal.speed,
    coordinate_frame=proposal.coordinate_frame,
)

You can add fields to ResampleZoneParams (e.g. a confidence threshold, or whatever else you want), but don't change the Zone parameter: the backend's coverage planner reads Zone.vertices, Zone.coverage_width, etc. to draw tracklines, and it expects the public schema.

Test offline

Before pointing at the real backend, run the package's own tests:

pip install -e "dynos-adaptive-resampling/[dev]"
pytest dynos-adaptive-resampling/tests/ -v

These exercise _gather_historic_data and _predict_new_zone against a stub backend. No network or session needed.

Run it for real

Two terminals.

Terminal 1 is your resampler. This can be your laptop, a lab server, or the same machine as the backend; the backend dispatches each assignment to whichever servant is currently registered for resample_zone.

dynos login  # logins persist across terminals but expire after an hour
dynos session create --robot sentry-mock # Omitting '--robot sentry_mock' is valid but will omit important robot knowledge like coordinates, which is probably not what you want
dynos connect dynos_adaptive_resampling.runnable:AdaptiveResamplingNode

Leave it running. It executes resample_zone whenever the backend reaches that step.

Terminal 2 is mission. Create the source zone and run the adaptive mission:

dynos call create zone.json
from dynos_client import RemoteOrchestrator
from dynos_adaptive_resampling.mission import build_resample_mission

orch = RemoteOrchestrator.from_config(timeout_s=3600)
results = orch.execute_blocks(build_resample_mission("site_alpha"))
for r in results:
    print(r)

While it runs, monitor from a third terminal:

dynos call state --scope public      # current symbolic state, pruned only for the symbols you're expecting
dynos call goal                      # current goal
dynos call objects --type zone       # source + proposed zones

What the mission does, step by step

  1. Init. Takeover, descent, mode setup.
  2. Survey the source zone (full_coverage_of(site_alpha)).
  3. Resample. Plan dispatches resample_zone(source_zone=site_alpha) to your servant; your model proposes a new zone (and, once you wire the write-back, creates resampled_site_alpha).
  4. Resurvey. full_coverage_of(resampled_site_alpha) (requires the write-back from step 3).
  5. Recover. full_abort performs the controlled ascent.

Public API

Symbol From Purpose
resample_zone dynos_adaptive_resampling.domain The transition that fires your @Action.
ResampleZoneParams dynos_adaptive_resampling.domain Its parameter dataclass (source_zone: Zone).
resampling_complete dynos_adaptive_resampling.domain Fluent the transition adds.
AdaptiveResampler dynos_adaptive_resampling.resampler The class you edit.
AdaptiveResamplingNode dynos_adaptive_resampling.runnable The dynos connect entry point.
build_resample_mission(zone_name) dynos_adaptive_resampling.mission Survey, resample, resurvey.

Troubleshooting

Resampler never gets an assignment: The mission hasn't reached resample_zone yet. Check dynos call state --scope public.

No plan found: The source zone doesn't exist, has no vertices, or has coverage_width <= 0. Check dynos call objects --type zone.

Resurvey failed: The proposed zone is missing fields. resampled_* needs vertices (3+), coverage_width > 0, robot_width > 0, and coordinate_frame. The ZoneProposal dataclass populates these; if you bypassed it, double-check.

For cross-package issues (login, session, connection), see user_guide.md or dynos-client's README.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

dynos_adaptive_resampling-0.1.5.tar.gz (12.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

dynos_adaptive_resampling-0.1.5-py3-none-any.whl (10.2 kB view details)

Uploaded Python 3

File details

Details for the file dynos_adaptive_resampling-0.1.5.tar.gz.

File metadata

File hashes

Hashes for dynos_adaptive_resampling-0.1.5.tar.gz
Algorithm Hash digest
SHA256 3dcfad59852dee36dc206033aca45413d393b1e609ef5d5f0d2f38f972f120ac
MD5 47eacc80bbeebcb5c3ed135472519db3
BLAKE2b-256 b4b17c965eb1bd79d414529fe3b4ad82503524d1fbcc612c2aa69eecaa26d605

See more details on using hashes here.

File details

Details for the file dynos_adaptive_resampling-0.1.5-py3-none-any.whl.

File metadata

File hashes

Hashes for dynos_adaptive_resampling-0.1.5-py3-none-any.whl
Algorithm Hash digest
SHA256 00788b6ce2d59b201328eb9744915c9f4b753ffc346a81d7cb183cbe39d46cce
MD5 0a2854794ff665186437c629a2d3569c
BLAKE2b-256 2ad2c4904a4f0364057201718824a12cc1ba878b48699c002e24c5028bb2ac14

See more details on using hashes here.

Release history Release notifications | RSS feed

0.2.2

2 files

0.2.0

2 files

This release

0.1.5 This release

2 files

0.1.4

2 files

0.1.3

2 files

0.1.2

2 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