-
Notifications
You must be signed in to change notification settings - Fork 16
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'enh-add-kalman-filter' of github.com:oddkiva/sara into …
…enh-add-kalman-filter
- Loading branch information
Showing
15 changed files
with
445 additions
and
51 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
59 changes: 59 additions & 0 deletions
59
cpp/src/DO/Sara/MultipleObjectTracking/BaseDefinitions.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
#pragma once | ||
|
||
#include <DO/Sara/Core/EigenExtension.hpp> | ||
|
||
|
||
namespace DO::Sara::MultipleObjectTracking { | ||
|
||
//! A pedestrian has a state which we model as a cylindric box and encode as a | ||
//! 4D vector | ||
//! (x, y, a, h) | ||
//! where: | ||
//! - (x, y) is the position of the pedestrian in meters w.r.t. the vehicle | ||
//! frame | ||
//! - a is the aspect ratio | ||
//! - h is the height of the pedestrian | ||
//! | ||
//! In this modelling, we assume that the road is flat and on the plane | ||
//! z = 0. | ||
//! | ||
//! That means that the 3D coordinates of the pedestrian feet is | ||
//! (x, y, 0) | ||
//! in the vehicle frame. | ||
template <typename T> | ||
using CylindricBoxObservationVector = Eigen::Vector4<T>; | ||
|
||
//! In practice the pedestrian state is expanded into a larger 12D vector that | ||
//! concatenates the 3 4D vectors: | ||
//! (x, y, a, h) the base state vector | ||
//! (dx, dy, da, dh) 1st-order differential of the base state vector | ||
//! (d2x, d2y, d2a, d2h) 2nd-order differential of the base state vector | ||
//! | ||
//! The differentials are used indeed in the transition matrix in the Kalman | ||
//! filter. | ||
template <typename T> | ||
using CylindricBoxStateVector = Eigen::Vector<T, 12>; | ||
|
||
|
||
template <typename T> | ||
struct ObservationDistribution | ||
{ | ||
using Mean = CylindricBoxObservationVector<T>; | ||
using CovarianceMatrix = Eigen::Matrix4<T>; | ||
|
||
Mean μ; | ||
CovarianceMatrix Σ; | ||
}; | ||
|
||
template <typename T> | ||
struct StateDistribution | ||
{ | ||
using Mean = CylindricBoxStateVector<T>; | ||
using CovarianceMatrix = Eigen::Matrix<T, 12, 12>; | ||
|
||
Mean μ; | ||
CovarianceMatrix Σ; | ||
}; | ||
|
||
|
||
} // namespace DO::Sara::MultipleObjectTracking |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#pragma once | ||
|
||
#include <DO/Sara/Core/EigenExtension.hpp> | ||
|
||
|
||
namespace DO::Sara { | ||
|
||
template <typename Derived> | ||
inline auto cosine_similarity(const Eigen::MatrixBase<Derived>& a, | ||
const Eigen::MatrixBase<Derived>& b, | ||
Eigen::MatrixBase<Derived>& c) -> void | ||
{ | ||
c = a * b.transpose(); | ||
} | ||
|
||
template <typename Derived> | ||
inline auto cosine_distance(const Eigen::MatrixBase<Derived>& a, | ||
const Eigen::MatrixBase<Derived>& b, | ||
Eigen::MatrixBase<Derived>& c) -> void | ||
{ | ||
using T = typename Eigen::MatrixBase<Derived>::Scalar; | ||
static constexpr auto one = static_cast<T>(1); | ||
c = cosine_similarity(a, b); | ||
c.array() = one - c.array(); | ||
} | ||
|
||
} // namespace DO::Sara |
72 changes: 72 additions & 0 deletions
72
cpp/src/DO/Sara/MultipleObjectTracking/ObservationModel.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
#pragma once | ||
|
||
#include <DO/Sara/MultipleObjectTracking/BaseDefinitions.hpp> | ||
#include <DO/Sara/MultipleObjectTracking/ObservationNoiseDistribution.hpp> | ||
|
||
|
||
namespace DO::Sara::MultipleObjectTracking { | ||
|
||
template <typename T> | ||
struct ObservationEquation | ||
{ | ||
using State = StateDistribution<T>; | ||
|
||
using Observation = ObservationDistribution<T>; | ||
using ObservationNoise = ObservationNoiseDistribution<T>; | ||
using ObservationModelMatrix = Eigen::Matrix<T, 4, 12>; | ||
|
||
using Innovation = Observation; | ||
using KalmanGain = typename ObservationDistribution<T>::CovarianceMatrix; | ||
|
||
inline static auto observation_model_matrix() -> ObservationModelMatrix | ||
{ | ||
auto H = ObservationModelMatrix{}; | ||
|
||
static const auto I = Eigen::Matrix4<T>::Identity(); | ||
static const auto O = Eigen::Matrix<T, 4, 8>::Zero(); | ||
H << I, O; | ||
|
||
return H; | ||
} | ||
|
||
inline auto innovation(const State& x_a_priori, | ||
const Observation& z) const // | ||
-> Innovation | ||
{ | ||
return { | ||
.μ = z - H * x_a_priori, // | ||
.Σ = H * x_a_priori.Σ * H.transpose() + v.Σ // | ||
}; | ||
} | ||
|
||
inline auto kalman_gain_matrix(const Observation& x_predicted, | ||
const Innovation& S) const // | ||
-> KalmanGain | ||
{ | ||
return x_predicted.Σ * H.transpose() * S.Σ.inverse(); | ||
} | ||
|
||
inline auto update(const State& x_predicted, const Observation& z) -> State | ||
{ | ||
const auto y = innovation(x_predicted, z); | ||
const auto K = kalman_gain_matrix(x_predicted, y); | ||
|
||
static const auto I = State::CovarianceMatrix::Identity(); | ||
return { | ||
.μ = x_predicted.μ + K * y.μ, // | ||
.Σ = (I - K * H) * x_predicted.Σ // | ||
}; | ||
} | ||
|
||
inline auto residual(const Observation& z, | ||
const State& x) const // | ||
-> typename Observation::Mean | ||
{ | ||
return z.μ - H * x.μ; | ||
} | ||
|
||
const ObservationModelMatrix H = observation_model_matrix(); | ||
ObservationNoise v; | ||
}; | ||
|
||
} // namespace DO::Sara::MultipleObjectTracking |
50 changes: 50 additions & 0 deletions
50
cpp/src/DO/Sara/MultipleObjectTracking/ObservationNoiseDistribution.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
#pragma once | ||
|
||
#include <DO/Sara/MultipleObjectTracking/BaseDefinitions.hpp> | ||
|
||
#include <DO/Sara/Core/PhysicalQuantities.hpp> | ||
|
||
|
||
namespace DO::Sara::MultipleObjectTracking { | ||
|
||
//! The observation noise is the discrepancy between the state predicted by | ||
//! state-transition equation and the observation i.e. the cylindric bounding | ||
//! box. | ||
//! | ||
//! The observation is in our case obtained from metrologic formulas and a | ||
//! specified camera calibration parameter. | ||
//! | ||
//! The observation noise should also factor in measurement error when we | ||
//! obtain the observation vector. | ||
//! | ||
//! In the Kalman filter, the observation noise follows a zero-mean Gaussian | ||
//! distribution. | ||
template <typename T> | ||
struct ObservationNoiseDistribution | ||
{ | ||
using Mean = typename ObservationDistribution<T>::Mean; | ||
using CovarianceMatrix = | ||
typename ObservationDistribution<T>::CovarianceMatrix; | ||
|
||
static constexpr auto distance_error = 0.5_m; | ||
static constexpr auto typical_pedestrian_height = 1.75_m; | ||
|
||
static inline auto default_standard_deviation( // | ||
const Length σ_x = distance_error, // | ||
const Length σ_y = distance_error, // | ||
const T σ_a = static_cast<T>(0.1), | ||
const Length σ_h = 5._percent * typical_pedestrian_height) | ||
-> CovarianceMatrix | ||
{ | ||
return {σ_x.as<T>(), σ_y.as<T>(), σ_a, σ_h.as<T>()}; | ||
} | ||
|
||
inline static auto default_covariance_matrix() -> CovarianceMatrix | ||
{ | ||
return default_standard_deviation().array().square().asDiagonal(); | ||
} | ||
|
||
CovarianceMatrix Σ; | ||
}; | ||
|
||
} // namespace DO::Sara::MultipleObjectTracking |
59 changes: 59 additions & 0 deletions
59
cpp/src/DO/Sara/MultipleObjectTracking/ProcessNoiseDistribution.hpp
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,59 @@ | ||
#pragma once | ||
|
||
#include <DO/Sara/MultipleObjectTracking/BaseDefinitions.hpp> | ||
#include <DO/Sara/MultipleObjectTracking/ObservationNoiseDistribution.hpp> | ||
|
||
|
||
namespace DO::Sara::MultipleObjectTracking { | ||
|
||
//! The process noise is the error that the state transition equation makes. | ||
//! | ||
//! In the Kalman filter, the process noise follows a zero-mean Gaussian | ||
//! distribution. | ||
template <typename T> | ||
struct ProcessNoiseDistribution | ||
{ | ||
using Mean = typename StateDistribution<T>::Mean; | ||
using CovarianceMatrix = typename StateDistribution<T>::CovarianceMatrix; | ||
|
||
static constexpr auto distance_error = | ||
ObservationNoiseDistribution<T>::distance_error; | ||
static constexpr auto typical_pedestrian_height = | ||
ObservationNoiseDistribution<T>::typical_pedestrian_height; | ||
|
||
static constexpr auto speed_error = 5._km / hour; | ||
static constexpr auto acceleration_error = (3._km / hour) / 0.5_s; | ||
|
||
static constexpr auto car_speed_acceleration = (60.L * mile / hour) / 5._s; | ||
static constexpr auto car_speed_acceleration_error = | ||
0.2L * car_speed_acceleration; | ||
|
||
inline static auto default_standard_deviation() -> Mean | ||
{ | ||
auto σ = Mean{}; | ||
|
||
// clang-format off | ||
σ << | ||
ObservationNoiseDistribution<T>::standard_deviation(), | ||
speed_error, | ||
speed_error, | ||
0, | ||
0, | ||
acceleration_error, | ||
acceleration_error, | ||
0, | ||
0; | ||
// clang-format on | ||
|
||
return σ; | ||
} | ||
|
||
inline static auto default_covariance_matrix() -> CovarianceMatrix | ||
{ | ||
return default_standard_deviation().array().square().asDiagonal(); | ||
} | ||
|
||
CovarianceMatrix Σ; | ||
}; | ||
|
||
} // namespace DO::Sara::MultipleObjectTracking |
Oops, something went wrong.