Locate objects with a running PerceptionLocalize stack over MCP (`state`, `localize`) - probe the machine, build the time window, watch labels on a schedule, narrow an object's position, change params per call, and tell where a failure comes from. Use whenever a blueprint with PerceptionLocalize and McpServer runs, such as go2-localize or xarm-localize-live.
92%
Does it follow best practices?
Run evals on this skill
Adds up to 20 points to the overall score
Passed
No findings from the security scan
localize answers from memory: the colour frames the module has embedded,
lifted to 3D through depth or lidar. It does not look at the current frame.
Every answer is a verified 3D object with a score and a view count, and an
empty answer is an answer.
nvidia-smi --query-gpu=name,memory.used,memory.total --format=csv,noheader
uv run dimos mcp call statestate() returns ready: N frames embedded, localize will answer or
not ready: <stage>. Until it reads ready, localize returns its stage
instead of an answer.Error: no running MCP server (is DimOS running?) means the stack is down.
Check uv run dimos status and report it. Do not stop or restart the stack.uv run dimos mcp call localize -j '{"objects": "chair,door", "start": -30, "duration": 30}' --timeout 300localize(objects, start=-10, duration=10, params="") returns once the answer
is built. Send the next call after it returns.objects is one label, or a few separated by commas. The labels of one call
share one detector pass per frame.--timeout 300 or set MCP_TIMEOUT=300.start and duration are seconds over the embedded frames the module holds.
| arguments | window |
|---|---|
start=-10, duration=10 (default) | the last 10 s |
start=-60, duration=60 | the last minute |
start=-60, duration=20 | from 60 s ago to 40 s ago |
start=30, duration=20 | 20 s, from 30 s after the oldest frame held |
start counts back from the newest embedded frame, a positive one
forward from the oldest frame still held. The module holds horizon_s of
frames, 600 s by default, so once memory is full the oldest frame moves.mobile=True),
each the sharpest of its slot.window A s to B s of C s of feed, N frames. With N = 0 nothing was read
and the answer is memory only.accept_score and min_views
aside. A window of frames never read for a label costs detector passes;
asking the same window again is nearly free.window 0.0s to 30.0s of 28.3s of feed, 76 frames
'chair' at (-0.97, 7.31, 0.40) in world score=0.49 views=6 id=ed6e5cde seen 24s ago
no verified detection of 'bag'id names the same object for as long as the module runs.score is the detector's best score for the object. Compare scores within one
label only; the scale changes with the wording.views counts the distinct camera positions, 1 cm apart, that saw the object.
An object needs 2, and a camera that does not move adds none. A camera that
never moves, such as a fixed top view, stays silent until min_views is 1:
pass '{"min_views": 1}', which reads no frame again.seen Ns ago is the age of the newest sighting.no verified detection means nothing passed the gates at these params. It is
not proof that the object is absent.Four labels on a rolling 5 s window, one call after another:
uv run dimos mcp call localize -j '{"objects": "chair,door,bag,plant", "start": -5, "duration": 5}' --timeout 60params the same on every call. Memory is per
exact label string, and frames read under other params are read again,
unless only accept_score or min_views changed.seen Ns ago. An object that moved farther than cluster_radius_m
gets a new id at its new position, and the old id stays at the old one.The position is the newest sighting's, so a closer sighting refines it.
{"objects": "red mug", "start": -5, "duration": 5}.
A sighting within cluster_radius_m of the object's centre joins it under
the same id, and the position moves to the new sighting.views grew and seen is near 0 s.At a table, a walking robot's room-scale params are coarse for small objects:
| field | room (go2) | desk (xarm) | desk (dual_yam) |
|---|---|---|---|
cluster_radius_m: sightings this close are one object | 0.30 | 0.08 | 0.08 |
fuse_voxel_m: object cloud resolution | 0.03 | 0.01 | 0.01 |
min_camera_range_m: closer sightings are dropped | 0.5 | 0.28 | 0.07 |
surface_patch_max_rise_m: a sighting this flat on the support is surface | 0.08 | 0.003 | 0.003 |
Pass desk-scale field overrides on every call for that label while working at the table. Objects the label already has from room-scale calls keep how they were built; a label first asked at the table is built at desk scale.
Each blueprint sets its rig's LocalizeParams (types.py) at construction
(desk-scale defaults in LocalizeParams(), room-scale GO2_PARAMS in
go2_localize.py).
params is a JSON object of LocalizeParams field overrides for that call
only. The next call without it is back on the module's params, the ones its
blueprint set.
params value | meaning |
|---|---|
"" | the module's params |
'{"accept_score": 0.45}' | these fields on the module's params |
uv run dimos mcp call localize -j '{"objects": "apple", "params": "{\"accept_score\": 0.45}"}' --timeout 300
uv run dimos mcp call localize -j '{"objects": "apple", "params": "{\"min_views\": 3}"}' --timeout 300| field | acts on | what it gates |
|---|---|---|
accept_score | every object of the label, at once | best score an object needs to be answered |
min_views | every object of the label, at once | camera positions an object needs |
candidate_floor | frames read by this call | detector score that forms a box; lower means more boxes and more GPU memory |
cluster_radius_m | frames read by this call | sightings this close are one object |
max_object_extent_m, min_points, min_camera_range_m | frames read by this call | size, points and camera distance a sighting needs |
fuse_voxel_m | objects a sighting of this call joins | resolution of the object's cloud |
verify_radius_m, peak_prominence | frames read by this call | how many frames retrieval hands to the detector |
accept_score and min_views act only when the answer is built: changing
them reads no frame again and applies at once to everything remembered for
the label. Try them first.unexpected keyword argument.LocalizeParams in
types.py.red mug,
wooden crate. Broad or overlapping labels make many boxes.Remote torch.OutOfMemoryError, halve the labels per call.Embedding, detection and segmentation work from the image and find almost any object. Lifting a detection to 3D needs depth at the object, and that depends on the rig. Most failures to get a position come from the lift or from the rig, not from the image models.
ids. The one seen most recently matches the current
odometry.params, the score fields candidate_floor and
accept_score first.fuse_voxel_m is 0.01 in LocalizeParams() and 0.03
in go2. For GraspGenX, go as low as 0.003, because it can reject clouds
fused at larger voxels. The voxel applies every time a sighting joins an
object, so pass it on every call for that label, for example
'{"fuse_voxel_m": 0.003}'. A cloud already fused coarser
does not regain detail.Tuning params offline on a recording, before deploying them, is in README.md.
dimensionalOS/dimos
d2fb73c
If you maintain this skill, you can claim it as your own. Once claimed, you can manage eval scenarios, bundle related skills, attach documentation or rules, and ensure cross-agent compatibility.