Run the DYNOS planner in the loop with an external vehicle simulator
Project description
dynos-sim-bridge
A worked example: run the DYNOS planner in the loop with an external vehicle
simulator. This package is scaffolding: it ships a stub SimHardware plus a
trivially simple StochasticSim that you replace with calls into your
simulator, and the wiring (runnable.py, mission.py) that lets dynos connect find it.
It demonstrates the two channels a simulator needs, both on the one
SimHardware class:
- Motion out (planner -> simulator):
SimHardwareimplements thegototransition by commanding your simulator, exactly like the real Sentry hardware class commands the vehicle. - State in (simulator -> planner): the vehicle's real position flows back
through a servant belief -- a
@Belief(fluent=at)callback the backend polls after each step, exactly the way it runs a local@Belief. Whatever waypoint the simulator reports becomesat(<waypoint>)in the planner's world. If the simulator ended up somewhere other than commanded, the belief reflects reality and the planner replans from there.
There is no separate position-sync step and no out-of-band set_belief: the
planner always builds on the observed position because the observation is the
channel.
Install
You will be modifying the source, so install editable:
pip install -e dynos-sim-bridge
This pulls in dynos-client and dynos-sentry-domain.
What's in this repository
bridge.py
Provides StochasticSim (the stand-in simulator) and SimHardware, which wires
it to the planner:
@Action(transition=goto) go_to: command the simulator to drive to the leg's endpoint.@Belief(fluent=at) observe_position: report the vehicle's real symbolic position back to the planner.
Everything above the Edit away down here line is plumbing you should leave
alone; replace StochasticSim with a bridge to your real simulator (same
goto/position shape).
mission.py
Provides build_sim_survey_mission(zone_name). Edit if you want a different
sequence.
runnable.py
Provides SimBridgeNode, the dynos connect-compatible entry point. You
probably don't need to edit this.
SimHardwareclaims thegototransition. Registering it replaces whatever was executinggoto(e.g. thesentry-mockhardware's owngoto) -- that is the point: your simulator becomes the motion executor. Run the bridge instead of a second motion provider, not alongside one.
Why a servant belief, not create_object + set_start
The tempting way to tell the planner where the vehicle is each tick is to create
a current_location coordinate and reset the initial state. Don't:
set_startre-derives the whole initial state; it is a planning-time input, not a per-tick observation channel.- Two points at the same lon/lat and altitude are the same physical point,
so a
current_locationthat lands on a known waypoint is collapsed onto that waypoint by the backend, and you then have to discover the canonical name.
A servant belief skips all of that: the backend asks your servant "where is the
vehicle at?" and your observe_position answers with the at fluent symbol
over a waypoint the planner already knows.
How the round-trip works
- You launch the bridge as a servant:
dynos connect dynos_sim_bridge.runnable:SimBridgeNode. RegisteringSimHardwareadvertises both thegotoaction and theatbelief, then it idles. - From a second process you set the goal and execute a mission. No position sync is needed first -- the planner learns the position from the belief.
- The planner expands
full_coverage_of(zone)intogotolegs and dispatches each to your servant. SimHardware.go_todrives the simulator toward the leg's endpointx. Then the backend pollsobserve_position:- Vehicle is at
x: the observation confirms thegotoeffectat(x); the planner continues to the next leg. - Vehicle ended up at
y(current, obstacle, missed move): the observation reportsat(y); the effectat(x)is not confirmed, so the step gates and the planner replans toward the same goal fromy. This is the planner operating on updated symbolic knowledge -- the point of running it in the loop.
- Vehicle is at
- The mission ends with
full_abort(controlled ascent).
The servant belief goes through the client API: @Belief/BeliefResult are
exported from dynos_client, so a remote servant running with dynos_client
alone reports beliefs exactly as an in-tree robot class does with the
backend-side @Belief.
Replacing the stub
Replace StochasticSim with a small adapter over your simulator, keeping the
same two methods:
goto(target): command your simulator to drive to target (a waypoint name)
and return whether it arrived.
position(): return the name of the waypoint the vehicle is currently on, or
None when it is between waypoints (the belief then reports "unchecked" and the
planner keeps its prior position).
Coordinates follow the project convention: (longitude, latitude), degrees for
geographic, meters for local_enu. Altitude is part of a point's identity.
Test offline
Before pointing at the real backend, run the package's own tests:
pip install -e "dynos-sim-bridge/[dev]"
pytest dynos-sim-bridge/tests/ -v
These exercise StochasticSim, the goto plumbing, and the at belief. No
network or session needed. The end-to-end loop (backend polls the belief and
continues or replans) is covered by the sentry integration test
tests/sentry/test_servant_beliefs.py.
Run it for real
Two terminals.
Terminal 1 is your simulator bridge:
dynos login # logins persist across terminals but expire after an hour
dynos session create --robot sentry-mock
dynos connect dynos_sim_bridge.runnable:SimBridgeNode
Leave it running. It executes goto whenever the backend reaches a leg, and
answers the at belief whenever the backend polls it.
Terminal 2 is the mission. Create the survey zone and run:
dynos call create zone.json
from dynos_client import RemoteOrchestrator
from dynos_sim_bridge.mission import build_sim_survey_mission
orch = RemoteOrchestrator.from_config(timeout_s=3600)
for r in orch.execute_blocks(build_sim_survey_mission("site_alpha")):
print(r)
Public API
| Symbol | From | Purpose |
|---|---|---|
SimHardware |
dynos_sim_bridge.bridge |
The robot class you edit; executes goto, observes at. |
StochasticSim |
dynos_sim_bridge.bridge |
The trivial stand-in simulator you replace. |
SimBridgeNode |
dynos_sim_bridge.runnable |
The dynos connect entry point. |
build_sim_survey_mission(zone) |
dynos_sim_bridge.mission |
Take over, survey, recover. |
Troubleshooting
Bridge never gets an assignment: the mission hasn't reached a goto leg. Check
dynos call state --scope public.
at(<name>) unresolved: the name your position() returned isn't a registered
object. Return the name of a waypoint the planner knows (e.g. the leg's
endpoint), not an ad-hoc string.
For cross-package issues (login, session, connection), see user_guide.md or
dynos-client's README.
Project details
Release history Release notifications | RSS feed
Download files
Download the file for your platform. If you're not sure which to choose, learn more about installing packages.
Source Distribution
Built Distribution
Filter files by name, interpreter, ABI, and platform.
If you're not sure about the file name format, learn more about wheel file names.
Copy a direct link to the current filters
File details
Details for the file dynos_sim_bridge-0.1.5.tar.gz.
File metadata
- Download URL: dynos_sim_bridge-0.1.5.tar.gz
- Upload date:
- Size: 10.6 kB
- Tags: Source
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.8.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
37ce2a2f14b1d511510b9137b5438e3af207fb57a48b4b7d4bc2f5572214cf9d
|
|
| MD5 |
44716262ca7e8caf6cb2fecc201d1d5d
|
|
| BLAKE2b-256 |
32860babc1f3cd3309a3511f52cf7d22644c68e2d1fc15ee285b56043a889f0f
|
File details
Details for the file dynos_sim_bridge-0.1.5-py3-none-any.whl.
File metadata
- Download URL: dynos_sim_bridge-0.1.5-py3-none-any.whl
- Upload date:
- Size: 8.6 kB
- Tags: Python 3
- Uploaded using Trusted Publishing? No
- Uploaded via: twine/6.1.0 CPython/3.8.10
File hashes
| Algorithm | Hash digest | |
|---|---|---|
| SHA256 |
42f3356f3dc071ba0d144e7df505d0da0475d595df00518267e53c6cbb2396fb
|
|
| MD5 |
b11f7f5e33676dfd5f249ade4c72e4e8
|
|
| BLAKE2b-256 |
55fcf93003937178c3bd606ab73415cfe260e22c36ea4230a5c225d9ccc68cf8
|