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 the 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

build_resample_mission(zone) returns a Mission that does survey, resample, resurvey. Pass the Zone object (e.g. Zone(name="site_alpha")), not its name string. 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. Connecting it also registers this package's domain module with the backend (so resample_zone becomes plannable and dispatches back to your node) -- no edits to the backend or the Sentry domain. The backend must have this package installed; for the local demo below that is the same machine.

How the round-trip works

  1. You launch the resampler as a servant: dynos connect dynos_adaptive_resampling.runnable:AdaptiveResamplingNode. The servant registers its transition + domain with the backend, then idles, polling 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 creates the new Zone on the backend (resampled_site_alpha) so the follow-up survey can plan coverage over it.
  5. Once the new zone exists, the next plan block surveys it.

The vehicle-lifecycle bookends -- takeover, descent, and abort/recovery -- are inserted by the planner and the on-vehicle safety system. The mission you author is just the three survey/resample/resurvey blocks; you never hand-write a takeover or an abort.

Replacing the stub

You will edit resampler.py. Two methods shape the proposal:

_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, new_zone_name, coverage_width, robot_width): return a ready-to-create Zone (the domain object) -- not a side-car type. The shipped stub is a trivial heuristic (it centers a 100 m x 100 m box on the highest-value reading); replace it with your model:

from dynos_sentry.sentry import Zone

def _predict_new_zone(self, historic_data, new_zone_name, coverage_width, robot_width):
    features = self._extract_features(historic_data["sonar_readings"])
    prediction = self._model.predict(features)
    return Zone(
        name=new_zone_name,
        vertices=self._prediction_to_polygon(prediction),  # (lon, lat) corners
        altitude=70.0,
        speed=0.8,
        coordinate_frame="geographic",
        coverage_width=coverage_width,   # sensor swath; keep > 0 or coverage can't plan
        robot_width=robot_width,
    )

do_resample then calls create_object(new_zone) for you. It gets a backend handle from RemoteOrchestrator.from_config() (the config dynos connect wrote); it also reads the source zone's coverage_width/robot_width and threads them in so the resurvey flies the same sensor swath (falling back to sane defaults if the source can't be read).

You can add fields to ResampleZoneParams (e.g. a confidence threshold), 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, _predict_new_zone, and do_resample (with a fake backend that records the created zone). 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 the mission. Create the source zone and run the adaptive mission:

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

orch = RemoteOrchestrator.from_config(timeout_s=3600)
results = orch.execute_blocks(build_resample_mission(Zone(name="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 + resampled zones

What the mission does, step by step

The mission you author is three blocks; the planner and the on-vehicle safety system add the lifecycle steps around them.

  1. Survey the source zone (full_coverage_of(site_alpha)). The planner prefixes the takeover and descent it needs.
  2. Resample. The plan dispatches resample_zone(source_zone=site_alpha) to your servant; your model creates resampled_site_alpha on the backend.
  3. Resurvey (full_coverage_of(resampled_site_alpha)).

Recovery (full_abort, controlled ascent) is owned by the on-vehicle safety system, not authored in the mission.

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) 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 resampled_* zone is missing fields. It needs vertices (3+), coverage_width > 0, robot_width > 0, and coordinate_frame. The shipped _predict_new_zone sets all of these; if you replaced it, make sure your Zone still carries them.

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.2.2.tar.gz (13.4 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.2.2-py3-none-any.whl (11.1 kB view details)

Uploaded Python 3

File details

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

File metadata

File hashes

Hashes for dynos_adaptive_resampling-0.2.2.tar.gz
Algorithm Hash digest
SHA256 fa75d116d0614852831a5274ddee627fbc424e1606a14d13d9313f66749238e9
MD5 d0cff54092613c57e006914298e14016
BLAKE2b-256 fed14c07a12b773f928b4feef5bf5f59c4de7b2e12e5057c62c2a2d90b1903a2

See more details on using hashes here.

File details

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

File metadata

File hashes

Hashes for dynos_adaptive_resampling-0.2.2-py3-none-any.whl
Algorithm Hash digest
SHA256 7c52d935966373975149fea99dc24da6ca6fd21d11783402e31747d0957c72b2
MD5 70c8ce127c5e5fbe2559aa521ac8d831
BLAKE2b-256 4d45e326a316c840544f74d2d1f177b9b93cdee532958409aa20526156b8a218

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.2.2 This release

2 files

0.2.0

2 files

0.1.5

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