Skip to content

DIM-1842 drone simulator using MuJoCo simulator and Crazyflie 2#2046

Open
Shreyas0812 wants to merge 17 commits into
dimensionalOS:mainfrom
Shreyas0812:feature/1842-drone-simulator
Open

DIM-1842 drone simulator using MuJoCo simulator and Crazyflie 2#2046
Shreyas0812 wants to merge 17 commits into
dimensionalOS:mainfrom
Shreyas0812:feature/1842-drone-simulator

Conversation

@Shreyas0812
Copy link
Copy Markdown

Problem

No way to test drone software stack without physical hardware. Adds a simulation connection for the Bitcraze Crazyflie 2 using MuJoCo, mirroring the existing Unitree Go1/G1 sim path.

Closes DIM-1842

Solution

  • DroneSimConnection - sim connection module that reuses the existing MujocoConnection infrastructure, skipping MAVLink
  • DroneController - MuJoCo control policy mapping Twist commands (forward/lateral/yaw) to hover thrust and roll/pitch/yaw moments using constants (for thrust) from cf2.xml
  • drone_primitive_no_nav blueprint - minimal drone stack with rerun/foxglove visualization
  • drone_basic_sim blueprint - full sim stack connecting drone_primitive_no_nav with DroneSimConnection

How to Test

dimos --simulation run drone-basic-sim

Use WASD to move the drone. W/S = forward/back, A/D = left/right, Q/E = yaw.

Closes DIM-1842

…s ReplanningAStar (Same as g1) for planning -- yet to be tested
…drone_rerun_blueprint instead of g1 -- Inspired from unitree_g1_primitive_no_nav
…ing the file, updating imports, continuing mujoco_connection for drone
…g now. Ran test all blueprints for populating all_blueprints. Added the bitcraze_crazyflie_2 in model and a new class in policy
…e.start(self) -- need to verify if this is temporary solution, refactoring might be needed
…ode -- added drone to mujoco_process -- fixed Drone Controller policy
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps Bot commented May 11, 2026

Greptile Summary

Adds a MuJoCo-backed Crazyflie 2 drone simulator by introducing DroneSimConnection, DroneController, and two new blueprints (drone_primitive_no_nav, drone_basic_sim), mirroring the existing Unitree sim path and registering everything in the blueprint/module registry.

  • DroneController.get_control sets only data.ctrl[0] to the hover thrust constant (0.26487), while ctrl[1–3] receive small moment-scale values. If the bundled bitcraze_crazyflie_2.xml exposes four independent per-rotor thrust actuators (the default menagerie layout), all four rotors need the base hover value — leaving three at ~0 would flip the drone on spawn. Please confirm the actuator layout matches this mixing scheme.
  • DroneSimConnection contains a redundant local import MujocoConnection inside start() (already imported at module level), and DroneSimConfig declares an ip field that is never consumed by the sim path.
  • DroneController does not inherit OnnxController, creating a type annotation mismatch in load_model that static analysis tools will flag.

Confidence Score: 3/5

The blueprint wiring and shared-memory plumbing look solid, but the drone control law may be fundamentally wrong for the menagerie actuator layout, causing the drone to crash on first simulation run.

The DroneController sets only one of the four ctrl slots to the hover thrust value. If the cf2 model uses per-rotor thrusts (the standard menagerie layout), the other three rotors receive near-zero thrust and the drone flips immediately. This needs to be verified against the actual XML before the simulation can be tested at all.

dimos/simulation/mujoco/policy.py — the hover thrust and moment assignment logic in DroneController.get_control needs validation against the cf2 actuator layout.

Important Files Changed

Filename Overview
dimos/simulation/mujoco/policy.py Adds DroneController with hover thrust + moment mapping; doesn't inherit OnnxController causing a type mismatch, and the per-rotor thrust assignment may be incorrect for the standard menagerie actuator layout.
dimos/robot/drone/sim.py New DroneSimConnection module reuses MujocoConnection infrastructure; contains a redundant local import of MujocoConnection and an unused ip config field.
dimos/simulation/mujoco/mujoco_process.py Maps drone to bitcraze_crazyflie_2, sets initial z-height to 0.5, and adds the missing else-branch that zeros the command array when no new command arrives.
dimos/simulation/mujoco/model.py Loads crazyflie assets and routes bitcraze_crazyflie_2 to DroneController; type annotation of policy remains OnnxController even though DroneController is not a subclass.
dimos/robot/drone/blueprints/basic/drone_basic_sim.py Wires together drone_primitive_no_nav, DroneSimConnection, and ReplanningAStarPlanner via autoconnect; missing trailing newline.
dimos/robot/drone/blueprints/primitive/drone_primitive_no_nav.py Minimal drone visualization + sensor blueprint; includes several commented-out imports and is missing a trailing newline.
dimos/robot/all_blueprints.py Registers drone-basic-sim, drone-primitive-no-nav, and drone-sim-connection in the blueprint/module registries — straightforward additions.

