mirror of
https://gitee.com/mirrors_PX4/PX4-Autopilot.git
synced 2026-11-07 02:21:36 +08:00
fix and re-enable EKF pytests
This commit is contained in:
@@ -0,0 +1,73 @@
|
||||
############################################################################
|
||||
#
|
||||
# Copyright (c) 2015-2018 ECL Development Team. All rights reserved.
|
||||
#
|
||||
# Redistribution and use in source and binary forms, with or without
|
||||
# modification, are permitted provided that the following conditions
|
||||
# are met:
|
||||
#
|
||||
# 1. Redistributions of source code must retain the above copyright
|
||||
# notice, this list of conditions and the following disclaimer.
|
||||
# 2. Redistributions in binary form must reproduce the above copyright
|
||||
# notice, this list of conditions and the following disclaimer in
|
||||
# the documentation and/or other materials provided with the
|
||||
# distribution.
|
||||
# 3. Neither the name ECL nor the names of its contributors may be
|
||||
# used to endorse or promote products derived from this software
|
||||
# without specific prior written permission.
|
||||
#
|
||||
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
|
||||
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
|
||||
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
|
||||
# FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
# COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
|
||||
# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
|
||||
# BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS
|
||||
# OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
|
||||
# AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
|
||||
# ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
# POSSIBILITY OF SUCH DAMAGE.
|
||||
#
|
||||
############################################################################
|
||||
|
||||
if(EKF_PYTHON_TESTS)
|
||||
|
||||
add_custom_target(ecl_EKF_pytest
|
||||
COMMAND env PYTHONPATH=${CMAKE_BINARY_DIR}/EKF/swig/python ${CMAKE_CURRENT_SOURCE_DIR}/ekf_test.py --verbose
|
||||
DEPENDS ecl_EKF _ecl_EKF
|
||||
USES_TERMINAL
|
||||
)
|
||||
|
||||
add_custom_target(ecl_EKF_pytest-quick
|
||||
COMMAND env PYTHONPATH=${CMAKE_BINARY_DIR}/EKF/swig/python ${CMAKE_CURRENT_SOURCE_DIR}/ekf_test.py --quick --verbose
|
||||
DEPENDS ecl_EKF _ecl_EKF
|
||||
USES_TERMINAL
|
||||
)
|
||||
|
||||
add_custom_target(ecl_EKF_pytest-benchmark
|
||||
COMMAND env PYTHONPATH=${CMAKE_BINARY_DIR}/EKF/swig/python ${CMAKE_CURRENT_SOURCE_DIR}/ekf_test.py --benchmark
|
||||
DEPENDS ecl_EKF _ecl_EKF
|
||||
USES_TERMINAL
|
||||
)
|
||||
|
||||
# requires python3-tk
|
||||
add_custom_target(ecl_EKF_pytest-plots
|
||||
COMMAND env PYTHONPATH=${CMAKE_BINARY_DIR}/EKF/swig/python ${CMAKE_CURRENT_SOURCE_DIR}/ekf_test.py --plots
|
||||
DEPENDS ecl_EKF _ecl_EKF
|
||||
USES_TERMINAL
|
||||
)
|
||||
|
||||
add_custom_target(ecl_EKF_pytest-lint
|
||||
COMMAND env PYTHONPATH=${CMAKE_BINARY_DIR}/EKF/swig/python ${CMAKE_CURRENT_SOURCE_DIR}/lint.py
|
||||
DEPENDS ecl_EKF _ecl_EKF
|
||||
WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}
|
||||
USES_TERMINAL
|
||||
)
|
||||
|
||||
# ctest entry
|
||||
add_test(NAME ecl_EKF_pytest_run
|
||||
COMMAND ${CMAKE_COMMAND} --build ${CMAKE_BINARY_DIR} --target ecl_EKF_pytest-quick
|
||||
)
|
||||
|
||||
endif()
|
||||
@@ -37,7 +37,7 @@
|
||||
In order to run the tests, make sure to compile the ecl library including the
|
||||
SWIG bindings, e.g. by running
|
||||
|
||||
cmake -DPythonTests=1 ../EKF && make pytest-quick
|
||||
cmake -DEKF_PYTHON_TESTS=ON .. && make ecl_EKF_pytest-quick
|
||||
|
||||
from your build directory.
|
||||
|
||||
@@ -45,10 +45,10 @@ from datetime import datetime
|
||||
|
||||
CHECKERS = [
|
||||
['pep8', '.'],
|
||||
['pep8', './ekf_test'],
|
||||
['pep8', './lint'],
|
||||
['pylint', './lint', '--reports=n', '--score=n'],
|
||||
['pylint', './ekf_test', '--reports=n', '--score=n'],
|
||||
['pep8', './ekf_test.py'],
|
||||
['pep8', './lint.py'],
|
||||
['pylint', './lint.py', '--reports=n', '--score=n'],
|
||||
['pylint', './ekf_test.py', '--reports=n', '--score=n'],
|
||||
['pylint', './plot_utils.py', '--reports=n', '--score=n'],
|
||||
['pylint', './test_altitude.py', '--reports=n', '--score=n'],
|
||||
['pylint', './test_basics.py', '--reports=n', '--score=n'],
|
||||
@@ -49,7 +49,7 @@ from hypothesis import given
|
||||
from hypothesis import example
|
||||
from hypothesis import strategies as st
|
||||
|
||||
from test_utils import ecl
|
||||
from test_utils import ecl_EKF
|
||||
from test_utils import update_sensors
|
||||
from test_utils import float_array
|
||||
from test_utils import initialized_ekf
|
||||
@@ -61,10 +61,10 @@ from test_utils import initialized_ekf
|
||||
def test_accel_z_bias_converges(z_bias):
|
||||
"""Make sure the accelerometer bias in z-direction is estimated correctly
|
||||
"""
|
||||
ekf = ecl.Ekf()
|
||||
ekf = ecl_EKF.Ekf()
|
||||
|
||||
time_usec = 1000
|
||||
dt_usec = ecl.Ekf.FILTER_UPDATE_PERIOD_MS * 1000
|
||||
dt_usec = ecl_EKF.Ekf.FILTER_UPDATE_PERIOD_MS * 1000
|
||||
|
||||
# Run for a while
|
||||
n_samples = 10000
|
||||
@@ -84,7 +84,7 @@ def test_accel_z_bias_converges(z_bias):
|
||||
dt_usec,
|
||||
accel=float_array([0.0,
|
||||
0.0,
|
||||
-ecl.one_g + z_bias]))
|
||||
-ecl_EKF.one_g + z_bias]))
|
||||
ekf.update()
|
||||
time_usec += dt_usec
|
||||
|
||||
@@ -136,7 +136,7 @@ def test_converges_to_baro_altitude(altitude):
|
||||
# Due to hypothesis not interacting with pytest, cannot use fixture here
|
||||
ekf, time_usec = initialized_ekf()
|
||||
|
||||
dt_usec = ecl.Ekf.FILTER_UPDATE_PERIOD_MS * 1000
|
||||
dt_usec = ecl_EKF.Ekf.FILTER_UPDATE_PERIOD_MS * 1000
|
||||
|
||||
# No samples, half are used for ramping up / down to the altitude
|
||||
n_samples = 200
|
||||
@@ -166,9 +166,9 @@ def test_converges_to_baro_altitude(altitude):
|
||||
dt_usec,
|
||||
accel=float_array([0,
|
||||
0,
|
||||
-ecl.one_g - rampup_accel
|
||||
-ecl_EKF.one_g - rampup_accel
|
||||
if i < n_samples // 4
|
||||
else -ecl.one_g + rampup_accel]),
|
||||
else -ecl_EKF.one_g + rampup_accel]),
|
||||
baro_data=current_state.alt)
|
||||
ekf.update()
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ from __future__ import absolute_import
|
||||
|
||||
import pytest
|
||||
|
||||
from test_utils import ecl
|
||||
from test_utils import ecl_EKF
|
||||
|
||||
# Pylint does not like pytest fixtures, disable the warning
|
||||
# pylint: disable=redefined-outer-name
|
||||
@@ -93,7 +93,7 @@ def test_status_on_imu_mag_baro(initialized_ekf):
|
||||
def test_converges_to_zero():
|
||||
"""Make sure the EKF with zero inputs converges to / stays at zero
|
||||
"""
|
||||
ekf = ecl.Ekf()
|
||||
ekf = ecl_EKF.Ekf()
|
||||
|
||||
time_usec = 1000
|
||||
dt_usec = 5000
|
||||
|
||||
@@ -44,14 +44,14 @@ import pytest
|
||||
from hypothesis import given
|
||||
from hypothesis import strategies as st
|
||||
|
||||
from test_utils import ecl
|
||||
from test_utils import ecl_EKF
|
||||
from test_utils import float_array
|
||||
|
||||
|
||||
@pytest.mark.parametrize("dt_usec, downsampling_factor", [
|
||||
(ecl.Ekf.FILTER_UPDATE_PERIOD_MS * 1000 // 3, 3),
|
||||
(ecl.Ekf.FILTER_UPDATE_PERIOD_MS * 1000 // 2, 2),
|
||||
(ecl.Ekf.FILTER_UPDATE_PERIOD_MS * 1000, 1),
|
||||
(ecl_EKF.Ekf.FILTER_UPDATE_PERIOD_MS * 1000 // 3, 3),
|
||||
(ecl_EKF.Ekf.FILTER_UPDATE_PERIOD_MS * 1000 // 2, 2),
|
||||
(ecl_EKF.Ekf.FILTER_UPDATE_PERIOD_MS * 1000, 1),
|
||||
])
|
||||
@given(accel_x=st.floats(-5, 5),
|
||||
accel_y=st.floats(-5, 5),
|
||||
@@ -71,7 +71,7 @@ def test_imu_input(dt_usec, downsampling_factor, accel_x, accel_y, accel_z):
|
||||
accel_y,
|
||||
accel_z]) * dt_usec / 1e6
|
||||
|
||||
ekf = ecl.Ekf()
|
||||
ekf = ecl_EKF.Ekf()
|
||||
# Run to accumulate buffer (choose sample after downsampling)
|
||||
for _ in range(20 * downsampling_factor):
|
||||
time_usec += dt_usec
|
||||
@@ -94,14 +94,14 @@ def test_imu_input(dt_usec, downsampling_factor, accel_x, accel_y, accel_z):
|
||||
|
||||
|
||||
@pytest.mark.parametrize("dt_usec, expected_dt_usec", [
|
||||
(ecl.Ekf.FILTER_UPDATE_PERIOD_MS * 1000 // 3,
|
||||
ecl.Ekf.FILTER_UPDATE_PERIOD_MS * 1000),
|
||||
(ecl.Ekf.FILTER_UPDATE_PERIOD_MS * 1000 // 2,
|
||||
ecl.Ekf.FILTER_UPDATE_PERIOD_MS * 1000),
|
||||
(ecl.Ekf.FILTER_UPDATE_PERIOD_MS * 1000,
|
||||
ecl.Ekf.FILTER_UPDATE_PERIOD_MS * 1000),
|
||||
(ecl.Ekf.FILTER_UPDATE_PERIOD_MS * 1000 * 2,
|
||||
ecl.Ekf.FILTER_UPDATE_PERIOD_MS * 1000 * 2),
|
||||
(ecl_EKF.Ekf.FILTER_UPDATE_PERIOD_MS * 1000 // 3,
|
||||
ecl_EKF.Ekf.FILTER_UPDATE_PERIOD_MS * 1000),
|
||||
(ecl_EKF.Ekf.FILTER_UPDATE_PERIOD_MS * 1000 // 2,
|
||||
ecl_EKF.Ekf.FILTER_UPDATE_PERIOD_MS * 1000),
|
||||
(ecl_EKF.Ekf.FILTER_UPDATE_PERIOD_MS * 1000,
|
||||
ecl_EKF.Ekf.FILTER_UPDATE_PERIOD_MS * 1000),
|
||||
(ecl_EKF.Ekf.FILTER_UPDATE_PERIOD_MS * 1000 * 2,
|
||||
ecl_EKF.Ekf.FILTER_UPDATE_PERIOD_MS * 1000 * 2),
|
||||
(500 * 1000,
|
||||
500 * 1000)
|
||||
])
|
||||
@@ -115,7 +115,7 @@ def test_imu_sampling(dt_usec, expected_dt_usec):
|
||||
time_usec = 0
|
||||
delta_ang = float_array([0, 0, 0])
|
||||
delta_vel = float_array([0, 0, 0])
|
||||
ekf = ecl.Ekf()
|
||||
ekf = ecl_EKF.Ekf()
|
||||
for _ in range(100):
|
||||
time_usec += dt_usec
|
||||
ekf.set_imu_data(time_usec,
|
||||
@@ -126,9 +126,9 @@ def test_imu_sampling(dt_usec, expected_dt_usec):
|
||||
|
||||
imu_sample = ekf.get_imu_sample_delayed()
|
||||
assert imu_sample.delta_ang_dt == pytest.approx(
|
||||
expected_dt_usec / 1e6, abs=1e-6)
|
||||
expected_dt_usec / 1e6, abs=1e-5)
|
||||
assert imu_sample.delta_vel_dt == pytest.approx(
|
||||
expected_dt_usec / 1e6, abs=1e-6)
|
||||
expected_dt_usec / 1e6, abs=1e-5)
|
||||
# Make sure the timestamp of the last sample is a small positive multiple
|
||||
# of the period away from now
|
||||
assert (time_usec - imu_sample.time_us) >= 0
|
||||
|
||||
@@ -44,7 +44,7 @@ import numpy as np
|
||||
import pytest
|
||||
|
||||
try:
|
||||
import ecl # pylint: disable=import-error
|
||||
import ecl_EKF # pylint: disable=import-error
|
||||
except ImportError:
|
||||
print("ImportError: ecl library cannot be found."
|
||||
" Make sure to compile ecl with Python bindings "
|
||||
@@ -62,7 +62,7 @@ def float_array(inp):
|
||||
def update_sensors(ekf, # pylint: disable=too-many-arguments
|
||||
time_usec,
|
||||
dt_usec,
|
||||
accel=float_array([0.0, 0.0, -ecl.one_g]),
|
||||
accel=float_array([0.0, 0.0, -ecl_EKF.one_g]),
|
||||
ang_vel=float_array([0.0, 0.0, 0.0]),
|
||||
mag_data=float_array([1.0, 0.0, 0.0]),
|
||||
baro_data=0.0):
|
||||
@@ -83,7 +83,7 @@ def update_sensors(ekf, # pylint: disable=too-many-arguments
|
||||
def initialized_ekf():
|
||||
"""Provides an initialized ekf, ready to go
|
||||
"""
|
||||
ekf = ecl.Ekf()
|
||||
ekf = ecl_EKF.Ekf()
|
||||
|
||||
time_usec = 1000
|
||||
dt_usec = 5000
|
||||
|
||||
Reference in New Issue
Block a user