Skip to content

go2 mem2 recorder fixes, misc fixes, new recording#2109

Open
leshy wants to merge 6 commits into
mainfrom
ivan/fix/go2recording3
Open

go2 mem2 recorder fixes, misc fixes, new recording#2109
leshy wants to merge 6 commits into
mainfrom
ivan/fix/go2recording3

Conversation

@leshy
Copy link
Copy Markdown
Contributor

@leshy leshy commented May 16, 2026

No description provided.

@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 16, 2026

Greptile Summary

This PR fixes recorder timestamp handling in memory2, adds a tf identity-transform shortcut, introduces lidar on/off control for the Go2, and refactors message module imports in the CLI topic tooling. A new SLAM-abuse recording (go2_slamabuse3.db) is also committed via LFS.

  • memory2/module.py: Switches stream.append to wall-clock time.time() and removes ts from the warning log — but the format string still has four %s placeholders, leaving the third one (at time %s) without an argument, which silently breaks the warning every time a missing-tf event fires.
  • tf.py: Adds an identity-transform shortcut for same-frame lookups and makes the get() signature explicit — both are correct improvements.
  • Go2 lidar control: Adds set_lidar across the connection protocol, config, RPC, and no-op stubs for sim/replay connections, with an optional lidar_auto_off flag that disables the lidar on stop().

Confidence Score: 3/5

Two defects in the recorder need fixing before merging: the logger format mismatch will silently swallow missing-tf diagnostics, and the timestamp decoupling between tf lookup and stream storage may corrupt recording fidelity for sensor-timestamped data.

The recorder changes in module.py introduce a broken log format (4 placeholders, 3 args) that suppresses diagnostic output every time a tf lookup fails, and separately stores stream entries under wall-clock time while still resolving pose transforms against the message's original timestamp — creating a mismatch between stored timestamps and their associated poses. The lidar control and tf identity-shortcut additions look correct, and the CLI topic import refactor works if the message package layout uses per-class sub-modules as expected.

dimos/memory2/module.py has two issues that warrant a close look; dimos/robot/cli/topic.py should be verified against the actual message package layout to confirm every message type is reachable via the new sub-module import path.

Important Files Changed

Filename Overview
dimos/memory2/module.py Two bugs introduced: logger warning has 4 format placeholders but only 3 args (silent format failure), and stream.append now uses wall-clock time instead of the message's own timestamp, decoupling recording index timestamps from the tf-lookup timestamps.
dimos/protocol/tf/tf.py Added identity-transform shortcut when parent_frame == child_frame; explicit typed signature replaces *args/**kwargs forwarding. Correct and clean.
dimos/robot/cli/topic.py Both _resolve_type and on_msg now import per-class sub-modules; correct if every message class lives in its own file, but will silently break types that are only accessible via package init exports.
dimos/robot/unitree/connection.py New set_lidar method uses call_soon_threadsafe to schedule a publish_without_callback with a plain string payload ("ON"/"OFF"), consistent with the topic's std_msgs::String contract.
dimos/robot/unitree/go2/connection.py Adds lidar_auto_off config, wires set_lidar into startup/stop, exposes RPC endpoint, and stubs ReplayConnection. Startup unconditionally calls set_lidar(True) even though the Go2 boots with lidar on — redundant but harmless.
dimos/robot/unitree/go2/cli/go2tool.py Auto-selects the single BLE device instead of prompting for "1"; cleans up the interactive device-selection branch. Straightforward UX improvement.

Comments Outside Diff (1)

  1. dimos/memory2/module.py, line 313-318 (link)

    P1 Logger format string / argument count mismatch

    The format string contains four %s placeholders ([%s], '%s', at time %s, msg ts: %s) but only three arguments are now passed (name, frame_id, getattr(msg, "ts", None)). Removing ts from the argument list left the third placeholder (at time %s) without a corresponding value. Python's logging infrastructure will catch the resulting TypeError internally, so the app won't crash, but the warning message will silently fail to emit whenever a missing-tf event occurs — exactly when operators need that diagnostic information.

Reviews (1): Last reviewed commit: "recorder uses system time, new slam reco..." | Re-trigger Greptile

Comment thread dimos/memory2/module.py
getattr(msg, "ts", None),
)
stream.append(msg, ts=ts, pose=pose)
stream.append(msg, ts=time.time(), pose=pose)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Recording timestamp no longer tracks message time

ts was previously computed as getattr(msg, "ts", None) or time.time() and passed through to both the tf lookup and stream.append. It is still used for the tf lookup on line 309, but stream.append now always receives time.time(). Any message that carries its own hardware or protocol timestamp will be stored in the stream under the wall-clock arrival time instead of the message's own ts. For replayed or sensor-timestamped data this will cause the recording index to disagree with the pose timestamps that were resolved against the message's original ts.

Comment thread dimos/robot/cli/topic.py
Comment on lines 37 to +44
def _resolve_type(type_name: str) -> type:
for module_name in _modules_to_try:
try:
module = importlib.import_module(module_name)
if hasattr(module, type_name):
return getattr(module, type_name) # type: ignore[no-any-return]
module = importlib.import_module(f"{module_name}.{type_name}")
except ImportError:
continue
if hasattr(module, type_name):
return getattr(module, type_name) # type: ignore[no-any-return]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 _resolve_type no longer handles types that are exported from a package __init__

The old code imported the package (e.g. dimos.msgs.geometry_msgs) and checked whether the class was an attribute of that module — which works for packages that re-export their classes in __init__.py. The new code tries to import a sub-module named after the type (e.g. dimos.msgs.geometry_msgs.Twist). If that sub-module doesn't exist but the class is still accessible via the package init, ImportError is caught, the loop continues, and all entries are exhausted, ending in a ValueError. Any call-site that previously worked through the package-level export will silently break. Were the dimos.msgs.* packages recently reorganised so every message class now lives in its own sub-module? If the package inits still re-export classes, the old approach would still work and the new one may miss some types.

@codecov
Copy link
Copy Markdown

codecov Bot commented May 16, 2026

Codecov Report

❌ Patch coverage is 32.14286% with 19 lines in your changes missing coverage. Please review.
✅ All tests successful. No failed tests found.

Files with missing lines Patch % Lines
dimos/robot/unitree/go2/cli/go2tool.py 0.00% 7 Missing ⚠️
dimos/robot/unitree/go2/connection.py 44.44% 5 Missing ⚠️
dimos/robot/unitree/connection.py 25.00% 3 Missing ⚠️
dimos/protocol/tf/tf.py 60.00% 1 Missing and 1 partial ⚠️
dimos/memory2/module.py 0.00% 1 Missing ⚠️
dimos/robot/unitree/mujoco_connection.py 50.00% 1 Missing ⚠️

📢 Thoughts on this report? Let us know!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant