Skip to content

feat: mixed-embodiment simulator, PX4 drones and legged robots in one MuJoCo world - #3819

Open
Ez4ezka wants to merge 4 commits into
dimensionalOS:mainfrom
Ez4ezka:feat/mixed-embodiment-sim
Open

feat: mixed-embodiment simulator, PX4 drones and legged robots in one MuJoCo world#3819
Ez4ezka wants to merge 4 commits into
dimensionalOS:mainfrom
Ez4ezka:feat/mixed-embodiment-sim

Conversation

@Ez4ezka

@Ez4ezka Ez4ezka commented Aug 31, 2026

Copy link
Copy Markdown

What this is

One MuJoCo world that flies N quadrotors running real, unmodified PX4 firmware next to M simulated Unitree Go1 quadrupeds, all commanded through namespaced DimOS modules, a fleet coordinator, and MCP tools (plus an optional natural-language agent). It replaces the previous Gazebo drone path, which could not fly three drones in realtime on a laptop.

Someone with a laptop and this branch can be flying a mixed fleet in about 15 minutes: see the Quickstart on a fresh machine section at the top of dimos/simulation/px4_hil/README.md. Every dependency tier degrades gracefully (no meshes -> primitive airframes, no trained policy -> hand-tuned gait), so nothing blocks a first run.

How it works

  • PX4 in lockstep over HIL: the bridge feeds HIL_SENSOR/HIL_GPS and owns PX4's clock, so a slow machine runs the world slower instead of starving the EKF. Runs 5 to 18x realtime depending on fleet size and machine.
  • Aerodynamics: motor spool lag, rotor H-force drag, ground effect, and optional wind with OU gusts (SIM_WIND_N/E, SIM_GUST_STD). Verified: position hold within ~0.1 m in 3 m/s wind with gusts.
  • Legged robots: real Menagerie Go1 driven by the repo's trained ONNX policy (goto measured 6/6 targets), with a primitive fallback that needs no assets.
  • One safety story, layered: dispatch-time operating radius, separation admission, airborne gate; in-flight PX4 geofence and datalink-loss failsafe (the fleet RTLs and lands autonomously if the daemon dies, verified); ground fence and inter-robot proximity halt for the quadrupeds; fleet safety broadcasts are repeated and delivery-verified with per-robot re-send (a lost broadcast once stranded an armed drone at altitude; that incident is now a regression test).
  • Real assets, no repo bloat: X500 meshes are fetched and decimated by tools/fetch_x500_meshes.py (BSD-3, from PX4-gazebo-models) and gitignored.

Timeouts and clocks

