From afcc5b4695a6996326e72926bff975f61731f443 Mon Sep 17 00:00:00 2001 From: James Goppert <james.goppert@gmail.com> Date: Thu, 14 Apr 2016 14:07:28 -0400 Subject: [PATCH] Moved control library. --- Tools/check_code_style.sh | 2 +- cmake/configs/nuttx_mindpx-v2_default.cmake | 2 +- .../nuttx_px4-stm32f4discovery_default.cmake | 2 +- cmake/configs/nuttx_px4fmu-v1_default.cmake | 2 +- cmake/configs/nuttx_px4fmu-v2_default.cmake | 2 +- cmake/configs/nuttx_px4fmu-v2_ekf2.cmake | 2 +- cmake/configs/nuttx_px4fmu-v4_default.cmake | 2 +- cmake/configs/posix_eagle_default.cmake | 2 +- cmake/configs/posix_rpi2_default.cmake | 2 +- cmake/configs/posix_rpi2_release.cmake | 2 +- cmake/configs/posix_sitl_default.cmake | 2 +- cmake/configs/posix_sitl_ekf2.cmake | 2 +- cmake/configs/posix_sitl_replay.cmake | 2 +- cmake/configs/qurt_eagle_default.cmake | 2 +- cmake/configs/qurt_eagle_hil.cmake | 2 +- cmake/configs/qurt_eagle_release.cmake | 2 +- cmake/configs/qurt_eagle_travis.cmake | 2 +- .../controllib/CMakeLists.txt | 7 +- .../controllib/block/Block.cpp | 0 .../controllib/block/Block.hpp | 0 .../controllib/block/BlockParam.cpp | 0 .../controllib/block/BlockParam.hpp | 0 src/lib/controllib/blocks.cpp | 148 +++++ src/{modules => lib}/controllib/blocks.hpp | 36 -- .../controllib/uorb/blocks.cpp | 0 .../controllib/uorb/blocks.hpp | 0 .../controllib/controllib_test_main.cpp | 51 -- src/modules/controllib_test/CMakeLists.txt | 45 ++ .../blocks.cpp | 118 +--- .../controllib_test/controllib_test_main.cpp | 555 ++++++++++++++++++ .../test_params.c | 0 31 files changed, 787 insertions(+), 207 deletions(-) rename src/{modules => lib}/controllib/CMakeLists.txt (95%) rename src/{modules => lib}/controllib/block/Block.cpp (100%) rename src/{modules => lib}/controllib/block/Block.hpp (100%) rename src/{modules => lib}/controllib/block/BlockParam.cpp (100%) rename src/{modules => lib}/controllib/block/BlockParam.hpp (100%) create mode 100644 src/lib/controllib/blocks.cpp rename src/{modules => lib}/controllib/blocks.hpp (96%) rename src/{modules => lib}/controllib/uorb/blocks.cpp (100%) rename src/{modules => lib}/controllib/uorb/blocks.hpp (100%) delete mode 100644 src/modules/controllib/controllib_test_main.cpp create mode 100644 src/modules/controllib_test/CMakeLists.txt rename src/modules/{controllib => controllib_test}/blocks.cpp (88%) create mode 100644 src/modules/controllib_test/controllib_test_main.cpp rename src/modules/{controllib => controllib_test}/test_params.c (100%) diff --git a/Tools/check_code_style.sh b/Tools/check_code_style.sh index c7b4afe4b3..2f12ce5bc7 100755 --- a/Tools/check_code_style.sh +++ b/Tools/check_code_style.sh @@ -29,7 +29,7 @@ for fn in $(find src/examples \ src/modules/local_position_estimator \ src/modules/unit_test \ src/modules/systemlib \ - src/modules/controllib \ + src/lib/controllib \ -path './Build' -prune -o \ -path './mavlink' -prune -o \ -path './NuttX' -prune -o \ diff --git a/cmake/configs/nuttx_mindpx-v2_default.cmake b/cmake/configs/nuttx_mindpx-v2_default.cmake index e56a3b1674..6b52d9ad6c 100644 --- a/cmake/configs/nuttx_mindpx-v2_default.cmake +++ b/cmake/configs/nuttx_mindpx-v2_default.cmake @@ -112,13 +112,13 @@ set(config_module_list modules/param modules/systemlib modules/systemlib/mixer - modules/controllib modules/uORB modules/dataman # # Libraries # + lib/controllib lib/mathlib lib/mathlib/math/filter lib/ecl diff --git a/cmake/configs/nuttx_px4-stm32f4discovery_default.cmake b/cmake/configs/nuttx_px4-stm32f4discovery_default.cmake index 4d4e705196..f753853176 100644 --- a/cmake/configs/nuttx_px4-stm32f4discovery_default.cmake +++ b/cmake/configs/nuttx_px4-stm32f4discovery_default.cmake @@ -30,13 +30,13 @@ set(config_module_list modules/param modules/systemlib modules/systemlib/mixer - modules/controllib modules/uORB # # Libraries # #lib/mathlib/CMSIS + lib/controllib lib/mathlib lib/mathlib/math/filter lib/ecl diff --git a/cmake/configs/nuttx_px4fmu-v1_default.cmake b/cmake/configs/nuttx_px4fmu-v1_default.cmake index 98cab2bf3e..383ffc6b3e 100644 --- a/cmake/configs/nuttx_px4fmu-v1_default.cmake +++ b/cmake/configs/nuttx_px4fmu-v1_default.cmake @@ -96,13 +96,13 @@ set(config_module_list modules/param modules/systemlib modules/systemlib/mixer - modules/controllib modules/uORB modules/dataman # # Libraries # + lib/controllib lib/mathlib lib/mathlib/math/filter lib/ecl diff --git a/cmake/configs/nuttx_px4fmu-v2_default.cmake b/cmake/configs/nuttx_px4fmu-v2_default.cmake index b079322897..811c06aadd 100644 --- a/cmake/configs/nuttx_px4fmu-v2_default.cmake +++ b/cmake/configs/nuttx_px4fmu-v2_default.cmake @@ -106,13 +106,13 @@ set(config_module_list modules/param modules/systemlib modules/systemlib/mixer - modules/controllib modules/uORB modules/dataman # # Libraries # + lib/controllib lib/mathlib lib/mathlib/math/filter lib/ecl diff --git a/cmake/configs/nuttx_px4fmu-v2_ekf2.cmake b/cmake/configs/nuttx_px4fmu-v2_ekf2.cmake index f24ed6ef29..d91249cee0 100644 --- a/cmake/configs/nuttx_px4fmu-v2_ekf2.cmake +++ b/cmake/configs/nuttx_px4fmu-v2_ekf2.cmake @@ -105,13 +105,13 @@ set(config_module_list modules/param modules/systemlib modules/systemlib/mixer - modules/controllib modules/uORB modules/dataman # # Libraries # + lib/controllib lib/mathlib lib/mathlib/math/filter lib/ecl diff --git a/cmake/configs/nuttx_px4fmu-v4_default.cmake b/cmake/configs/nuttx_px4fmu-v4_default.cmake index e322dcc0e8..dbc1040ff0 100644 --- a/cmake/configs/nuttx_px4fmu-v4_default.cmake +++ b/cmake/configs/nuttx_px4fmu-v4_default.cmake @@ -105,13 +105,13 @@ set(config_module_list modules/param modules/systemlib modules/systemlib/mixer - modules/controllib modules/uORB modules/dataman # # Libraries # + lib/controllib lib/mathlib lib/mathlib/math/filter lib/rc diff --git a/cmake/configs/posix_eagle_default.cmake b/cmake/configs/posix_eagle_default.cmake index da2583b897..17cc9be561 100644 --- a/cmake/configs/posix_eagle_default.cmake +++ b/cmake/configs/posix_eagle_default.cmake @@ -43,8 +43,8 @@ set(config_module_list modules/sdlog2 modules/simulator modules/commander - modules/controllib + lib/controllib lib/mathlib lib/mathlib/math/filter lib/conversion diff --git a/cmake/configs/posix_rpi2_default.cmake b/cmake/configs/posix_rpi2_default.cmake index c745070c9e..fdc722a0e0 100644 --- a/cmake/configs/posix_rpi2_default.cmake +++ b/cmake/configs/posix_rpi2_default.cmake @@ -32,7 +32,7 @@ set(config_module_list modules/dataman modules/sdlog2 modules/commander - modules/controllib + lib/controllib lib/mathlib lib/mathlib/math/filter lib/conversion diff --git a/cmake/configs/posix_rpi2_release.cmake b/cmake/configs/posix_rpi2_release.cmake index 69813fb1f7..b23b2ea58e 100644 --- a/cmake/configs/posix_rpi2_release.cmake +++ b/cmake/configs/posix_rpi2_release.cmake @@ -41,7 +41,7 @@ set(config_module_list modules/dataman modules/sdlog2 modules/commander - modules/controllib + lib/controllib lib/mathlib lib/mathlib/math/filter lib/conversion diff --git a/cmake/configs/posix_sitl_default.cmake b/cmake/configs/posix_sitl_default.cmake index b6863de853..bd2591a6d8 100644 --- a/cmake/configs/posix_sitl_default.cmake +++ b/cmake/configs/posix_sitl_default.cmake @@ -50,7 +50,7 @@ set(config_module_list modules/dataman modules/sdlog2 modules/commander - modules/controllib + lib/controllib lib/mathlib lib/mathlib/math/filter lib/conversion diff --git a/cmake/configs/posix_sitl_ekf2.cmake b/cmake/configs/posix_sitl_ekf2.cmake index a46f8b769c..26ca2fad5a 100644 --- a/cmake/configs/posix_sitl_ekf2.cmake +++ b/cmake/configs/posix_sitl_ekf2.cmake @@ -49,7 +49,7 @@ set(config_module_list modules/dataman modules/sdlog2 modules/commander - modules/controllib + lib/controllib lib/mathlib lib/mathlib/math/filter lib/conversion diff --git a/cmake/configs/posix_sitl_replay.cmake b/cmake/configs/posix_sitl_replay.cmake index 6f62cfaeca..e2df0b4326 100644 --- a/cmake/configs/posix_sitl_replay.cmake +++ b/cmake/configs/posix_sitl_replay.cmake @@ -17,7 +17,7 @@ set(config_module_list modules/ekf2 modules/ekf2_replay modules/sdlog2 - modules/controllib + lib/controllib lib/mathlib lib/mathlib/math/filter lib/conversion diff --git a/cmake/configs/qurt_eagle_default.cmake b/cmake/configs/qurt_eagle_default.cmake index ce10981ad2..07cae1573f 100644 --- a/cmake/configs/qurt_eagle_default.cmake +++ b/cmake/configs/qurt_eagle_default.cmake @@ -54,7 +54,6 @@ set(config_module_list modules/systemlib/mixer modules/uORB modules/commander - modules/controllib modules/land_detector # @@ -67,6 +66,7 @@ set(config_module_list # # Libraries # + lib/controllib lib/mathlib lib/mathlib/math/filter lib/geo diff --git a/cmake/configs/qurt_eagle_hil.cmake b/cmake/configs/qurt_eagle_hil.cmake index fb34bc4d02..a3759fc97d 100644 --- a/cmake/configs/qurt_eagle_hil.cmake +++ b/cmake/configs/qurt_eagle_hil.cmake @@ -51,7 +51,7 @@ set(config_module_list lib/terrain_estimation lib/runway_takeoff lib/tailsitter_recovery - modules/controllib + lib/controllib # # QuRT port diff --git a/cmake/configs/qurt_eagle_release.cmake b/cmake/configs/qurt_eagle_release.cmake index 474284f1f3..fd5a7838d9 100644 --- a/cmake/configs/qurt_eagle_release.cmake +++ b/cmake/configs/qurt_eagle_release.cmake @@ -69,11 +69,11 @@ set(config_module_list modules/systemlib/mixer modules/uORB modules/commander - modules/controllib # # Libraries # + lib/controllib lib/mathlib lib/mathlib/math/filter lib/geo diff --git a/cmake/configs/qurt_eagle_travis.cmake b/cmake/configs/qurt_eagle_travis.cmake index f4a5c8c85a..01956337e5 100644 --- a/cmake/configs/qurt_eagle_travis.cmake +++ b/cmake/configs/qurt_eagle_travis.cmake @@ -52,11 +52,11 @@ set(config_module_list modules/systemlib/mixer modules/uORB modules/commander - modules/controllib # # Libraries # + lib/controllib lib/mathlib lib/mathlib/math/filter lib/geo diff --git a/src/modules/controllib/CMakeLists.txt b/src/lib/controllib/CMakeLists.txt similarity index 95% rename from src/modules/controllib/CMakeLists.txt rename to src/lib/controllib/CMakeLists.txt index 9a5962c398..fd1fb22d8f 100644 --- a/src/modules/controllib/CMakeLists.txt +++ b/src/lib/controllib/CMakeLists.txt @@ -31,17 +31,14 @@ # ############################################################################ px4_add_module( - MODULE modules__controllib - MAIN controllib_test + MODULE lib__controllib COMPILE_FLAGS -Os SRCS - controllib_test_main.cpp - test_params.c + blocks.cpp block/Block.cpp block/BlockParam.cpp uorb/blocks.cpp - blocks.cpp DEPENDS platforms__common ) diff --git a/src/modules/controllib/block/Block.cpp b/src/lib/controllib/block/Block.cpp similarity index 100% rename from src/modules/controllib/block/Block.cpp rename to src/lib/controllib/block/Block.cpp diff --git a/src/modules/controllib/block/Block.hpp b/src/lib/controllib/block/Block.hpp similarity index 100% rename from src/modules/controllib/block/Block.hpp rename to src/lib/controllib/block/Block.hpp diff --git a/src/modules/controllib/block/BlockParam.cpp b/src/lib/controllib/block/BlockParam.cpp similarity index 100% rename from src/modules/controllib/block/BlockParam.cpp rename to src/lib/controllib/block/BlockParam.cpp diff --git a/src/modules/controllib/block/BlockParam.hpp b/src/lib/controllib/block/BlockParam.hpp similarity index 100% rename from src/modules/controllib/block/BlockParam.hpp rename to src/lib/controllib/block/BlockParam.hpp diff --git a/src/lib/controllib/blocks.cpp b/src/lib/controllib/blocks.cpp new file mode 100644 index 0000000000..aeef0f0977 --- /dev/null +++ b/src/lib/controllib/blocks.cpp @@ -0,0 +1,148 @@ +/**************************************************************************** + * + * Copyright (C) 2012 PX4 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 PX4 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. + * + ****************************************************************************/ + +/** + * @file blocks.cpp + * + * Controller library code + */ + +#include <math.h> +#include <stdio.h> +#include <float.h> + +#include "blocks.hpp" + +#define ASSERT_CL(T) if (!(T)) { printf("FAIL\n"); return -1; } + +namespace control +{ + +float BlockLimit::update(float input) +{ + if (input > getMax()) { + input = _max.get(); + + } else if (input < getMin()) { + input = getMin(); + } + + return input; +} + +float BlockLimitSym::update(float input) +{ + if (input > getMax()) { + input = _max.get(); + + } else if (input < -getMax()) { + input = -getMax(); + } + + return input; +} + +float BlockLowPass::update(float input) +{ + if (!PX4_ISFINITE(getState())) { + setState(input); + } + + float b = 2 * float(M_PI) * getFCut() * getDt(); + float a = b / (1 + b); + setState(a * input + (1 - a)*getState()); + return getState(); +} + +float BlockHighPass::update(float input) +{ + float b = 2 * float(M_PI) * getFCut() * getDt(); + float a = 1 / (1 + b); + setY(a * (getY() + input - getU())); + setU(input); + return getY(); +} + +float BlockLowPass2::update(float input) +{ + if (!PX4_ISFINITE(getState())) { + setState(input); + } + + if (fabsf(_lp.get_cutoff_freq() - getFCutParam()) > FLT_EPSILON) { + _lp.set_cutoff_frequency(_fs, getFCutParam()); + } + + _state = _lp.apply(input); + return _state; +} + +float BlockIntegral::update(float input) +{ + // trapezoidal integration + setY(_limit.update(getY() + input * getDt())); + return getY(); +} + +float BlockIntegralTrap::update(float input) +{ + // trapezoidal integration + setY(_limit.update(getY() + + (getU() + input) / 2.0f * getDt())); + setU(input); + return getY(); +} + +float BlockDerivative::update(float input) +{ + float output; + + if (_initialized) { + output = _lowPass.update((input - getU()) / getDt()); + + } else { + // if this is the first call to update + // we have no valid derivative + // and so we use the assumption the + // input value is not changing much, + // which is the best we can do here. + _lowPass.update(0.0f); + output = 0.0f; + _initialized = true; + } + + setU(input); + return output; +} + +} // namespace control diff --git a/src/modules/controllib/blocks.hpp b/src/lib/controllib/blocks.hpp similarity index 96% rename from src/modules/controllib/blocks.hpp rename to src/lib/controllib/blocks.hpp index dbaa94d6c5..28b73aa62d 100644 --- a/src/modules/controllib/blocks.hpp +++ b/src/lib/controllib/blocks.hpp @@ -55,8 +55,6 @@ namespace control { -int __EXPORT basicBlocksTest(); - /** * A limiter/ saturation. * The output of update is the input, bounded @@ -82,8 +80,6 @@ protected: control::BlockParamFloat _max; }; -int __EXPORT blockLimitTest(); - /** * A symmetric limiter/ saturation. * Same as limiter but with only a max, is used for @@ -106,8 +102,6 @@ protected: control::BlockParamFloat _max; }; -int __EXPORT blockLimitSymTest(); - /** * A low pass filter as described here: * http://en.wikipedia.org/wiki/Low-pass_filter. @@ -133,8 +127,6 @@ protected: control::BlockParamFloat _fCut; }; -int __EXPORT blockLowPassTest(); - /** * A high pass filter as described here: * http://en.wikipedia.org/wiki/High-pass_filter. @@ -164,8 +156,6 @@ protected: control::BlockParamFloat _fCut; /**< cut-off frequency, Hz */ }; -int __EXPORT blockHighPassTest(); - /** * A 2nd order low pass filter block which uses the default px4 2nd order low pass filter */ @@ -194,8 +184,6 @@ protected: math::LowPassFilter2p _lp; }; -int __EXPORT blockLowPass2Test(); - /** * A rectangular integrator. * A limiter is built into the class to bound the @@ -223,8 +211,6 @@ protected: BlockLimitSym _limit; /**< limiter */ }; -int __EXPORT blockIntegralTest(); - /** * A trapezoidal integrator. * http://en.wikipedia.org/wiki/Trapezoidal_rule @@ -257,8 +243,6 @@ protected: BlockLimitSym _limit; /**< limiter */ }; -int __EXPORT blockIntegralTrapTest(); - /** * A simple derivative approximation. * This uses the previous and current input. @@ -304,8 +288,6 @@ protected: BlockLowPass _lowPass; /**< low pass filter */ }; -int __EXPORT blockDerivativeTest(); - /** * A proportional controller. * @link http://en.wikipedia.org/wiki/PID_controller @@ -329,8 +311,6 @@ protected: control::BlockParamFloat _kP; }; -int __EXPORT blockPTest(); - /** * A proportional-integral controller. * @link http://en.wikipedia.org/wiki/PID_controller @@ -361,8 +341,6 @@ private: control::BlockParamFloat _kI; }; -int __EXPORT blockPITest(); - /** * A proportional-derivative controller. * @link http://en.wikipedia.org/wiki/PID_controller @@ -393,8 +371,6 @@ private: control::BlockParamFloat _kD; }; -int __EXPORT blockPDTest(); - /** * A proportional-integral-derivative controller. * @link http://en.wikipedia.org/wiki/PID_controller @@ -433,8 +409,6 @@ private: control::BlockParamFloat _kD; }; -int __EXPORT blockPIDTest(); - /** * An output trim/ saturation block */ @@ -467,8 +441,6 @@ private: float _val; }; -int __EXPORT blockOutputTest(); - /** * A uniform random number generator */ @@ -503,8 +475,6 @@ private: control::BlockParamFloat _max; }; -int __EXPORT blockRandUniformTest(); - class __EXPORT BlockRandGauss: public Block { public: @@ -553,8 +523,6 @@ private: control::BlockParamFloat _stdDev; }; -int __EXPORT blockRandGaussTest(); - template<class Type, size_t M> class __EXPORT BlockStats: public Block { @@ -599,8 +567,6 @@ private: size_t _count; }; -int __EXPORT blockStatsTest(); - template<class Type, size_t M, size_t N, size_t LEN> class __EXPORT BlockDelay: public Block { @@ -659,6 +625,4 @@ private: int _delay; }; -int __EXPORT blockDelayTest(); - } // namespace control diff --git a/src/modules/controllib/uorb/blocks.cpp b/src/lib/controllib/uorb/blocks.cpp similarity index 100% rename from src/modules/controllib/uorb/blocks.cpp rename to src/lib/controllib/uorb/blocks.cpp diff --git a/src/modules/controllib/uorb/blocks.hpp b/src/lib/controllib/uorb/blocks.hpp similarity index 100% rename from src/modules/controllib/uorb/blocks.hpp rename to src/lib/controllib/uorb/blocks.hpp diff --git a/src/modules/controllib/controllib_test_main.cpp b/src/modules/controllib/controllib_test_main.cpp deleted file mode 100644 index 87950f6ee4..0000000000 --- a/src/modules/controllib/controllib_test_main.cpp +++ /dev/null @@ -1,51 +0,0 @@ -/**************************************************************************** - * - * Copyright (c) 2013-2015 PX4 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 PX4 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. - * - ****************************************************************************/ - -/** - * @file controllib.cpp - * Unit testing for controllib. - * - * @author James Goppert <james.goppert@gmail.com> - */ - -#include "blocks.hpp" - -extern "C" __EXPORT int controllib_test_main(int argc, char *argv[]); - -int controllib_test_main(int argc, char *argv[]) -{ - (void)argc; - (void)argv; - control::basicBlocksTest(); - return 0; -} diff --git a/src/modules/controllib_test/CMakeLists.txt b/src/modules/controllib_test/CMakeLists.txt new file mode 100644 index 0000000000..5d3a221fce --- /dev/null +++ b/src/modules/controllib_test/CMakeLists.txt @@ -0,0 +1,45 @@ +############################################################################ +# +# Copyright (c) 2015 PX4 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 PX4 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. +# +############################################################################ +px4_add_module( + MODULE modules__controllib_test + MAIN controllib_test + COMPILE_FLAGS + -Os + SRCS + controllib_test_main.cpp + test_params.c + DEPENDS + platforms__common + ) + +# vim: set noet ft=cmake fenc=utf-8 ff=unix : diff --git a/src/modules/controllib/blocks.cpp b/src/modules/controllib_test/blocks.cpp similarity index 88% rename from src/modules/controllib/blocks.cpp rename to src/modules/controllib_test/blocks.cpp index 4e0dea37ec..5565833287 100644 --- a/src/modules/controllib/blocks.cpp +++ b/src/modules/controllib_test/blocks.cpp @@ -41,13 +41,32 @@ #include <stdio.h> #include <float.h> -#include "blocks.hpp" +#include <controllib/blocks.hpp> #define ASSERT_CL(T) if (!(T)) { printf("FAIL\n"); return -1; } namespace control { +int basicBlocksTest(); +int blockLimitTest(); +int blockLimitSymTest(); +int blockLowPassTest(); +int blockHighPassTest(); +int blockLowPass2Test(); +int blockIntegralTest(); +int blockIntegralTrapTest(); +int blockDerivativeTest(); +int blockPTest(); +int blockPITest(); +int blockPDTest(); +int blockPIDTest(); +int blockOutputTest(); +int blockRandUniformTest(); +int blockRandGaussTest(); +int blockStatsTest(); +int blockDelayTest(); + int basicBlocksTest() { blockLimitTest(); @@ -71,18 +90,6 @@ int basicBlocksTest() return 0; } -float BlockLimit::update(float input) -{ - if (input > getMax()) { - input = _max.get(); - - } else if (input < getMin()) { - input = getMin(); - } - - return input; -} - int blockLimitTest() { printf("Test BlockLimit\t\t\t: "); @@ -99,18 +106,6 @@ int blockLimitTest() return 0; } -float BlockLimitSym::update(float input) -{ - if (input > getMax()) { - input = _max.get(); - - } else if (input < -getMax()) { - input = -getMax(); - } - - return input; -} - int blockLimitSymTest() { printf("Test BlockLimitSym\t\t: "); @@ -126,18 +121,6 @@ int blockLimitSymTest() return 0; } -float BlockLowPass::update(float input) -{ - if (!PX4_ISFINITE(getState())) { - setState(input); - } - - float b = 2 * float(M_PI) * getFCut() * getDt(); - float a = b / (1 + b); - setState(a * input + (1 - a)*getState()); - return getState(); -} - int blockLowPassTest() { printf("Test BlockLowPass\t\t: "); @@ -166,15 +149,6 @@ int blockLowPassTest() return 0; }; -float BlockHighPass::update(float input) -{ - float b = 2 * float(M_PI) * getFCut() * getDt(); - float a = 1 / (1 + b); - setY(a * (getY() + input - getU())); - setU(input); - return getY(); -} - int blockHighPassTest() { printf("Test BlockHighPass\t\t: "); @@ -206,20 +180,6 @@ int blockHighPassTest() return 0; } -float BlockLowPass2::update(float input) -{ - if (!PX4_ISFINITE(getState())) { - setState(input); - } - - if (fabsf(_lp.get_cutoff_freq() - getFCutParam()) > FLT_EPSILON) { - _lp.set_cutoff_frequency(_fs, getFCutParam()); - } - - _state = _lp.apply(input); - return _state; -} - int blockLowPass2Test() { printf("Test BlockLowPass2\t\t: "); @@ -248,13 +208,6 @@ int blockLowPass2Test() return 0; }; -float BlockIntegral::update(float input) -{ - // trapezoidal integration - setY(_limit.update(getY() + input * getDt())); - return getY(); -} - int blockIntegralTest() { printf("Test BlockIntegral\t\t: "); @@ -292,15 +245,6 @@ int blockIntegralTest() return 0; } -float BlockIntegralTrap::update(float input) -{ - // trapezoidal integration - setY(_limit.update(getY() + - (getU() + input) / 2.0f * getDt())); - setU(input); - return getY(); -} - int blockIntegralTrapTest() { printf("Test BlockIntegralTrap\t\t: "); @@ -344,28 +288,6 @@ int blockIntegralTrapTest() return 0; } -float BlockDerivative::update(float input) -{ - float output; - - if (_initialized) { - output = _lowPass.update((input - getU()) / getDt()); - - } else { - // if this is the first call to update - // we have no valid derivative - // and so we use the assumption the - // input value is not changing much, - // which is the best we can do here. - _lowPass.update(0.0f); - output = 0.0f; - _initialized = true; - } - - setU(input); - return output; -} - int blockDerivativeTest() { printf("Test BlockDerivative\t\t: "); diff --git a/src/modules/controllib_test/controllib_test_main.cpp b/src/modules/controllib_test/controllib_test_main.cpp new file mode 100644 index 0000000000..e785f56419 --- /dev/null +++ b/src/modules/controllib_test/controllib_test_main.cpp @@ -0,0 +1,555 @@ +/**************************************************************************** + * + * Copyright (c) 2013-2015 PX4 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 PX4 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. + * + ****************************************************************************/ + +/** + * @file controllib.cpp + * Unit testing for controllib. + * + * @author James Goppert <james.goppert@gmail.com> + */ + +#include <math.h> +#include <stdio.h> +#include <float.h> + +#include <controllib/blocks.hpp> + +using namespace control; + +#define ASSERT_CL(T) if (!(T)) { printf("FAIL\n"); return -1; } + +int basicBlocksTest(); +int blockLimitTest(); +int blockLimitSymTest(); +int blockLowPassTest(); +int blockHighPassTest(); +int blockLowPass2Test(); +int blockIntegralTest(); +int blockIntegralTrapTest(); +int blockDerivativeTest(); +int blockPTest(); +int blockPITest(); +int blockPDTest(); +int blockPIDTest(); +int blockOutputTest(); +int blockRandUniformTest(); +int blockRandGaussTest(); +int blockStatsTest(); +int blockDelayTest(); + +int basicBlocksTest() +{ + blockLimitTest(); + blockLimitSymTest(); + blockLowPassTest(); + blockHighPassTest(); + blockLowPass2Test(); + blockIntegralTest(); + blockIntegralTrapTest(); + blockDerivativeTest(); + blockPTest(); + blockPITest(); + blockPDTest(); + blockPIDTest(); + blockOutputTest(); + //blockRandUniformTest(); + // known failures + // blockRandGaussTest(); + blockStatsTest(); + blockDelayTest(); + return 0; +} + +int blockLimitTest() +{ + printf("Test BlockLimit\t\t\t: "); + BlockLimit limit(NULL, "TEST"); + // initial state + ASSERT_CL(equal(1.0f, limit.getMax())); + ASSERT_CL(equal(-1.0f, limit.getMin())); + ASSERT_CL(equal(0.0f, limit.getDt())); + // update + ASSERT_CL(equal(-1.0f, limit.update(-2.0f))); + ASSERT_CL(equal(1.0f, limit.update(2.0f))); + ASSERT_CL(equal(0.0f, limit.update(0.0f))); + printf("PASS\n"); + return 0; +} + +int blockLimitSymTest() +{ + printf("Test BlockLimitSym\t\t: "); + BlockLimitSym limit(NULL, "TEST"); + // initial state + ASSERT_CL(equal(1.0f, limit.getMax())); + ASSERT_CL(equal(0.0f, limit.getDt())); + // update + ASSERT_CL(equal(-1.0f, limit.update(-2.0f))); + ASSERT_CL(equal(1.0f, limit.update(2.0f))); + ASSERT_CL(equal(0.0f, limit.update(0.0f))); + printf("PASS\n"); + return 0; +} + +int blockLowPassTest() +{ + printf("Test BlockLowPass\t\t: "); + BlockLowPass lowPass(NULL, "TEST_LP"); + // test initial state + ASSERT_CL(equal(10.0f, lowPass.getFCut())); + ASSERT_CL(equal(0.0f, lowPass.getState())); + ASSERT_CL(equal(0.0f, lowPass.getDt())); + // set dt + lowPass.setDt(0.1f); + ASSERT_CL(equal(0.1f, lowPass.getDt())); + // set state + lowPass.setState(1.0f); + ASSERT_CL(equal(1.0f, lowPass.getState())); + // test update + ASSERT_CL(equal(1.8626974f, lowPass.update(2.0f))); + + // test end condition + for (int i = 0; i < 100; i++) { + lowPass.update(2.0f); + } + + ASSERT_CL(equal(2.0f, lowPass.getState())); + ASSERT_CL(equal(2.0f, lowPass.update(2.0f))); + printf("PASS\n"); + return 0; +}; + +int blockHighPassTest() +{ + printf("Test BlockHighPass\t\t: "); + BlockHighPass highPass(NULL, "TEST_HP"); + // test initial state + ASSERT_CL(equal(10.0f, highPass.getFCut())); + ASSERT_CL(equal(0.0f, highPass.getU())); + ASSERT_CL(equal(0.0f, highPass.getY())); + ASSERT_CL(equal(0.0f, highPass.getDt())); + // set dt + highPass.setDt(0.1f); + ASSERT_CL(equal(0.1f, highPass.getDt())); + // set state + highPass.setU(1.0f); + ASSERT_CL(equal(1.0f, highPass.getU())); + highPass.setY(1.0f); + ASSERT_CL(equal(1.0f, highPass.getY())); + // test update + ASSERT_CL(equal(0.2746051f, highPass.update(2.0f))); + + // test end condition + for (int i = 0; i < 100; i++) { + highPass.update(2.0f); + } + + ASSERT_CL(equal(0.0f, highPass.getY())); + ASSERT_CL(equal(0.0f, highPass.update(2.0f))); + printf("PASS\n"); + return 0; +} + +int blockLowPass2Test() +{ + printf("Test BlockLowPass2\t\t: "); + BlockLowPass2 lowPass(NULL, "TEST_LP", 100); + // test initial state + ASSERT_CL(equal(10.0f, lowPass.getFCutParam())); + ASSERT_CL(equal(0.0f, lowPass.getState())); + ASSERT_CL(equal(0.0f, lowPass.getDt())); + // set dt + lowPass.setDt(0.1f); + ASSERT_CL(equal(0.1f, lowPass.getDt())); + // set state + lowPass.setState(1.0f); + ASSERT_CL(equal(1.0f, lowPass.getState())); + // test update + ASSERT_CL(equal(1.06745527f, lowPass.update(2.0f))); + + // test end condition + for (int i = 0; i < 100; i++) { + lowPass.update(2.0f); + } + + ASSERT_CL(equal(2.0f, lowPass.getState())); + ASSERT_CL(equal(2.0f, lowPass.update(2.0f))); + printf("PASS\n"); + return 0; +}; + +int blockIntegralTest() +{ + printf("Test BlockIntegral\t\t: "); + BlockIntegral integral(NULL, "TEST_I"); + // test initial state + ASSERT_CL(equal(1.0f, integral.getMax())); + ASSERT_CL(equal(0.0f, integral.getDt())); + // set dt + integral.setDt(0.1f); + ASSERT_CL(equal(0.1f, integral.getDt())); + // set Y + integral.setY(0.9f); + ASSERT_CL(equal(0.9f, integral.getY())); + + // test exceed max + for (int i = 0; i < 100; i++) { + integral.update(1.0f); + } + + ASSERT_CL(equal(1.0f, integral.update(1.0f))); + // test exceed min + integral.setY(-0.9f); + ASSERT_CL(equal(-0.9f, integral.getY())); + + for (int i = 0; i < 100; i++) { + integral.update(-1.0f); + } + + ASSERT_CL(equal(-1.0f, integral.update(-1.0f))); + // test update + integral.setY(0.1f); + ASSERT_CL(equal(0.2f, integral.update(1.0))); + ASSERT_CL(equal(0.2f, integral.getY())); + printf("PASS\n"); + return 0; +} + +int blockIntegralTrapTest() +{ + printf("Test BlockIntegralTrap\t\t: "); + BlockIntegralTrap integral(NULL, "TEST_I"); + // test initial state + ASSERT_CL(equal(1.0f, integral.getMax())); + ASSERT_CL(equal(0.0f, integral.getDt())); + // set dt + integral.setDt(0.1f); + ASSERT_CL(equal(0.1f, integral.getDt())); + // set U + integral.setU(1.0f); + ASSERT_CL(equal(1.0f, integral.getU())); + // set Y + integral.setY(0.9f); + ASSERT_CL(equal(0.9f, integral.getY())); + + // test exceed max + for (int i = 0; i < 100; i++) { + integral.update(1.0f); + } + + ASSERT_CL(equal(1.0f, integral.update(1.0f))); + // test exceed min + integral.setU(-1.0f); + integral.setY(-0.9f); + ASSERT_CL(equal(-0.9f, integral.getY())); + + for (int i = 0; i < 100; i++) { + integral.update(-1.0f); + } + + ASSERT_CL(equal(-1.0f, integral.update(-1.0f))); + // test update + integral.setU(2.0f); + integral.setY(0.1f); + ASSERT_CL(equal(0.25f, integral.update(1.0))); + ASSERT_CL(equal(0.25f, integral.getY())); + ASSERT_CL(equal(1.0f, integral.getU())); + printf("PASS\n"); + return 0; +} + +int blockDerivativeTest() +{ + printf("Test BlockDerivative\t\t: "); + BlockDerivative derivative(NULL, "TEST_D"); + // test initial state + ASSERT_CL(equal(0.0f, derivative.getU())); + ASSERT_CL(equal(10.0f, derivative.getLP())); + // set dt + derivative.setDt(0.1f); + ASSERT_CL(equal(0.1f, derivative.getDt())); + // set U + derivative.setU(1.0f); + ASSERT_CL(equal(1.0f, derivative.getU())); + // perform one update so initialized is set + derivative.update(1.0); + ASSERT_CL(equal(1.0f, derivative.getU())); + // test update + ASSERT_CL(equal(8.6269744f, derivative.update(2.0f))); + ASSERT_CL(equal(2.0f, derivative.getU())); + printf("PASS\n"); + return 0; +} + +int blockPTest() +{ + printf("Test BlockP\t\t\t: "); + BlockP blockP(NULL, "TEST_P"); + // test initial state + ASSERT_CL(equal(0.2f, blockP.getKP())); + ASSERT_CL(equal(0.0f, blockP.getDt())); + // set dt + blockP.setDt(0.1f); + ASSERT_CL(equal(0.1f, blockP.getDt())); + // test update + ASSERT_CL(equal(0.4f, blockP.update(2.0f))); + printf("PASS\n"); + return 0; +} + +int blockPITest() +{ + printf("Test BlockPI\t\t\t: "); + BlockPI blockPI(NULL, "TEST"); + // test initial state + ASSERT_CL(equal(0.2f, blockPI.getKP())); + ASSERT_CL(equal(0.1f, blockPI.getKI())); + ASSERT_CL(equal(0.0f, blockPI.getDt())); + ASSERT_CL(equal(1.0f, blockPI.getIntegral().getMax())); + // set dt + blockPI.setDt(0.1f); + ASSERT_CL(equal(0.1f, blockPI.getDt())); + // set integral state + blockPI.getIntegral().setY(0.1f); + ASSERT_CL(equal(0.1f, blockPI.getIntegral().getY())); + // test update + // 0.2*2 + 0.1*(2*0.1 + 0.1) = 0.43 + ASSERT_CL(equal(0.43f, blockPI.update(2.0f))); + printf("PASS\n"); + return 0; +} + +int blockPDTest() +{ + printf("Test BlockPD\t\t\t: "); + BlockPD blockPD(NULL, "TEST"); + // test initial state + ASSERT_CL(equal(0.2f, blockPD.getKP())); + ASSERT_CL(equal(0.01f, blockPD.getKD())); + ASSERT_CL(equal(0.0f, blockPD.getDt())); + ASSERT_CL(equal(10.0f, blockPD.getDerivative().getLP())); + // set dt + blockPD.setDt(0.1f); + ASSERT_CL(equal(0.1f, blockPD.getDt())); + // set derivative state + blockPD.getDerivative().setU(1.0f); + ASSERT_CL(equal(1.0f, blockPD.getDerivative().getU())); + // perform one update so initialized is set + blockPD.getDerivative().update(1.0); + ASSERT_CL(equal(1.0f, blockPD.getDerivative().getU())); + // test update + // 0.2*2 + 0.1*(0.1*8.626...) = 0.486269744 + ASSERT_CL(equal(0.486269744f, blockPD.update(2.0f))); + printf("PASS\n"); + return 0; +} + +int blockPIDTest() +{ + printf("Test BlockPID\t\t\t: "); + BlockPID blockPID(NULL, "TEST"); + // test initial state + ASSERT_CL(equal(0.2f, blockPID.getKP())); + ASSERT_CL(equal(0.1f, blockPID.getKI())); + ASSERT_CL(equal(0.01f, blockPID.getKD())); + ASSERT_CL(equal(0.0f, blockPID.getDt())); + ASSERT_CL(equal(10.0f, blockPID.getDerivative().getLP())); + ASSERT_CL(equal(1.0f, blockPID.getIntegral().getMax())); + // set dt + blockPID.setDt(0.1f); + ASSERT_CL(equal(0.1f, blockPID.getDt())); + // set derivative state + blockPID.getDerivative().setU(1.0f); + ASSERT_CL(equal(1.0f, blockPID.getDerivative().getU())); + // perform one update so initialized is set + blockPID.getDerivative().update(1.0); + ASSERT_CL(equal(1.0f, blockPID.getDerivative().getU())); + // set integral state + blockPID.getIntegral().setY(0.1f); + ASSERT_CL(equal(0.1f, blockPID.getIntegral().getY())); + // test update + // 0.2*2 + 0.1*(2*0.1 + 0.1) + 0.1*(0.1*8.626...) = 0.5162697 + ASSERT_CL(equal(0.5162697f, blockPID.update(2.0f))); + printf("PASS\n"); + return 0; +} + +int blockOutputTest() +{ + printf("Test BlockOutput\t\t: "); + BlockOutput blockOutput(NULL, "TEST"); + // test initial state + ASSERT_CL(equal(0.0f, blockOutput.getDt())); + ASSERT_CL(equal(0.5f, blockOutput.get())); + ASSERT_CL(equal(-1.0f, blockOutput.getMin())); + ASSERT_CL(equal(1.0f, blockOutput.getMax())); + // test update below min + blockOutput.update(-2.0f); + ASSERT_CL(equal(-1.0f, blockOutput.get())); + // test update above max + blockOutput.update(2.0f); + ASSERT_CL(equal(1.0f, blockOutput.get())); + // test trim + blockOutput.update(0.0f); + ASSERT_CL(equal(0.5f, blockOutput.get())); + printf("PASS\n"); + return 0; +} + +int blockRandUniformTest() +{ + srand(1234); + printf("Test BlockRandUniform\t\t: "); + BlockRandUniform blockRandUniform(NULL, "TEST"); + // test initial state + ASSERT_CL(equal(0.0f, blockRandUniform.getDt())); + ASSERT_CL(equal(-1.0f, blockRandUniform.getMin())); + ASSERT_CL(equal(1.0f, blockRandUniform.getMax())); + // test update + int n = 10000; + float mean = blockRandUniform.update(); + + for (int i = 2; i < n + 1; i++) { + float val = blockRandUniform.update(); + mean += (val - mean) / i; + ASSERT_CL(less_than_or_equal(val, blockRandUniform.getMax())); + ASSERT_CL(greater_than_or_equal(val, blockRandUniform.getMin())); + } + + ASSERT_CL(equal(mean, (blockRandUniform.getMin() + + blockRandUniform.getMax()) / 2, 1e-1)); + printf("PASS\n"); + return 0; +} + +int blockRandGaussTest() +{ + srand(1234); + printf("Test BlockRandGauss\t\t: "); + BlockRandGauss blockRandGauss(NULL, "TEST"); + // test initial state + ASSERT_CL(equal(0.0f, blockRandGauss.getDt())); + ASSERT_CL(equal(1.0f, blockRandGauss.getMean())); + ASSERT_CL(equal(2.0f, blockRandGauss.getStdDev())); + // test update + int n = 10000; + float mean = blockRandGauss.update(); + float sum = 0; + + // recursive mean, stdev algorithm from Knuth + for (int i = 2; i < n + 1; i++) { + float val = blockRandGauss.update(); + float newMean = mean + (val - mean) / i; + sum += (val - mean) * (val - newMean); + mean = newMean; + } + + float stdDev = sqrt(sum / (n - 1)); + (void)(stdDev); + ASSERT_CL(equal(mean, blockRandGauss.getMean(), 1e-1)); + ASSERT_CL(equal(stdDev, blockRandGauss.getStdDev(), 1e-1)); + printf("PASS\n"); + return 0; +} + +int blockStatsTest() +{ + printf("Test BlockStats\t\t\t: "); + BlockStats<float, 1> stats(NULL, "TEST"); + ASSERT_CL(equal(0.0f, stats.getMean()(0))); + ASSERT_CL(equal(0.0f, stats.getStdDev()(0))); + stats.update(matrix::Scalar<float>(1.0f)); + stats.update(matrix::Scalar<float>(2)); + ASSERT_CL(equal(1.5f, stats.getMean()(0))); + ASSERT_CL(equal(0.5f, stats.getStdDev()(0))); + stats.reset(); + ASSERT_CL(equal(0.0f, stats.getMean()(0))); + ASSERT_CL(equal(0.0f, stats.getStdDev()(0))); + printf("PASS\n"); + return 0; +} + +int blockDelayTest() +{ + printf("Test BlockDelay\t\t\t: "); + using namespace matrix; + BlockDelay<float, 2, 1, 3> delay(NULL, "TEST"); + Vector2f u1(1, 2); + Vector2f y1 = delay.update(u1); + ASSERT_CL(equal(y1(0), u1(0))); + ASSERT_CL(equal(y1(1), u1(1))); + + Vector2f u2(4, 5); + Vector2f y2 = delay.update(u2); + ASSERT_CL(equal(y2(0), u1(0))); + ASSERT_CL(equal(y2(1), u1(1))); + + Vector2f u3(7, 8); + Vector2f y3 = delay.update(u3); + ASSERT_CL(equal(y3(0), u1(0))); + ASSERT_CL(equal(y3(1), u1(1))); + + Vector2f u4(9, 10); + Vector2f y4 = delay.update(u4); + ASSERT_CL(equal(y4(0), u2(0))); + ASSERT_CL(equal(y4(1), u2(1))); + printf("PASS\n"); + return 0; +} + +extern "C" __EXPORT int controllib_test_main(int argc, char *argv[]); + +int controllib_test_main(int argc, char *argv[]) +{ + (void)argc; + (void)argv; + blockLimitTest(); + blockLimitSymTest(); + blockLowPassTest(); + blockHighPassTest(); + blockLowPass2Test(); + blockIntegralTest(); + blockIntegralTrapTest(); + blockDerivativeTest(); + blockPTest(); + blockPITest(); + blockPDTest(); + blockPIDTest(); + blockOutputTest(); + //blockRandUniformTest(); + // known failures + // blockRandGaussTest(); + blockStatsTest(); + blockDelayTest(); + return 0; +} diff --git a/src/modules/controllib/test_params.c b/src/modules/controllib_test/test_params.c similarity index 100% rename from src/modules/controllib/test_params.c rename to src/modules/controllib_test/test_params.c -- GitLab