Skip to content

Reintegrate drone_models and drone_controllers into crazyflow#71

Open
amacati wants to merge 24 commits into
mainfrom
feat.merge_models
Open

Reintegrate drone_models and drone_controllers into crazyflow#71
amacati wants to merge 24 commits into
mainfrom
feat.merge_models

Conversation

@amacati

@amacati amacati commented Jun 17, 2026

Copy link
Copy Markdown
Collaborator

drone-models

Previous state

Drone definitions and dynamics lived in a separate drone-models package, pulled in as a PyPI dependency / git submodule (submodules/drone-models, import drone_models). The MJCF files, meshes and parameters were resolved via drone_models.__file__, and the dynamics were imported into crazyflow/sim/physics.py.

Naming ambiguities

"Model" was overloaded three ways — the MuJoCo MJX model, the dynamics formulation, and the drone hardware. "models", "physics" and "dynamics" were often used interchangeably. These disambiguities have been fixed in the same step:

Concept Before After
Dynamics Physics / models / dynamics Dynamics / dynamics
Drone hardware drone_model (param/attr) drone
MuJoCo model model (spec, file name) mjx_model

Proposed naming scheme

  • drone — a hardware platform (cf2x_L250, cf21B_500, …).
  • dynamics — a physics formulation that advances the state (first_principles, so_rpy, so_rpy_rotor, so_rpy_rotor_drag), selected via the Dynamics enum.
  • mjx_model — the MuJoCo MJX model used for kinematics/rendering.

We avoid the use of model where possible because it is ambiguous.

Package split

The vendored package is split by what the files are:

  • crazyflow/drones/ — hardware descriptions: MJCF *.xml, meshes (assets/), and shared params.toml (mass, inertia, thrust/torque curves). available_drones enumerates platforms.
  • crazyflow/dynamics/ — the dynamics themselves: one subpackage per fidelity level (each with dynamics.py + params.toml), plus core.py (Dynamics, parametrize), symbols.py, transform.py, and utils/. Written backend-agnostic (Array API: NumPy/JAX/PyTorch) and CasADi-symbolic, so the dynamics stay usable standalone for estimation/control.
    available_dynamics / dynamics_features enumerate and introspect them.

Other resulting changes

  • Removed the drone-models dependency and submodule and added package-data globs for the vendored XML/STL/TOML.
  • Deleted crazyflow/sim/physics.py; dynamics selection now lives in crazyflow/dynamics.
  • Added crazyflow/_typing.py (Array/ArrayLike shim until array-api typing lands).
  • Mechanical renames across docs, examples and tests (physicsdynamics, drone_modeldrone);
    docs/user-guide/physics-models.mddynamics-models.md.

Follow-up (separate PR)

  • Move to_xp (crazyflow/dynamics/utils/__init__.py) to the general crazyflow/utils.py. It's a generic Array-API helper, not dynamics-specific.
  • Reconsider home of the transform/rotation helpers (crazyflow/dynamics/transform.py, crazyflow/dynamics/utils/rotation.py). Several are general-purpose and may belong in shared utils.

drone-controllers

Previous state

Controllers lived in a separate drone-controllers package, pulled in as a PyPI dependency and git submodule (submodules/drone-controllers, import drone_controllers).

Package move

Vendored into crazyflow/control/, mirroring crazyflow/dynamics/: mellinger/ subpackage (controller functions + params.toml), core.py (parametrize, param loaders), control.py (Control enum), transform.py.

Unification

Previously the controller functions, the sim data structs, and the controller-to-SimData adapters were split across packages. They now live together in crazyflow/control/mellinger/control.py, the same way each dynamics module co-locates dynamics + Params + sim_dynamics.

API changes

  • drone_model param renamed to drone (consistent with dynamics).
  • load_params split into load_params(controller, drone) (raw, name-keyed loader) and load_fn_params(fn, drone) (per-function selection + signature filter).
  • Integral errors are explicit named arguments (pos_err_i, r_int_error) instead of a generic ctrl_errors tuple.
  • Sim adapters renamed control_<stage> and registered in the step pipeline under explicit role-based stage names (state_controller, attitude_controller, force_torque_controller, commit_attitude), so the pipeline is readable and the names are a stable insertion API.

Other resulting changes

  • Removed the drone-controllers dependency and submodule.
  • Added array-api-compat and array-api-extra as direct dependencies (were transitive via the package).
  • Added tests (tests/unit/control/) and docs (docs/user-guide/control/).

