Skip to content

Commit 7cce325

Browse files
committed
Rename organization
1 parent 2a6fddd commit 7cce325

7 files changed

Lines changed: 1269 additions & 135 deletions

File tree

README.md

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -11,18 +11,18 @@ Drone controllers @ LSY. Contains array API (i.e., NumPy, JAX, Torch...) impleme
1111
[Python Version]: https://img.shields.io/badge/python-3.10+-blue.svg
1212
[Python Version URL]: https://www.python.org
1313

14-
[Ruff Check]: https://github.com/utiasDSL/drone-controllers/actions/workflows/ruff.yml/badge.svg?style=flat-square
15-
[Ruff Check URL]: https://github.com/utiasDSL/drone-controllers/actions/workflows/ruff.yml
14+
[Ruff Check]: https://github.com/learnsyslab/drone-controllers/actions/workflows/ruff.yml/badge.svg?style=flat-square
15+
[Ruff Check URL]: https://github.com/learnsyslab/drone-controllers/actions/workflows/ruff.yml
1616

17-
[Tests]: https://github.com/utiasDSL/drone-controllers/actions/workflows/testing.yml/badge.svg
18-
[Tests URL]: https://github.com/utiasDSL/drone-controllers/actions/workflows/testing.yml
17+
[Tests]: https://github.com/learnsyslab/drone-controllers/actions/workflows/testing.yml/badge.svg
18+
[Tests URL]: https://github.com/learnsyslab/drone-controllers/actions/workflows/testing.yml
1919

20-
[Docs]: https://github.com/utiasDSL/drone-controllers/actions/workflows/docs.yml/badge.svg
21-
[Docs URL]: https://utiasdsl.github.io/drone-controllers/
20+
[Docs]: https://github.com/learnsyslab/drone-controllers/actions/workflows/docs.yml/badge.svg
21+
[Docs URL]: https://learnsyslab.github.io/drone-controllers/
2222

2323
## Installation
2424

25-
1. Clone repository `git clone git@github.com:utiasDSL/drone-controllers.git`
25+
1. Clone repository `git clone git@github.com:learnsyslab/drone-controllers.git`
2626
2. Enter repository `cd drone-controllers`
2727
3. Install locally with `pip install -e .` or the pixi environment with `pixi install`, which can be activated with `pixi shell`
2828

docs/getting-started/installation.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ pip install drone-controllers
1616
Clone the repository and install in development mode:
1717

1818
```bash
19-
git clone https://github.com/utiasDSL/drone-controllers.git
19+
git clone https://github.com/learnsyslab/drone-controllers.git
2020
cd drone-controllers
2121
pip install -e .
2222
```
@@ -49,7 +49,7 @@ If you plan to contribute to Drone Controllers, install the development dependen
4949
curl -fsSL https://pixi.sh/install.sh | bash
5050

5151
# Clone and install
52-
git clone https://github.com/utiasDSL/drone-controllers.git
52+
git clone https://github.com/learnsyslab/drone-controllers.git
5353
cd drone-controllers
5454
pixi install
5555

docs/index.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ u = K_p e + K_i \int e \, dt + K_d \frac{de}{dt}
55
$$
66

77

