Skip to content
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

[sample] add 2D vehicule location example #16

Merged
merged 1 commit into from
Apr 24, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .github/workflows/deploy_test_coverage_coveralls.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@ jobs:
cmake --build . ;
sudo make install ) )
- name: Build
run: gcc-11 sample/*.cpp source/*.cpp test/*.cpp -Iinclude -I/usr/local/include/eigen3 -O0 -g -std=c++23 -fmodules-ts --coverage -lstdc++
run: gcc-11 sample/*.cpp source/*.cpp test/*.cpp -Iinclude -I/usr/local/include/eigen3 -O0 -g -std=c++23 -fmodules-ts --coverage -lstdc++ -lm
- name: "Coverage: Base"
run: |
lcov --rc lcov_branch_coverage=1 --gcov-tool gcov-11 --capture --initial --directory . --output-file base.info
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/verify_test_memory_valgrind.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ jobs:
cmake --build . ;
sudo make install ) )
- name: Build
run: gcc-11 sample/*.cpp test/*.cpp source/*.cpp -Iinclude -I/usr/local/include/eigen3 -g -O0 -std=c++23 -lstdc++
run: gcc-11 sample/*.cpp test/*.cpp source/*.cpp -Iinclude -I/usr/local/include/eigen3 -g -O0 -std=c++23 -lstdc++ -lm
- name: Test
run: valgrind --verbose ./a.out
2 changes: 1 addition & 1 deletion .github/workflows/verify_test_sanitizer_address.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ jobs:
cmake --build . ;
sudo make install ) )
- name: Build
run: gcc-11 sample/*.cpp test/*.cpp source/*.cpp -Iinclude -I/usr/local/include/eigen3 -std=c++23 -g -fsanitize=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer -lstdc++
run: gcc-11 sample/*.cpp test/*.cpp source/*.cpp -Iinclude -I/usr/local/include/eigen3 -std=c++23 -g -fsanitize=address -fsanitize-address-use-after-scope -fno-omit-frame-pointer -lstdc++ -lm
- name: Test
run: ASAN_OPTIONS=verbosity=2:strict_string_checks=1:detect_stack_use_after_return=1:check_initialization_order=1:strict_init_order=1 ./a.out
2 changes: 1 addition & 1 deletion .github/workflows/verify_test_sanitizer_leak.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ jobs:
cmake --build . ;
sudo make install ) )
- name: Build
run: gcc-11 sample/*.cpp test/*.cpp source/*.cpp -Iinclude -I/usr/local/include/eigen3 -std=c++23 -g -fsanitize=leak -lstdc++
run: gcc-11 sample/*.cpp test/*.cpp source/*.cpp -Iinclude -I/usr/local/include/eigen3 -std=c++23 -g -fsanitize=leak -lstdc++ -lm
- name: Test
run: LSAN_OPTIONS=verbosity=2 ./a.out
2 changes: 1 addition & 1 deletion .github/workflows/verify_test_sanitizer_thread.yml
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ jobs:
cmake --build . ;
sudo make install ) )
- name: Build
run: gcc-11 sample/*.cpp test/*.cpp source/*.cpp -Iinclude -I/usr/local/include/eigen3 -std=c++23 -g -fsanitize=thread -lstdc++
run: gcc-11 sample/*.cpp test/*.cpp source/*.cpp -Iinclude -I/usr/local/include/eigen3 -std=c++23 -g -fsanitize=thread -lstdc++ -lm
- name: Test
run: TSAN_OPTIONS=verbosity=2 ./a.out
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,6 @@ jobs:
cmake --build . ;
sudo make install ) )
- name: Build
run: gcc-11 sample/*.cpp test/*.cpp source/*.cpp -Iinclude -I/usr/local/include/eigen3 -std=c++23 -g -fsanitize=undefined -lstdc++
run: gcc-11 sample/*.cpp test/*.cpp source/*.cpp -Iinclude -I/usr/local/include/eigen3 -std=c++23 -g -fsanitize=undefined -lstdc++ -lm
- name: Test
run: UBSAN_OPTIONS=verbosity=2 ./a.out
2 changes: 1 addition & 1 deletion .github/workflows/verify_test_ubuntu-20-04_gcc-trunk.yml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,6 @@ jobs:
cmake --build . ;
sudo make install ) )
- name: Build
run: LD_LIBRARY_PATH=/opt/gcc-latest/lib64 LD_RUN_PATH=/opt/gcc-latest/lib64 /opt/gcc-latest/bin/gcc sample/*.cpp test/*.cpp source/*.cpp -Iinclude -I/usr/local/include/eigen3 -Wall -Wextra -pedantic -std=c++23 -lstdc++
run: LD_LIBRARY_PATH=/opt/gcc-latest/lib64 LD_RUN_PATH=/opt/gcc-latest/lib64 /opt/gcc-latest/bin/gcc sample/*.cpp test/*.cpp source/*.cpp -Iinclude -I/usr/local/include/eigen3 -Wall -Wextra -pedantic -std=c++23 -lstdc++ -lm
- name: Run
run: ./a.out
8 changes: 5 additions & 3 deletions .github/workflows/verify_test_windows-2019_msvc.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,9 @@ jobs:
uses: actions/checkout@v3
- name: Install
uses: ilammy/msvc-dev-cmd@v1.10.0
- name: Version
run: cl
- name: Install Eigen
run: vcpkg install eigen3
- name: Build
run: cl /EHsc /std:c++latest /I include /TP sample/*.cpp source/*.cpp test/*.cpp
run: cl /EHsc /std:c++latest /I include /I C:\vcpkg\packages\eigen3_x86-windows\include\eigen3 /TP sample/*.cpp source/*.cpp test/*.cpp /Fe:kalman.exe
- name: Run
run: ./kalman.exe
16 changes: 8 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -52,11 +52,11 @@ using kalman = fcarouge::kalman<double>;

kalman k;

k.state_x = kalman::state{ 60 };
k.estimate_uncertainty_p = kalman::estimate_uncertainty{ 15 * 15 };
k.transition_observation_h = []() { return kalman::observation{ 1 }; };
k.noise_observation_r = []() {
return kalman::observation_noise_uncertainty{ 5 * 5 };
k.state_x = 60;
k.estimate_uncertainty_p = 225;
k.transition_observation_h = [] { return kalman::observation{ 1 }; };
k.noise_observation_r = [] {
return kalman::observation_noise_uncertainty{ 25 };
};

k.update(48.54);
Expand All @@ -74,7 +74,7 @@ const double gravitational_acceleration{ -9.8 }; // m.s^-2
const std::chrono::milliseconds delta_time{ 250 };
kalman k;

k.state_x = kalman::state{ 0, 0 };
k.state_x = { 0, 0 };
k.estimate_uncertainty_p =
kalman::estimate_uncertainty{ { 500, 0 }, { 0, 500 } };
k.transition_state_f = [](const std::chrono::milliseconds &delta_time) {
Expand All @@ -92,8 +92,8 @@ k.transition_control_g = [](const std::chrono::milliseconds &delta_time) {
const auto dt{ std::chrono::duration<double>(delta_time).count() };
return kalman::control{ 0.0313, dt };
};
k.transition_observation_h = []() { return kalman::observation{ { 1, 0 } }; };
k.noise_observation_r = []() {
k.transition_observation_h = [] { return kalman::observation{ { 1, 0 } }; };
k.noise_observation_r = [] {
return kalman::observation_noise_uncertainty{ 400 };
};

Expand Down
4 changes: 2 additions & 2 deletions include/fcarouge/kalman.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -90,11 +90,11 @@ class kalman
// Functors could be replaced by the standard general-purpose polymorphic
// function wrapper `std::function` if lambda captures are needed.

observation (*transition_observation_h)() = []() {
observation (*transition_observation_h)() = [] {
return observation{ Identity<observation>()() };
};

observation_noise_uncertainty (*noise_observation_r)() = []() {
observation_noise_uncertainty (*noise_observation_r)() = [] {
return observation_noise_uncertainty{};
};

Expand Down
12 changes: 6 additions & 6 deletions sample/building_height.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -21,20 +21,20 @@ namespace
//! 55.01m, 55.15m, 49.89m, 40.85m, 46.72m, 50.05m, 51.27m, 49.95m.
//!
//! @example building_height.cpp
[[maybe_unused]] constexpr auto building_height{ []() {
// One-dimensional filter, constant system dynamic model.
[[maybe_unused]] constexpr auto building_height{ [] {
// A one-dimensional filter, constant system dynamic model.
using kalman = kalman<float>;
kalman k;

// Initialization
// One can estimate the building height simply by looking at it. The estimated
// building height is: 60 meters.
k.state_x = kalman::state{ 60 };
k.state_x = 60;

// Now we shall initialize the estimate uncertainty. A human’s estimation
// error (standard deviation) is about 15 meters: σ = 15. Consequently the
// variance is 225: σ^2 = 225.
k.estimate_uncertainty_p = kalman::estimate_uncertainty{ 15 * 15 };
k.estimate_uncertainty_p = 225;

// Prediction
// Now, we shall predict the next state based on the initialization values.
Expand All @@ -49,8 +49,8 @@ namespace
// The first measurement is: z1 = 48.54m. Since the standard deviation σ of
// the altimeter measurement error is 5, the variance σ^2 would be 25, thus
// the measurement uncertainty is: r1 = 25.
k.noise_observation_r = []() {
return kalman::observation_noise_uncertainty{ 5 * 5 };
k.noise_observation_r = [] {
return kalman::observation_noise_uncertainty{ 25 };
};
k.update(48.54);

Expand Down
22 changes: 12 additions & 10 deletions sample/liquid_temperature.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -26,29 +26,29 @@ namespace
//! 50.023°C, and 49.99°C.
//!
//! @example liquid_temperature.cpp
[[maybe_unused]] constexpr auto liquid_temperature{ []() {
// One-dimensional filter, constant system dynamic model.
[[maybe_unused]] constexpr auto liquid_temperature{ [] {
// A one-dimensional filter, constant system dynamic model.
using kalman = kalman<float>;
kalman k;

// Initialization
// Before the first iteration, we must initialize the Kalman filter and
// predict the next state (which is the first state). We don't know what the
// temperature of the liquid is, and our guess is 10°C.
k.state_x = kalman::state{ 10 };
k.state_x = 10;

// Our guess is very imprecise, so we set our initialization estimate error σ
// to 100. The estimate uncertainty of the initialization is the error
// variance σ^2: p0,0 = 100^2 = 10,000. This variance is very high. If we
// initialize with a more meaningful value, we will get faster Kalman filter
// convergence.
k.estimate_uncertainty_p = kalman::estimate_uncertainty{ 100 * 100 };
k.estimate_uncertainty_p = 100 * 100;

// Prediction
// Now, we shall predict the next state based on the initialization values. We
// think that we have an accurate model, thus we set the process noise
// variance q to 0.0001.
k.noise_process_q = []() {
k.noise_process_q = [] {
return kalman::process_noise_uncertainty{ 0.0001 };
};

Expand All @@ -67,13 +67,13 @@ namespace
// 0.1, the variance σ^2 would be 0.01, thus the measurement uncertainty is:
// r1 = 0.01. The measurement error (standard deviation) is 0.1 degrees
// Celsius.
k.noise_observation_r = []() {
k.noise_observation_r = [] {
return kalman::observation_noise_uncertainty{ 0.1 * 0.1 };
};

k.update(49.95);

// And so on.
// And so on, every measurements period: Δt = 5s (constant).
k.predict();
k.update(49.967);
k.predict();
Expand All @@ -92,15 +92,17 @@ namespace
k.update(50.023);
k.predict();
k.update(49.99);
k.predict();

// The estimate uncertainty quickly goes down, after 10 measurements:
assert(49.988 - 0.0001 < k.state_x && k.state_x < 49.988 + 0.0001 &&
"The filter estimates the liquid temperature at 49.988°C.");
assert(0.0013 - 0.0001 < k.estimate_uncertainty_p &&
k.estimate_uncertainty_p < 0.0013 + 0.0001 &&
"The estimate uncertainty is 0.0013, i.e. the estimate error standard "
"deviation is: 0.036°C.");

k.predict();

assert(49.988 - 0.0001 < k.state_x && k.state_x < 49.988 + 0.0001 &&
"The filter estimates the liquid temperature at 49.988°C.");
// So we can say that the liquid temperature estimate is: 49.988 ± 0.036°C.
// In this example we've measured a liquid temperature using the
// one-dimensional Kalman filter. Although the system dynamics include a
Expand Down
Loading