Every PX4 timeout parameter runs on the sim clock (10 to 18x wall speed here), while DimOS-side loops tick in wall time. sim_params.py scales COM_DL_LOSS_T, COM_OF_LOSS_T, SIM_BAT_DRAIN accordingly and documents why; robot-side control loops (the quadruped's move controller) run inside the bridge at physics rate for the same reason.

Verification

  • 101 tests in this diff (unit + constructor/step smoke tests at every module seam, wire-format contract tests between coordinator and modules).
  • Live-verified flows: 2-drone sweep + RTL, 2-dog missions, staged air-then-ground sweep (sweep_then_ground), daemon-kill autonomous RTL, wind hold, collision-guard halt between converging dogs.
  • ruff check clean on every touched file.

Known limits (documented in the README)

  • No aerodynamic model beyond the terms listed (no downwash coupling between vehicles).
  • Separation guardrail is admission control, not in-flight collision avoidance.
  • The trained walking policy is Go1-only; fleet size is fixed at daemon start.

🤖 Generated with Claude Code

Ez4ezka and others added 4 commits August 31, 2026 11:38
One MuJoCo world drives N PX4 SITL instances over the HIL interface (TCP
4560+i, sim owns PX4's clock via lockstep) alongside M simulated quadrupeds.
Includes rotor aerodynamics (spool lag, H-force drag, ground effect, optional
OU-gust wind), real Holybro X500 assets fetched on demand (gitignored), a
one-command bring-up script with honest readiness gating, and sim-time-scaled
PX4 parameters (battery, geofence, datalink-loss failsafe).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Per-vehicle Px4DroneModule (namespaced), SwarmCoordinator with layered
guardrails (operating radius, separation admission, airborne gate, altitude
cap), fleet maneuvers (grid sweep, line formation, investigate, staged
air-then-ground sweep), and a fleet-level GCS presence that satisfies PX4's
arming checks once NAV_DLL_ACT is set. Safety broadcasts repeat 3x and are
verified against reported flight modes with per-robot re-send: a lost rtl_all
once left an armed drone hovering while its twin landed, and that incident is
now a regression test.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
LeggedSimModule mirrors the drone module on the shared fleet bus (same state
shape, robot_class field) so coordinator queries span embodiments. Real
Menagerie Go1 driven by the repo's trained ONNX policy when assets are
present, primitive fallback otherwise; heading-held relative move runs inside
the simulator at physics rate; ground fence and inter-robot proximity halt.
mixed-fleet-mcp and mixed-fleet-agentic compose N drones + M dogs from
SIM_DRONES/SIM_DOGS.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
…gent loop

Skills from namespaced module instances qualify as instance/module/skill only
when ambiguous; the LLM client shows sanitized aliases (OpenAI rejects '/' in
function names, and one bad name 400s the whole request) while calling the
server by the real name; the agent message loop survives a failed turn
instead of dying silently behind a 'thinking...' UI.

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@github-actions github-actions Bot added the first-time-contributor PR opened by an author who had not previously committed to this repository label Aug 31, 2026
@greptile-apps

greptile-apps Bot commented Aug 31, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

This change introduces mixed PX4 and legged-robot fleet simulation, fleet coordination, namespaced MCP skills, telemetry handling, geospatial guardrails, and fleet safety-command delivery checks.

A drone movement request can be accepted within the configured separation distance when another connected, armed drone has telemetry that is only slightly stale. The affected movement commands are goto_drone, goto_drone_global, and investigate.

Fleet safety-command verification also stops retrying an aircraft when the telemetry field needed to verify delivery is absent, allowing a lost safety broadcast to go without an individually addressed resend.

T-Rex validation blocked

The focused fleet safety retry reproduction could not reach the coordinator because the dimos_lcm package is missing. The prepared virtual environment also references a nonexistent Python executable.

Confidence Score: 3/5

Not safe to merge until stale armed peers are handled conservatively during separation checks and incomplete verification telemetry remains eligible for safety-command retries.

A focused runtime reproduction confirmed that the real coordinator publishes unsafe movement commands when an armed peer is just beyond the freshness window. The incomplete-telemetry retry behavior remains a clear control-flow concern, but its focused runtime reproduction was blocked by unavailable runtime dependencies.

Files Needing Attention: dimos/robot/drone/px4_swarm_coordinator.py, especially _violates_separation and _verify_fleet_command.

T-Rex T-Rex Logs

What T-Rex did

  • Generated a proof for the posted P1 finding and attached the focused reproduction source and runtime output to support reviewer inspection.
  • Validated the contract by running the source harness to exercise _verify_fleet_command('rtl', ['drone1']), captured emitted command targets, and asserted the expected resend behavior, while confirming no source files outside the uploaded artifacts were modified and that the environment blocker was identified as the root cause.
  • Generated a second proof for the posted P1 finding to corroborate the ongoing validation work.
  • Performed focused validation that showed goto_drone and goto_drone_global each published one command, investigated drone1’s and drone2’s positions, and concluded that maximum agent steps had been reached with no further work for the requested validation.

View all artifacts

T-Rex Ran code and verified through T-Rex

Comments Outside Diff (1)

  1. General comment

    P1 Stale airborne peers are omitted from separation admission

    • Bug
      • A connected, armed peer with telemetry age 0.76 seconds is excluded from the guardrail position set. A waypoint at that peer's position, within the configured 2.0 m separation floor, was accepted by goto_drone, goto_drone_global, and the drone1 assignment in investigate.
    • Cause
      • _violates_separation calls _globals(max_age_s=GUARDRAIL_MAX_AGE_SEC) at line 513. _globals skips every entry older than that bound at line 282, so the loop at lines 529-535 has no peer to compare. The fail-closed branch only protects an issuing drone whose own position is absent, not a stale non-issuing airborne peer.
    • Fix
      • Fail closed when any other connected, armed multirotor lacks a global position fresher than GUARDRAIL_MAX_AGE_SEC, rather than omitting that peer from the collision check. Apply the same condition for every per-drone assignment in multi-drone maneuvers.

    T-Rex Ran code and verified through T-Rex

Reviews (1): Last reviewed commit: "feat(mcp): per-instance tool naming, Ope..." | Re-trigger Greptile

Comment on lines +600 to +607
if (needs_mode and st.get("mode") is None) or (
not needs_mode and st.get("armed") is None
):
logger.warning(
f"[verify:{action}] {key}: telemetry lacks the field needed to "
"verify delivery -- cannot confirm"
)
continue

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 Incomplete telemetry suppresses safety retries

When a fleet safety broadcast is lost while an aircraft lacks the telemetry field needed for verification, this branch logs and continues without retaining the aircraft in still. It is therefore removed from pending and receives no individually addressed resend. A lost RTL, land, hold, emergency-land, or kill command can leave that aircraft armed and flying.

Comment on lines +513 to +535
globals_ = self._globals(max_age_s=GUARDRAIL_MAX_AGE_SEC)
issuing_global = globals_.get(issuing_key)
issuing_local = self._local_ned(issuing_key)
# Fail closed. Without a *fresh* position for the issuing vehicle this
# check cannot be performed, and "cannot verify" is not "safe" -- the
# previous behaviour let the command through and hoped PX4 would nack
# it. Telemetry arrives within a second, so refusing costs a retry.
if issuing_global is None or issuing_local is None:
return (
f"no position for {issuing_key} fresher than "
f"{GUARDRAIL_MAX_AGE_SEC:.2f}s — cannot verify separation"
)
dn = target_n - issuing_local[0]
de = target_e - issuing_local[1]
pred_lat, pred_lon = offset_latlon(issuing_global[0], issuing_global[1], dn, de)
pred_world = (pred_lat, pred_lon, -target_d) # NED down -> altitude up
for key, point in globals_.items():
if key == issuing_key:
continue
dist = distance_3d_m(pred_world, point)
if dist < self.config.min_separation_m:
return f"{key} @ {dist:.2f}m"
return None

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 Stale peers bypass separation admission

_violates_separation obtains the comparison set through _globals(max_age_s=GUARDRAIL_MAX_AGE_SEC), which omits a connected, armed peer when its position is slightly older than 0.75 seconds. The issuing drone can still have fresh telemetry and pass the fail-closed check, so goto_drone, goto_drone_global, and the per-drone assignment in investigate can accept a destination inside the configured separation floor. Reject the request while any other connected armed drone lacks a fresh global position instead of treating that peer as absent.

Artifacts

Focused stale-peer admission reproduction source

  • Authored Python harness calls the real coordinator command methods with an armed peer whose telemetry is 0.76 seconds old and whose position is inside the destination separation floor; it exercises the claimed admission path.

Stale-peer command-admission runtime output

  • Captured output of the focused harness run from `/home/user/repo` with exit code 0; it shows all three command paths admitted an unsafe drone1 waypoint, confirming the claim.

View artifacts

T-Rex Ran code and verified through T-Rex

@aclauer aclauer left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Plz no AI spam pr descriptions

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

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

Labels

first-time-contributor PR opened by an author who had not previously committed to this repository

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants