Skip to content

Commit f5ff8a5

Browse files
committed
Simplify wrappers, add drone-models test suite to crazyflow
1 parent a601622 commit f5ff8a5

12 files changed

Lines changed: 814 additions & 4 deletions

File tree

crazyflow/dynamics/core.py

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,6 @@
1414
if TYPE_CHECKING:
1515
from types import ModuleType
1616

17-
1817
F = TypeVar("F", bound=Callable[..., Any])
1918
P = ParamSpec("P")
2019
R = TypeVar("R")

crazyflow/dynamics/first_principles/dynamics.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
from __future__ import annotations
1616

17+
import warnings
1718
from typing import TYPE_CHECKING
1819

1920
import casadi as cs
@@ -106,6 +107,7 @@ def dynamics(
106107
rot_mat = rot.inv().as_matrix() # from world to body
107108
# Rotor dynamics
108109
if rotor_vel is None:
110+
warnings.warn("Rotor velocity not provided, using commanded rotor velocity.")
109111
rotor_vel, rotor_vel_dot = cmd, None
110112
else:
111113
rotor_vel_dot = xp.where(

crazyflow/dynamics/so_rpy/dynamics.py

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
11
"""Second-order fitted RPY dynamics (no rotor dynamics).
22
3-
This module implements a simplified quadrotor dynamics where the rotational dynamics are modelled as a fitted second-order linear system driven by roll, pitch,
4-
and yaw (RPY) commands, and the translational dynamics are driven by the collective
5-
thrust command. Motor spin-up dynamics are not modelled.
3+
This module implements a simplified quadrotor dynamics where the rotational dynamics are modelled as
4+
a fitted second-order linear system driven by roll, pitch, and yaw (RPY) commands, and the
5+
translational dynamics are driven by the collective thrust command. Motor spin-up dynamics are not
6+
modelled.
67
78
The command interface is ``[roll_rad, pitch_rad, yaw_rad, thrust_N]``.
89

crazyflow/dynamics/so_rpy_rotor/dynamics.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414

1515
from __future__ import annotations
1616

17+
import warnings
1718
from typing import TYPE_CHECKING
1819

1920
import casadi as cs
@@ -103,6 +104,7 @@ def dynamics(
103104

104105
# Note that we are abusing the rotor_vel state as the thrust
105106
if rotor_vel is None:
107+
warnings.warn("Rotor velocity not provided, using commanded rotor velocity.")
106108
rotor_vel, rotor_vel_dot = cmd_f[..., None], None
107109
else:
108110
rotor_vel_dot = 1 / thrust_time_coef * (cmd_f[..., None] - rotor_vel)

crazyflow/dynamics/so_rpy_rotor_drag/dynamics.py

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616

1717
from __future__ import annotations
1818

19+
import warnings
1920
from typing import TYPE_CHECKING
2021

2122
import casadi as cs
@@ -116,6 +117,7 @@ def dynamics(
116117

117118
# Note that we are abusing the rotor_vel state as the thrust
118119
if rotor_vel is None:
120+
warnings.warn("Rotor velocity not provided, using commanded rotor velocity.")
119121
rotor_vel, rotor_vel_dot = cmd_f[..., None], None
120122
else:
121123
rotor_vel_dot = 1 / thrust_time_coef * (cmd_f[..., None] - rotor_vel)

tests/integration/dynamics/__init__.py

Whitespace-only changes.
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
"""Tests for identification pipeline."""
2+
3+
from __future__ import annotations
4+
5+
import array_api_compat.numpy as np
6+
import pytest
7+
8+
from crazyflow.dynamics.utils.data_utils import derivatives_svf, preprocessing
9+
from crazyflow.dynamics.utils.identification import sys_id_rotation, sys_id_translation
10+
11+
12+
@pytest.mark.integration
13+
def test_sys_id_rotation():
14+
time = np.linspace(0.0, 1.0, 100)
15+
pos = np.stack((np.cos(2 * np.pi * time), np.sin(2 * np.pi * time), time), axis=-1)
16+
quat = np.zeros((100, 4))
17+
quat[:, 3] = 1.0 # No rotation
18+
cmd_rpy = np.zeros((100, 3))
19+
cmd_f = np.ones(100) * 0.03
20+
data = {
21+
"time": np.linspace(0.0, 1.0, 100),
22+
"pos": pos,
23+
"quat": quat,
24+
"cmd_rpy": cmd_rpy,
25+
"cmd_f": cmd_f,
26+
}
27+
28+
data = preprocessing(data)
29+
data["rpy"] = np.roll(cmd_rpy, shift=10, axis=0)
30+
data = derivatives_svf(data)
31+
32+
sys_id_rotation(data)
33+
34+
35+
@pytest.mark.integration
36+
@pytest.mark.parametrize("dynamics", ["so_rpy", "so_rpy_rotor", "so_rpy_rotor_drag"])
37+
def test_sys_id_translation(dynamics: str):
38+
mass = 0.03
39+
time = np.linspace(0.0, 1.0, 100)
40+
phi = 2 * np.pi * time
41+
pos = np.stack((np.cos(phi) * 0.1, np.sin(phi) * 0.1, np.roll(np.cos(phi), 10)), axis=-1)
42+
quat = np.zeros((100, 4))
43+
quat[:, 3] = 1.0 # No rotation
44+
cmd_rpy = np.zeros((100, 3))
45+
cmd_f = (np.ones(100) + np.cos(phi)) * mass * 9.81
46+
data = {
47+
"time": np.linspace(0.0, 1.0, 100),
48+
"pos": pos,
49+
"quat": quat,
50+
"cmd_rpy": cmd_rpy,
51+
"cmd_f": cmd_f,
52+
}
53+
54+
data = preprocessing(data)
55+
data = derivatives_svf(data)
56+
57+
sys_id_translation(dynamics=dynamics, mass=mass, data=data)

tests/unit/dynamics/__init__.py

Whitespace-only changes.

0 commit comments

Comments
 (0)