8-
[![CI](https://github.com/utiasDSL/drone-controllers/actions/workflows/testing.yml/badge.svg)](https://github.com/utiasDSL/drone-controllers/actions)
9-
[![License](https://img.shields.io/github/license/utiasDSL/drone-controllers)](https://github.com/utiasDSL/drone-controllers/blob/main/LICENSE)
8+
[![CI](https://github.com/learnsyslab/drone-controllers/actions/workflows/testing.yml/badge.svg)](https://github.com/learnsyslab/drone-controllers/actions)
9+
[![License](https://img.shields.io/github/license/learnsyslab/drone-controllers)](https://github.com/learnsyslab/drone-controllers/blob/main/LICENSE)
1010

1111
**Drone Controllers** is a Python library providing faithful reimplementations of onboard drone controllers that can be used for simulation and modelling.
1212

@@ -91,4 +91,4 @@ All controllers support the Python Array API standard, meaning you can use them
9191
- Read the [Getting Started](getting-started/installation.md) guide
9292
- Browse the [API Reference](api/core.md)
9393
- Check out [Concepts](concepts/overview.md) for theory
94-
- Report issues on [GitHub](https://github.com/utiasDSL/drone-controllers/issues)
94+
- Report issues on [GitHub](https://github.com/learnsyslab/drone-controllers/issues)

drone_controllers/core.py

Lines changed: 60 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,89 +1,91 @@
1-
"""Core functionalities for controller parametrization and registration."""
1+
"""Core functionalities for controller parametrization."""
22

33
from __future__ import annotations
44

5+
import inspect
6+
import tomllib
57
from functools import partial
6-
from typing import Any, Callable, ParamSpec, Protocol, TypeVar, runtime_checkable
8+
from pathlib import Path
9+
from typing import TYPE_CHECKING, Any, Callable, ParamSpec, TypeVar
710

8-
P = ParamSpec("P")
9-
R = TypeVar("R")
11+
import numpy as np
1012

13+
if TYPE_CHECKING:
14+
from types import ModuleType
1115

12-
controller_parameter_registry: dict[str, type[ControllerParams]] = {}
16+
P = ParamSpec("P")
17+
R = TypeVar("R")
1318

1419

15-
def parametrize(fn: Callable[P, R], drone_model: str) -> Callable[P, R]:
16-
"""Parametrize a controller function with the default controller parameters for a drone model.
20+
def parametrize(
21+
fn: Callable[P, R], drone_model: str, xp: ModuleType | None = None, device: str | None = None
22+
) -> Callable[P, R]:
23+
"""Parametrize a controller function with the default parameters for a drone model.
1724
1825
Args:
1926
fn: The controller function to parametrize.
2027
drone_model: The drone model to use.
28+
xp: The array API module to use. If not provided, numpy is used.
29+
device: The device to use. If none, the device is inferred from the xp module.
2130
2231
Example:
23-
>>> from drone_models.controller import parametrize
24-
>>> from drone_models.controller.mellinger import state2attitude
25-
>>> controller_fn = parametrize(state2attitude, drone_model="cf2x_L250")
26-
>>> command_rpyt, int_pos_err = controller_fn(
27-
... pos=pos,
28-
... quat=quat,
29-
... vel=vel,
30-
... ang_vel=ang_vel,
31-
... cmd=cmd,
32-
... ctrl_errors=(int_pos_err,),
33-
... ctrl_freq=100,
32+
>>> from drone_controllers import parametrize
33+
>>> from drone_controllers.mellinger import state2attitude
34+
>>> controller = parametrize(state2attitude, drone_model="cf2x_L250")
35+
>>> command_rpyt, int_pos_err = controller(
36+
... pos=pos, quat=quat, vel=vel, ang_vel=ang_vel, cmd=cmd, ctrl_freq=100
3437
... )
3538
3639
Returns:
37-
The parametrized controller function with all keyword argument only parameters filled in.
40+
The parametrized controller function with all keyword-only parameters filled in.
3841
"""
39-
controller_id = fn.__module__ + "." + fn.__name__
42+
xp = np if xp is None else xp
43+
controller = fn.__module__.split(".")[-2]
44+
fn_name = fn.__name__
4045
try:
41-
params = controller_parameter_registry[controller_id].load(drone_model)
46+
sig = inspect.signature(fn)
47+
kwonly_params = [
48+
name
49+
for name, param in sig.parameters.items()
50+
if param.kind == inspect.Parameter.KEYWORD_ONLY
51+
]
52+
params = load_params(controller, fn_name, drone_model, xp=xp)
53+
params = {k: xp.asarray(v, device=device) for k, v in params.items() if k in kwonly_params}
4254
except KeyError as e:
4355
raise KeyError(
44-
f"Controller `{controller_id}` does not exist in the parameter registry"
56+
f"Drone model `{drone_model}` not found for controller `{controller}.{fn_name}`"
4557
) from e
46-
except ValueError as e:
47-
raise ValueError(f"Drone model `{drone_model}` not supported for `{fn.__name__}`") from e
48-
return partial(fn, **params._asdict())
49-
50-
51-
@runtime_checkable
52-
class ControllerParams(Protocol):
53-
"""Protocol for controller parameters."""
58+
return partial(fn, **params)
5459

55-
@staticmethod
56-
def load(drone_model: str) -> ControllerParams:
57-
"""Load the parameters from the config file."""
5860

59-
def _asdict(self) -> dict[str, Any]:
60-
"""Convert the parameters to a dictionary."""
61+
def load_params(
62+
controller: str, fn_name: str, drone_model: str, xp: ModuleType | None = None
63+
) -> dict[str, Any]:
64+
"""Load and merge parameters for a controller function and drone model.
6165
62-
63-
def register_controller_parameters(
64-
params: ControllerParams | type[ControllerParams],
65-
) -> Callable[[Callable[P, R]], Callable[P, R]]:
66-
"""Register the default controller parameters for this controller.
67-
68-
Warning:
69-
The controller parameters **must** be a named tuple with a function `load` that takes in the
70-
drone model name and returns an instance of itself, or a class that implements the
71-
ControllerParams protocol.
66+
Reads parameters from the controller's ``params.toml`` file, merging the
67+
shared ``[drone_model.core]`` section with the function-specific
68+
``[drone_model.{fn_name}]`` section (if it exists).
7269
7370
Args:
74-
params: The controller parameter type.
71+
controller: Name of the controller sub-package, e.g. ``"mellinger"``.
72+
fn_name: Name of the controller function, e.g. ``"state2attitude"``.
73+
drone_model: Name of the drone configuration, e.g. ``"cf2x_L250"``.
74+
xp: Array API module used to convert parameter values. If ``None``,
75+
NumPy is used.
7576
7677
Returns:
77-
A decorator function that registers the parameters and returns the function unchanged.
78-
"""
79-
if not isinstance(params, ControllerParams):
80-
raise ValueError(f"{params} does not implement the ControllerParams protocol")
78+
A flat dict mapping parameter names to arrays in the requested array namespace.
8179
82-
def decorator(fn: Callable[P, R]) -> Callable[P, R]:
83-
controller_id = fn.__module__ + "." + fn.__name__
84-
if controller_id in controller_parameter_registry:
85-
raise ValueError(f"Controller `{controller_id}` already registered")
86-
controller_parameter_registry[controller_id] = params
87-
return fn
88-
89-
return decorator
80+
Raises:
81+
KeyError: If ``drone_model`` is not found in the TOML file.
82+
"""
83+
xp = np if xp is None else xp
84+
with open(Path(__file__).parent / f"{controller}/params.toml", "rb") as f:
85+
all_params = tomllib.load(f)
86+
if drone_model not in all_params:
87+
raise KeyError(f"Drone model `{drone_model}` not found in {controller}/params.toml")
88+
drone_params = all_params[drone_model]
89+
params = dict(drone_params.get("core", {}))
90+
params |= drone_params.get(fn_name, {})
91+
return {k: xp.asarray(v) for k, v in params.items()}

mkdocs.yml

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
site_name: Drone Controllers
22
site_description: Controllers for quadrotor drones
3-
site_url: https://utiasdsl.github.io/drone-controllers/
4-
repo_url: https://github.com/utiasDSL/drone-controllers
5-
repo_name: utiasDSL/drone-controllers
3+
site_url: https://learnsyslab.github.io/drone-controllers/
4+
repo_url: https://github.com/learnsyslab/drone-controllers
5+
repo_name: learnsyslab/drone-controllers
66

77
theme:
88
name: material
@@ -96,7 +96,7 @@ extra_javascript:
9696
extra:
9797
social:
9898
- icon: fontawesome/brands/github
99-
link: https://github.com/utiasDSL/drone-controllers
99+
link: https://github.com/learnsyslab/drone-controllers
100100

101101
extra_css:
102102
- stylesheets/extra.css

0 commit comments

Comments
 (0)