feat: blueprint namespaces#2725
Conversation
|
Preview deployment for your docs. Learn more about Mintlify Previews.
|
Greptile SummaryThis PR adds blueprint namespaces for running multiple module instances together. The main changes are:
Confidence Score: 4/5This is close, but these issues should be fixed before merging.
dimos/porcelain/remote_module_source.py; dimos/robot/unitree/go2/blueprints/basic/unitree_go2_multi.py; dimos/robot/unitree/go2/blueprints/basic/unitree_go2_multi_teleop.py Important Files Changed
Reviews (2): Last reviewed commit: "use multiple keyboard teleops" | Re-trigger Greptile |
| if cls.__name__ == name: | ||
| for instance_key, proxy in self._coordinator._deployed_modules.items(): | ||
| cls = self._coordinator._instance_classes[instance_key] | ||
| if name in (instance_key, cls.__name__): |
There was a problem hiding this comment.
Class Lookup Picks Arbitrary Instance
When two namespaced instances share a class, get_module("NamedModule") matches both entries through cls.__name__ and returns the first match in coordinator dict order. Local porcelain callers can receive the wrong robot's proxy instead of the same ambiguity error the coordinator raises for class-based lookup.
Note: If this suggestion doesn't match your team's coding style, reply to this and let me know. I'll remember it for next time!
|
|
||
| unitree_go2_multi = autoconnect( | ||
| *[namespace(f"robot{i}", GO2Connection.blueprint(ip=ip)) for i, ip in enumerate(_ips)], |
There was a problem hiding this comment.
❌ 2 Tests Failed:
View the full list of 3 ❄️ flaky test(s)
To view more test analytics, go to the Test Analytics Dashboard |
66a32c0 to
613b4f4
Compare
613b4f4 to
184dac8
Compare
| 4. Blueprint definition → `.global_config(simulation="mujoco")` | ||
| 5. CLI flag → `dimos --simulation run ...` | ||
|
|
||
| Environment variables and `.env` values must be prefixed with `DIMOS_`. |
There was a problem hiding this comment.
Why'd we change this? Seemed like a good pattern to me
184dac8 to
a283283
Compare
| descriptors = self._coord.call("list_modules") | ||
| self._descriptors = {d.class_name: d for d in descriptors} | ||
| # rpc_name is empty when talking to an older daemon. | ||
| self._descriptors = {(d.rpc_name or d.class_name): d for d in descriptors} |
There was a problem hiding this comment.
Remote lookup diverges
RemoteModuleSource now keys descriptors only by rpc_name, but it does not keep the class-name fallback and ambiguity check that the local source uses. With remote instances such as robot0/go2connection and robot1/go2connection, a porcelain access like get_module("GO2Connection") raises KeyError instead of reporting that the class name is ambiguous. Remote callers should get the same clear ambiguity behavior as local callers, while exact instance-name lookups continue to work.
| _ips = global_config.processed_robot_ips | ||
|
|
||
| unitree_go2_multi = autoconnect( | ||
| *[namespace(f"robot{i}", GO2Connection.blueprint(ip=ip)) for i, ip in enumerate(_ips)], | ||
| ).global_config(n_workers=max(2, 2 * len(_ips)), robot_model="unitree_go2") |
There was a problem hiding this comment.
Import still fails This blueprint still reads
global_config.processed_robot_ips during module import. When dimos run unitree-go2-multi is called without ROBOT_IPS or --robot-ips, the import raises ValueError before the CLI can load the blueprint and report the missing fleet config cleanly. The IP check should run during blueprint loading or build-time config handling instead of at import time.
| _ips = global_config.processed_robot_ips | ||
|
|
||
| unitree_go2_multi_teleop = autoconnect( | ||
| *[ | ||
| namespace( | ||
| f"robot{i}", | ||
| GO2Connection.blueprint(ip=ip), | ||
| KeyboardTeleop.blueprint(), | ||
| ) | ||
| for i, ip in enumerate(_ips) | ||
| ], | ||
| ).global_config(n_workers=max(2, 2 * len(_ips)), robot_model="unitree_go2") |
There was a problem hiding this comment.
Teleop import fails The teleop multi blueprint has the same import-time config read. If
ROBOT_IPS or --robot-ips is missing, selecting unitree-go2-multi-teleop raises from global_config.processed_robot_ips while importing the module, before the CLI can handle the missing configuration. This makes the registered blueprint unavailable instead of producing a controlled config error.
Problem
Closes #2491
Solution
namespace(prefix, *blueprints, expose=...). It prefixes instance names, stream topics, RPC topics and TF frames of everything inside. Streams listed inexposestay global so shared modules can consume them. Module references resolve inside the namespace first, then outward.-o robot0/go2connection.ip=10.0.0.5or envROBOT0_GO2CONNECTION__IP=....--simulationeach robot gets its own MuJoCo process and the IPs are ignored. Fixed the hardcoded TF frames inGO2Connection(base_link, camera_link, camera_optical) to honor the namespace prefix. The parent world frame stays shared so all robots hang off one tree root.How to Test
Two MuJoCo windows and two teleop windows open. Click one teleop window and drive with WASD. Only that robot moves.
dimos topic echo /robot0/odomshows the namespaced topics. On real robots use their IPs and drop--simulation.Contributor License Agreement