@amacati amacati requested a review from ratheron June 17, 2026 13:22
@amacati amacati added the enhancement New feature or request label Jun 17, 2026
@amacati amacati force-pushed the feat.merge_models branch from 7afd420 to e53f1e5 Compare June 17, 2026 18:08
@amacati amacati changed the title Merge drone_models into crazyflow & unify naming Reintegrate drone_models and drone_controllers into crazyflow Jun 17, 2026

@ratheron ratheron 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.

Thanks for working on this integration! This will make the entry to Crazyflow easier

Comment thread crazyflow/drones/__init__.py Outdated
Comment thread crazyflow/drones/cf21B_500_fused.xml Outdated
Comment thread crazyflow/drones/params.toml
Comment thread crazyflow/dynamics/first_principles/dynamics.py
Comment on lines +7 to +20
\[
\begin{aligned}
\dot{\mathbf{p}} &= \mathbf{v}, \\
\dot{\mathbf{q}} &= \tfrac{1}{2}
\begin{bmatrix}0 \\ {}^{\mathcal{B}}\boldsymbol{\omega}\end{bmatrix}
\otimes \mathbf{q}, \\
m\dot{\mathbf{v}} &= m\mathbf{g}
+ (c_{\mathrm{acc}} + c_f F_{\mathrm{cmd}})\,R\,\mathbf{e}_z, \\
\ddot{\boldsymbol{\psi}} &=
c_{\psi}\,\boldsymbol{\psi}
+ c_{\dot{\psi}}\,\dot{\boldsymbol{\psi}}
+ c_u\,\mathbf{u}_{\mathrm{rpy}},
\end{aligned}
\]

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.

Is there a way to preview the output to double check this nicely?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

https://www.tuhh.de/MathJax/test/sample-dynamic-2.html, but it requires copy+paste. Other than that, only running it locally with pixi run docs-serve

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Fixed the rotation direction of the quaternion and the ordering of entries

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.

Why is there a q in the equation? The core model only has psi as state. While it get's transformed to fit the Crazyflow states, I think adding this is conversion is more confusing

Comment thread docs/user-guide/dynamics/transforms.md Outdated
Comment thread tests/integration/test_interfaces.py Outdated
Comment thread tests/unit/control/test_transform.py
Comment thread tests/unit/dynamics/test_preprocessing.py
Comment thread tests/unit/dynamics/test_parametrization.py Outdated
@amacati

amacati commented Jun 18, 2026

Copy link
Copy Markdown
Collaborator Author

Latest changes are all in and ready for another review

@ratheron ratheron 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.

Looks like you found a clean solution for the parameterize after all. I like it!
Left some minor comments

Comment on lines +7 to +20
\[
\begin{aligned}
\dot{\mathbf{p}} &= \mathbf{v}, \\
\dot{\mathbf{q}} &= \tfrac{1}{2}
\begin{bmatrix}0 \\ {}^{\mathcal{B}}\boldsymbol{\omega}\end{bmatrix}
\otimes \mathbf{q}, \\
m\dot{\mathbf{v}} &= m\mathbf{g}
+ (c_{\mathrm{acc}} + c_f F_{\mathrm{cmd}})\,R\,\mathbf{e}_z, \\
\ddot{\boldsymbol{\psi}} &=
c_{\psi}\,\boldsymbol{\psi}
+ c_{\dot{\psi}}\,\dot{\boldsymbol{\psi}}
+ c_u\,\mathbf{u}_{\mathrm{rpy}},
\end{aligned}
\]

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.

Why is there a q in the equation? The core model only has psi as state. While it get's transformed to fit the Crazyflow states, I think adding this is conversion is more confusing

Comment thread crazyflow/dynamics/so_rpy_rotor/__init__.py Outdated
Comment thread crazyflow/dynamics/so_rpy_rotor_drag/__init__.py Outdated
Comment thread crazyflow/envs/drone_env.py Outdated
Comment thread crazyflow/sim/sim.py

@ratheron ratheron 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.

Looks like you found a clean solution for the parameterize after all. I like it!
Left some minor comments

@amacati amacati force-pushed the feat.merge_models branch from 345e1cb to f22b001 Compare June 19, 2026 14:17
@amacati amacati requested a review from ratheron June 19, 2026 14:17
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants