feat(agents): TypeSafe world state with way to the target, open sides and doorways - #4244
Draft
spomichter wants to merge 2 commits into
Draft
spomichter wants to merge 2 commits into
spomichter wants to merge 2 commits into
Conversation
…et with open sides and doorways What the model reads each tick: everything relative to the robot, target first and floor-level obstacles only, way_to_target (clear or blocked, what blocks it, the nearest way past on each side: open, corner, doorway with range, width and target_beyond), free space in 8 directions from footprints and the depth scan, the robot's own last 8 s, the side it is going around and ways already driven. Walls are published by demo-objects. Question and brief wording steer by that description; the answer schema, decoding and steering are unchanged. Found by the evo loop (exp_0013): 11 of 14 runs reach on seven habitat_nav tasks of which the 2026-09-18 run completed 2.
ts_state_bench.py scores habitat_nav cases for evo: the suite's grade when reached (not through a wall), else progress along the planner arm's driven route; one simulator at a time by file lock. ts_state_frozen.py is the gate that limits a search to the state builder and question text.
❌ 1 Tests Failed:
View the full list of 1 ❄️ flaky test(s)
To view more test analytics, go to the Test Analytics Dashboard |
This branch was successfully deployed
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Contribution path
Draft, stacked on #4216 (
feat/typesafe-nav-eval), which is stacked on the TypeSafe agent. The diff is the world state the agent sends to the model, the question wording that refers to it, and the scorer used to find it. The TypeSafe v2 rewrite is #4212; this needs porting to whichever agent lands.Problem
In the 84-case
habitat_navrun the TypeSafe arm reached 34 of 84. 45 of the 50 failures share one cause: the JSON state gives the model the straight-line bearing to the target and eight scan sectors, and the questions only ever turn toward the target, so anything on that line ends in a give-up, a forward/backward dither or a falsefinished. Measured on that run's requests: side and rear sectors read "5.0 m clear" in 816 of 840 readings (the scan is forward-facing and an empty sector is reported as max range), 22% of the 20 listed objects are above 1.5 m, and the target is last in the list in 121 of 168 requests.Solution
dimos/agents/typesafe/world_state.pybuilds one document per tick, everything relative to the robot:{"goal": "go to the couch", "robot": {"motion": "driving", "last_drive": {"x": "forward", "y": "none", "yaw": "turn_right"}, "recent": {"moved_m": 1.2, "turned_deg": 188, "target_closer_m": 0.9, "pattern": "advancing"}}, "objects": [{"target": true, "label": "couch", "bearing": "ahead_right", "bearing_deg": -16, "distance": "far", "distance_m": 10.19, "width_m": 1.5}, {"label": "potted_plant", "bearing": "left", "distance_m": 0.39, "width_m": 0.8}], "way_to_target": {"state": "blocked", "blocked_by": "wall", "blocked_at_m": 6.4, "open_sides": [{"side": "left", "kind": "corner", "bearing_deg": -1, "detour_deg": 15, "clear_m": 3.6}, {"side": "right", "kind": "doorway", "bearing_deg": -20, "detour_deg": 4, "range_m": 4.9, "width_m": 1.0, "target_beyond": true}], "going_around": {"side": "left", "for_s": 22}}, "free_space": {"ahead": {"clear_m": 3.4, "state": "clear", "by": "wall"}, "...": "8 directions"}}_objects_3d: the target first, then up to 5 obstacles within 4 m that overlap the 0.1-0.9 m body band above the robot's floor with a footprint of at least 0.2 m. No world coordinates.bearing_word:aheadis within 15 degrees;behindalways saysbehind_leftorbehind_right.way_to_target: one body-wide line from the robot to the target's box against the floor-level footprints of objects and walls and against the depth scan givesclear(+room,narrowed_on) orblocked(+blocked_by,blocked_at_m;obstaclewhen only the scan sees it).ray_castsends single rays every 5 degrees; on each side of the line the nearest direction that runs free past the blocker isopen, a range jump of 1 m between neighbouring rays iscorner.doorwaysfinds 0.7-3.0 m gaps in straight runs of wall boxes that the robot has a free line to and reports bearing, range, width and whether the target lies beyond that wall. One wall as seen from the robot; nothing is searched or chained, and no side is ranked or recommended.Memory(kept by the agent between ticks):recentover 8 s with a pattern word (starting, advancing, still, stuck, turning_on_the_spot, moving_without_getting_closer),going_around(the side the model's own picks began steering to, kept until it closes),been_there(a way whose far point lies on the robot's own trail older than 10 s), and 30 s of scan returns within 2.5 m so a direction seen blocked stays unlisted when the robot looks away.free_space: 8 directions from the same footprints plus the scan, each naming what is there;unseenwhen nothing is known.demo_objects.pypublishes walls (no longer excludes^wall).drive.py/TASK: same six answers. Forward, strafe and turn steer by a "steering bearing": the target's bearing when the line is clear, else the bearing of one listed open side, keeping the side already chosen.finishedneeds the target near, the robot stopped and no wall on the line.decode,_steer, the config and the module's streams are unchanged.misc/evals/ts_state_bench.py: evo benchmark overhabitat_navcases. Per case the suite's grade when reached, not counting a reach with a ground-truth wall between the final pose and the target box, else 0.4 x the furthest fraction reached of the planner arm's driven route; one simulator at a time by file lock; a run with no valid model ticks is a harness error, not a score.ts_state_frozen.py: the gate that limits a search to the state builder and question text (whitelist, AST pins on decoding/steering/config/streams and on the_tickdata flow, ground-truth hash, greps for planner or reference-route references and scene ids).Found by an evo loop of 13 experiments (
exp_0013). Same tasks, 84-case run (one attempt, 300 s) vs this branch (120 s):exp_0008state)An oracle run with the bearing to a look-ahead point on the true route reached 4 of 6, so the controller and model were not the limit. Input is ~3,500 tokens per tick (was ~3,980).
Known problems:
102344403_cabinet_2reached in the 84-case run and fails 0 of 2 here: the robot shuttles through the one doorway beside its start.nav_metricsreachedhas no line-of-sight test (a robot within 1 m of a target behind a wall counts as arrived, for every arm); the scorer here rejects that, the suite does not.How to Test
ruff, mypy (strict) and pre-commit pass on the changed files. The three type fixes after the scored experiment do not change behaviour.
Checklist