Reviews (1): Last reviewed commit: "vis moved to vis_module in main merge --..." | Re-trigger Greptile

Comment thread dimos/robot/drone/sim.py
Comment on lines +50 to +52
from dimos.robot.unitree.mujoco_connection import MujocoConnection

self.connection = MujocoConnection(self.config.g)
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 The MujocoConnection is imported at the module level (line 23) and again with a redundant local import inside start(). The local import serves no purpose since the top-level import is unconditional, and having two imports of the same name in the same scope can silently shadow the outer binding if the inner one ever changes. Remove the duplicate.

Suggested change
from dimos.robot.unitree.mujoco_connection import MujocoConnection
self.connection = MujocoConnection(self.config.g)
self.connection = MujocoConnection(self.config.g)

Comment on lines +161 to +181
class DroneController():
def __init__(
self,
input_controller: InputController,
**kwargs: Any,
) -> None:
self._input_controller = input_controller

def get_obs(self, model: mujoco.MjModel, data: mujoco.MjData) -> np.ndarray[Any, Any]:
command = self._input_controller.get_command()
return command.astype(np.float32)

def get_control(self, model: mujoco.MjModel, data: mujoco.MjData) -> None:
command = self._input_controller.get_command()
forward = float(command[0])
lateral = float(command[1])
yaw = float(command[2])
data.ctrl[0] = _DRONE_HOVER_THRUST
data.ctrl[1] = lateral * _DRONE_MOMENT_SCALE # x_moment (roll)
data.ctrl[2] = -forward * _DRONE_MOMENT_SCALE # y_moment (pitch)
data.ctrl[3] = -yaw * _DRONE_MOMENT_SCALE # z_moment (yaw) No newline at end of file
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 DroneController does not inherit from OnnxController, but load_model annotates the policy variable as OnnxController. The case "bitcraze_crazyflie_2" branch then assigns a DroneController instance to that annotated variable, which is a static type error. A strict type checker (mypy/pyright) will flag this. Consider having DroneController inherit from an abstract base that both OnnxController and DroneController satisfy, or introduce a Protocol for get_control/get_obs.

ReplanningAStarPlanner.blueprint(),
)

__all__ = ["drone_basic_sim"] No newline at end of file
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 File is missing a trailing newline, which causes issues with some diff tools and linters (e.g., no-newline-at-end-of-file checks).

Suggested change
__all__ = ["drone_basic_sim"]
__all__ = ["drone_basic_sim"]

)
)

__all__ = ["drone_primitive_no_nav"] No newline at end of file
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 File is missing a trailing newline. The same issue is present in drone_basic_sim.py and sim.py.

Suggested change
__all__ = ["drone_primitive_no_nav"]
__all__ = ["drone_primitive_no_nav"]

Comment thread dimos/robot/drone/sim.py
Comment on lines +30 to +31
ip: str = Field(default_factory=lambda m: m["g"].robot_ip)

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 DroneSimConfig.ip is declared but never read anywhere in DroneSimConnection — the sim connection passes self.config.g (the GlobalConfig) directly to MujocoConnection, and robot_ip is only used by MAVLink-based hardware connections. If the field is intentionally reserved for future use, a comment would help; otherwise it can be removed to avoid confusion.

Comment on lines +173 to +181
def get_control(self, model: mujoco.MjModel, data: mujoco.MjData) -> None:
command = self._input_controller.get_command()
forward = float(command[0])
lateral = float(command[1])
yaw = float(command[2])
data.ctrl[0] = _DRONE_HOVER_THRUST
data.ctrl[1] = lateral * _DRONE_MOMENT_SCALE # x_moment (roll)
data.ctrl[2] = -forward * _DRONE_MOMENT_SCALE # y_moment (pitch)
data.ctrl[3] = -yaw * _DRONE_MOMENT_SCALE # z_moment (yaw) No newline at end of file
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 Only data.ctrl[0] receives the full hover thrust, while data.ctrl[1:3] are assigned the raw moment-scale values (lateral * 0.005, -forward * 0.005, -yaw * 0.005). If the bitcraze_crazyflie_2 MuJoCo model exposes four independent per-rotor thrust actuators (which is the default layout in the MuJoCo Menagerie), then all four ctrl entries need the base hover thrust, and the moments are applied as differential offsets on top. With the current code, rotors 1–3 receive near-zero thrust at idle, causing the drone to flip immediately.

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