-
Notifications
You must be signed in to change notification settings - Fork 29
Reintegrate drone_models and drone_controllers into crazyflow
#71
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Open
amacati
wants to merge
24
commits into
main
Choose a base branch
from
feat.merge_models
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
24 commits
Select commit
Hold shift + click to select a range
4fcdfd0
Merge models back into crazyflow
amacati a1321af
Introduce consistent naming scheme for dynamics/physics/models
amacati 17a9f2b
Improve naming consistency in docs
amacati d7e2bee
Finalize consistent naming for drones/models/physics/dynamics
amacati 1a228e9
Rename dynamics file, simplify so_rpy model, simplify models wrapper
amacati 347dded
Remove drone-models submodule
amacati cb7ec8d
Simplify wrappers, add drone-models test suite to crazyflow
amacati afa2d3e
Improve tests
amacati 56a9a4f
Fix test imports
amacati e7e2e06
Rename dynamics docs
amacati c677f81
Add drone model docs
amacati 026350d
Fix docs
amacati 129fc60
Add controllers back into crazyflow
amacati ae62616
Improve API and add docs
amacati 1b052ae
Explicitly name controllers
amacati cc2219f
Remove all submodules. Update deps
amacati 3109cdf
Update doc mistakes and benchmarks
amacati 0715579
Address comments
amacati 8c76a9c
[WIP] Refactor parametrize
amacati a46fbae
Move fused models into regular xml
amacati a4bbc8a
Refactor parametrization
amacati f9aef46
Fix docs and comments
amacati 9bcfac4
Fix model docs. Restructure into core dynamics_euler and wrapper dyna…
amacati f22b001
Fix doctests
amacati File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,8 @@ | ||
| """This file is to be removed as soon as a proper typing is available by the official array-api.""" | ||
|
|
||
| from typing import Any, TypeAlias | ||
|
|
||
| import numpy.typing as npt | ||
|
|
||
| Array: TypeAlias = Any # To be changed to array_api_typing later | ||
| ArrayLike: TypeAlias = Array | npt.ArrayLike |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,3 +1,26 @@ | ||
| from crazyflow.control.control import Control | ||
| """Implementations of onboard drone controllers in Python. | ||
|
|
||
| __all__ = ["Control"] | ||
| All controllers are implemented using the array API standard. This means that every controller is | ||
| agnostic to the choice of framework and supports e.g. NumPy, JAX, or PyTorch. We also implement all | ||
| controllers as pure functions to ensure that users can jit-compile them. All controllers use | ||
| broadcasting to support batching of arbitrary leading dimensions. | ||
|
|
||
| We reimplement the onboard controller for two reasons: | ||
| - We cannot use the C++ bindings of the firmware to differentiate through the onboard controller. | ||
| - We need to implement it with JAX to enable efficient, batched computations. | ||
| """ | ||
|
|
||
| from typing import Callable | ||
|
|
||
| __all__ = [] | ||
|
|
||
| from crazyflow.control.core import Control, parametrize | ||
| from crazyflow.control.mellinger import attitude2force_torque as mellinger_attitude2force_torque | ||
| from crazyflow.control.mellinger import state2attitude as mellinger_state2attitude | ||
|
|
||
| available_controller: dict[str, Callable] = { | ||
| "mellinger_state2attitude": mellinger_state2attitude, | ||
| "mellinger_attitude2force_torque": mellinger_attitude2force_torque, | ||
| } | ||
|
|
||
| __all__ = ["Control", "parametrize"] |
This file was deleted.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,134 @@ | ||
| """Core functionalities for controller parametrization.""" | ||
|
|
||
| from __future__ import annotations | ||
|
|
||
| import tomllib | ||
| from enum import Enum | ||
| from pathlib import Path | ||
| from typing import TYPE_CHECKING, Callable, ParamSpec, TypeVar | ||
|
|
||
| import jax | ||
| from jax import Array | ||
|
|
||
| from crazyflow.utils import filter_to_signature, to_xp | ||
| from crazyflow.utils import parametrize as _parametrize | ||
|
|
||
| if TYPE_CHECKING: | ||
| from types import ModuleType | ||
|
|
||
| from crazyflow._typing import Array # To be changed to array_api_typing later | ||
|
|
||
| P = ParamSpec("P") | ||
| R = TypeVar("R") | ||
|
|
||
|
|
||
| def parametrize( | ||
| fn: Callable[P, R], drone: str, xp: ModuleType | None = None, device: str | None = None | ||
| ) -> Callable[P, R]: | ||
| """Parametrize a controller function with the default controller parameters for a drone. | ||
|
|
||
| Args: | ||
| fn: The controller function to parametrize. | ||
| drone: The drone to use. | ||
| xp: The array API module to use. If not provided, numpy is used. | ||
| device: The device to use. If None, the device is inferred from the xp module. | ||
|
|
||
| Example: | ||
| ```python | ||
| import numpy as np | ||
| from crazyflow.control import parametrize | ||
| from crazyflow.control.mellinger import state2attitude | ||
|
|
||
| ctrl = parametrize(state2attitude, "cf2x_L250") | ||
| pos = np.zeros(3) | ||
| quat = np.array([0.0, 0.0, 0.0, 1.0]) | ||
| vel = np.zeros(3) | ||
| cmd = np.zeros(13) | ||
| rpyt, int_pos_err = ctrl(pos, quat, vel, cmd) | ||
| ``` | ||
|
|
||
| Returns: | ||
| The parametrized controller function with all keyword argument only parameters filled in. | ||
| """ | ||
| return _parametrize(fn, drone, load_params, xp=xp, device=device) | ||
|
|
||
|
|
||
| def load_params( | ||
| fn: Callable, drone: str, xp: ModuleType | None = None, device: str | None = None | ||
| ) -> dict[str, Array]: | ||
| """Load the parameters a specific controller function accepts. | ||
|
|
||
| Merges the ``"core"`` section with the function's ``[drone.<fn_name>]`` section (function values | ||
| take precedence), then keeps only the parameters in ``fn``'s signature. | ||
|
|
||
| Args: | ||
| fn: The controller function for which to load parameters. | ||
| drone: Name of the drone configuration, e.g. ``"cf2x_L250"``. | ||
| xp: The array API module to use. If not provided, numpy is used. | ||
| device: The device to use. If None, the device is inferred from the xp module. | ||
|
|
||
| Returns: | ||
| A flat dict mapping parameter names to arrays in the requested array namespace. | ||
| """ | ||
| assert isinstance(fn, Callable), f"Expected a function, got {type(fn)}" | ||
| controller = fn.__module__.split(".")[-2] | ||
| params_path = Path(__file__).parent / f"{controller}/params.toml" | ||
| if not params_path.exists(): | ||
| raise KeyError(f"`{controller}` not found. Available controllers: {tuple(Control)}") | ||
| with open(params_path, "rb") as f: | ||
| params = tomllib.load(f) | ||
| if drone not in params: | ||
| raise KeyError(f"Drone `{drone}` not found in {controller}/params.toml") | ||
| merged = params[drone].get("core", {}) | params[drone].get(fn.__name__, {}) | ||
| return to_xp(filter_to_signature(merged, fn), xp=xp, device=device) | ||
|
|
||
|
|
||
| class Control(str, Enum): | ||
| """Control type of the simulated onboard controller.""" | ||
|
|
||
| state = "state" | ||
| """State control takes [x, y, z, vx, vy, vz, ax, ay, az, yaw, roll_rate, pitch_rate, yaw_rate]. | ||
|
|
||
| Note: | ||
| Recommended frequency is >=20 Hz. | ||
|
|
||
| Warning: | ||
| Currently, we only use positions, velocities, and yaw. The rest of the state is ignored. | ||
| This is subject to change in the future. | ||
| """ | ||
| attitude = "attitude" | ||
| """Attitude control takes [roll, pitch, yaw, collective thrust]. | ||
|
|
||
| Note: | ||
| Recommended frequency is >=100 Hz. | ||
| """ | ||
| force_torque = "force_torque" | ||
| """Force and torque control takes [fc, tx, ty, tz]. | ||
|
|
||
| Note: | ||
| Recommended frequency is >=500 Hz. | ||
| """ | ||
| rotor_vel = "rotor_vel" | ||
| """Rotor velocity control takes [w1, w2, w3, w4] in RPMs. | ||
|
|
||
| Note: | ||
| Recommended frequency is >=500 Hz. | ||
| """ | ||
| default = attitude | ||
|
|
||
|
|
||
| @jax.jit | ||
| def controllable(step: Array, freq: int, control_steps: Array, control_freq: int) -> Array: | ||
| """Check which worlds can currently update their controllers. | ||
|
|
||
| Args: | ||
| step: The current step of the simulation. | ||
| freq: The frequency of the simulation. | ||
| control_steps: The steps at which the controllers were last updated. | ||
| control_freq: The frequency of the controllers. | ||
|
|
||
| Returns: | ||
| A boolean mask of shape (n_worlds,) that is True at the worlds where the controllers can be | ||
| updated. | ||
| """ | ||
| return ((step - control_steps) >= (freq / control_freq)) | (control_steps == -1) |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.