-
Notifications
You must be signed in to change notification settings - Fork 55
Implement batch API for Kalman filter #660
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
base: master
Are you sure you want to change the base?
Conversation
ThreeMonth03
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yungyuc Please review this pull request. Thanks.
| for (size_t iter = 0; iter < z_m; ++iter) | ||
| { | ||
| for (size_t j = 0; j < z_n; ++j) | ||
| { | ||
| z(j) = zs(iter, j); | ||
| } | ||
|
|
||
| if (iter < u_m) | ||
| { | ||
| for (size_t j = 0; j < u_n; ++j) | ||
| { | ||
| u(j) = us(iter, j); | ||
| } | ||
| } | ||
| else if (iter == u_m) | ||
| { | ||
| u = array_type(small_vector<size_t>{0}); | ||
| } | ||
|
|
||
| predict_and_update(z, u, bfs, iter); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Iterate the data points according to the first dimension.
yungyuc
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can do this for now. But to really test the implementation, we need an application for the Kalman filter.
-
KalmanFilter::bf_typeneeds a helper class.
We are about to have a hammer. Let's find a nail.
cpp/modmesh/linalg/kalman_filter.hpp
Outdated
| using value_type = T; | ||
| using real_type = typename detail::select_real_t<value_type>::type; | ||
| using array_type = SimpleArray<T>; | ||
| using bf_type = std::tuple<array_type, array_type, array_type, array_type>; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This bf_type needs a helper class. std::tuple should not be used because it is too difficult to document for each of the field.
The alias should probably be avoided once the helper class is made and named carefully.
cpp/modmesh/linalg/kalman_filter.hpp
Outdated
| if (u.shape(0) > 0) | ||
| { | ||
| predict(u); | ||
| } | ||
| else | ||
| { | ||
| predict(); | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Is possible to separate with / without control input into 2 functions to avoid this branch ?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, I thought that the row of control input may be missing value, but it can be deal with at a different module.
a6d6674 to
2f37b62
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can do this for now. But to really test the implementation, we need an application for the Kalman filter.
KalmanFilter::bf_typeneeds a helper class.We are about to have a hammer. Let's find a nail.
@yungyuc. I fix it. Please review this pull request. Thanks.
cpp/modmesh/linalg/kalman_filter.hpp
Outdated
| template <typename T> | ||
| class BatchFilterHelper | ||
| { | ||
| using tuple_type = std::tuple<SimpleArray<T>, SimpleArray<T>, SimpleArray<T>, SimpleArray<T>>; | ||
|
|
||
| public: | ||
| BatchFilterHelper(size_t observation_size, size_t state_size) | ||
| { | ||
| small_vector<size_t> xs_shape{observation_size, state_size}; | ||
| small_vector<size_t> ps_shape{observation_size, state_size, state_size}; | ||
| m_prior_xs = SimpleArray<T>(xs_shape); | ||
| m_prior_ps = SimpleArray<T>(ps_shape); | ||
| m_posterior_xs = SimpleArray<T>(xs_shape); | ||
| m_posterior_ps = SimpleArray<T>(ps_shape); | ||
| } | ||
| SimpleArray<T> & prior_xs() | ||
| { | ||
| return m_prior_xs; | ||
| } | ||
| SimpleArray<T> & prior_ps() | ||
| { | ||
| return m_prior_ps; | ||
| } | ||
| SimpleArray<T> & posterior_xs() | ||
| { | ||
| return m_posterior_xs; | ||
| } | ||
| SimpleArray<T> & posterior_ps() | ||
| { | ||
| return m_posterior_ps; | ||
| } | ||
| tuple_type to_tuple() const | ||
| { | ||
| return std::make_tuple(m_prior_xs, m_prior_ps, m_posterior_xs, m_posterior_ps); | ||
| } | ||
|
|
||
| private: | ||
| SimpleArray<T> m_prior_xs; | ||
| SimpleArray<T> m_prior_ps; | ||
| SimpleArray<T> m_posterior_xs; | ||
| SimpleArray<T> m_posterior_ps; | ||
| }; /* end class BatchFilterHelper */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Create the batch filter helper.
| template <typename T> | ||
| BatchFilterHelper<T> KalmanFilter<T>::batch_filter(array_type const & zs, std::unique_ptr<array_type> const & us_ptr) | ||
| { | ||
| size_t z_m = zs.shape(0); | ||
| size_t z_n = zs.shape(1); | ||
| array_type z(small_vector<size_t>{z_n}); | ||
| BatchFilterHelper<T> bfs(z_m, m_state_size); | ||
|
|
||
| std::unique_ptr<array_type> u_ptr = nullptr; | ||
| size_t u_n = 0; | ||
| if (us_ptr) | ||
| { | ||
| size_t u_m = us_ptr->shape(0); | ||
| if (u_m != z_m) | ||
| { | ||
| throw std::invalid_argument("KalmanFilter::batch_filter: The number of control inputs must match the number of measurements."); | ||
| } | ||
| u_n = us_ptr->shape(1); | ||
| u_ptr = std::make_unique<array_type>(small_vector<size_t>{u_n}); | ||
| } | ||
|
|
||
| for (size_t iter = 0; iter < z_m; ++iter) | ||
| { | ||
| for (size_t j = 0; j < z_n; ++j) | ||
| { | ||
| z(j) = zs(iter, j); | ||
| } | ||
| if (us_ptr) | ||
| { | ||
| for (size_t j = 0; j < u_n; ++j) | ||
| { | ||
| (*u_ptr)(j) = (*us_ptr)(iter, j); | ||
| } | ||
| } | ||
| predict_and_update(z, u_ptr, bfs, iter); | ||
| } | ||
| return bfs; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not sure whether it is a good idea to deal with the similar pattern by std::unique_ptr or std::optional.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see the necessary why you need to use unique_ptr.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see the necessary why you need to use
unique_ptr.
The argument of control input u is optional, I'm not sure which design is the best choice:
1. Overloading: It the contol input is 0 dimensional SimpleArray, it should be seen as the null input.
2. std::optional
3. std:unique_ptr
4. Coding the similar logic twice: It looks quite long.
| .def( | ||
| "batch_filter", | ||
| [](wrapped_type & self, array_type const & zs, array_type const & us) | ||
| { | ||
| return self.batch_filter(zs, us).to_tuple(); | ||
| }, | ||
| py::arg("zs"), | ||
| py::arg("us")) | ||
| .def( | ||
| "batch_filter", | ||
| [](wrapped_type & self, array_type const & zs) | ||
| { | ||
| return self.batch_filter(zs).to_tuple(); | ||
| }, | ||
| py::arg("zs")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To pass a few return variables, the helper class should be casted to std::tuple.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tuple is hard to maintain. Python invented named tuple to mitigate.
But we are using C++ already. Why don't you just wrap the array container (BFType) to Python and return it? It will work just like a named tuple in Python.
Doing it will need to turn BFType to a class with accessors, though.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The use of unique_ptr is not necessary and should be removed from the PR.
More points to address:
- Add a comment block to describe
BatchFilterHelperand give the class a better name. - Evaluate if
BatchFilterHelpershould have accessors removed and changed to bestruct. - ALERT: Are you sure you want to force data copy for calling
predict?
cpp/modmesh/linalg/kalman_filter.hpp
Outdated
| } /* end namespace detail */ | ||
|
|
||
| template <typename T> | ||
| class BatchFilterHelper |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Provide a description block of comment for the class. I don't know what does "filter" mean and please explain that at least.
Rename it to be meaningful (and as concise as BatchFilterHelper).
BatchFilterHelper does not carry much information. It does not help readers.
Also consider to make it a struct with all member data public and remove the accessors. All the member data now are arrays. In this scenario, accessors are not very useful.
cpp/modmesh/linalg/kalman_filter.hpp
Outdated
| } | ||
|
|
||
| private: | ||
| SimpleArray<T> m_prior_xs; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
What do the member data array mean? It's hard to tell from the variable names.
cpp/modmesh/linalg/kalman_filter.hpp
Outdated
|
|
||
| // P <- 0.5(P + P^H) (m_p <- 0.5(m_p + m_p^H)) | ||
| m_p = m_p.symmetrize(); | ||
| predict(std::make_unique<array_type>(u)); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
make_unique constructs a new array and copy the data. It will be slow. Are you sure you want to force data copy for calling predict?
| template <typename T> | ||
| BatchFilterHelper<T> KalmanFilter<T>::batch_filter(array_type const & zs, std::unique_ptr<array_type> const & us_ptr) | ||
| { | ||
| size_t z_m = zs.shape(0); | ||
| size_t z_n = zs.shape(1); | ||
| array_type z(small_vector<size_t>{z_n}); | ||
| BatchFilterHelper<T> bfs(z_m, m_state_size); | ||
|
|
||
| std::unique_ptr<array_type> u_ptr = nullptr; | ||
| size_t u_n = 0; | ||
| if (us_ptr) | ||
| { | ||
| size_t u_m = us_ptr->shape(0); | ||
| if (u_m != z_m) | ||
| { | ||
| throw std::invalid_argument("KalmanFilter::batch_filter: The number of control inputs must match the number of measurements."); | ||
| } | ||
| u_n = us_ptr->shape(1); | ||
| u_ptr = std::make_unique<array_type>(small_vector<size_t>{u_n}); | ||
| } | ||
|
|
||
| for (size_t iter = 0; iter < z_m; ++iter) | ||
| { | ||
| for (size_t j = 0; j < z_n; ++j) | ||
| { | ||
| z(j) = zs(iter, j); | ||
| } | ||
| if (us_ptr) | ||
| { | ||
| for (size_t j = 0; j < u_n; ++j) | ||
| { | ||
| (*u_ptr)(j) = (*us_ptr)(iter, j); | ||
| } | ||
| } | ||
| predict_and_update(z, u_ptr, bfs, iter); | ||
| } | ||
| return bfs; | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't see the necessary why you need to use unique_ptr.
cpp/modmesh/linalg/kalman_filter.hpp
Outdated
| } | ||
|
|
||
| template <typename T> | ||
| BatchFilterHelper<T> KalmanFilter<T>::batch_filter(array_type const & zs, std::unique_ptr<array_type> const & us_ptr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's a bad idea to be needing to include _ptr in the variable name to signify it's a pointer.
One of the argument is array_type and the other is unique_ptr<array_type>. I do not see why you need different argument types for the two arrays. It smells bad.
cpp/modmesh/linalg/kalman_filter.hpp
Outdated
|
|
||
| private: | ||
|
|
||
| void predict(std::unique_ptr<array_type> const & u_ptr) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I do not see why you need to use unique_ptr here.
cpp/modmesh/linalg/kalman_filter.hpp
Outdated
| void predict_state(); | ||
| void predict_state(array_type const & u); | ||
| // void predict_state(); | ||
| void predict_state(std::unique_ptr<array_type> const & u_ptr); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is the reason you change many places to use unique_ptr and it does not make sense to me.
c948592 to
9d141e7
Compare
ThreeMonth03
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Add a comment block to describe
BatchFilterHelperand give the class a better name.- Evaluate if
BatchFilterHelpershould have accessors removed and changed to bestruct.- The use of
unique_ptris not necessary and should be removed from the PR.
@yungyuc Please review this pull request again. Thanks.
cpp/modmesh/linalg/kalman_filter.hpp
Outdated
| struct BFType | ||
| { | ||
| using tuple_type = std::tuple<SimpleArray<T>, SimpleArray<T>, SimpleArray<T>, SimpleArray<T>>; | ||
|
|
||
| BFType(size_t observation_size, size_t state_size) | ||
| { | ||
| small_vector<size_t> xs_shape{observation_size, state_size}; | ||
| small_vector<size_t> ps_shape{observation_size, state_size, state_size}; | ||
| prior_state = SimpleArray<T>(xs_shape); | ||
| prior_state_covariance = SimpleArray<T>(ps_shape); | ||
| posterior_state = SimpleArray<T>(xs_shape); | ||
| posterior_state_covariance = SimpleArray<T>(ps_shape); | ||
| } | ||
| tuple_type to_tuple() const | ||
| { | ||
| return std::make_tuple(prior_state, prior_state_covariance, posterior_state, posterior_state_covariance); | ||
| } | ||
|
|
||
| SimpleArray<T> prior_state; | ||
| SimpleArray<T> prior_state_covariance; | ||
| SimpleArray<T> posterior_state; | ||
| SimpleArray<T> posterior_state_covariance; | ||
| }; /* end struct BFType */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Change to POD design, and name it as BFtype.
| /** | ||
| * @brief Predict and update in batch mode without a batch of control input us. | ||
| * | ||
| * @ref https://filterpy.readthedocs.io/en/latest/_modules/filterpy/kalman/kalman_filter.html#KalmanFilter.batch_filter | ||
| * | ||
| * @param zs A batch of measurement inputs. | ||
| * | ||
| * @see BFType<T> KalmanFilter<T>::batch_filter(array_type const & zs, array_type const & us) | ||
| * @see struct BFType<T>; | ||
| */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The api design is refered from filter.py, and it is the origin of the api naming.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clarify what is filter.py.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's not filter.py, that is FilterPy, a kalman filter library implemented by python.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Make it clear in the code comment block.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's clear.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yungyuc Please review this pull request again. Thanks.
I did not see your response to all my comments. In the future, when changing the code, please also leave comments in the review to make it smoother.
Points to address:
- Clearly define
BFTypein the header comment block. Currently it only says it's the return type and it is not informative enough. - Move the logic in
BFType::to_tupleto the Python wrapper (pybind11). - Clarify what is "filter.py".
- Evaluate if it reasonable to just wrap the array container (
BFType) to Python and return it from C++ to Python.
cpp/modmesh/linalg/kalman_filter.hpp
Outdated
| } /* end namespace detail */ | ||
|
|
||
| /** | ||
| * @brief Return type for `KalmanFilter<T>::batch_filter(...)`. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It is not informative:
Return type for
KalmanFilter<T>::batch_filter(...)
Define the type clearly in the comment block.
cpp/modmesh/linalg/kalman_filter.hpp
Outdated
| posterior_state = SimpleArray<T>(xs_shape); | ||
| posterior_state_covariance = SimpleArray<T>(ps_shape); | ||
| } | ||
| tuple_type to_tuple() const |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This BFType::to_tuple is only for Python wrapper. It should not be put in the C++ core. The code should be moved to the Python wrapper (pybind11).
| /** | ||
| * @brief Predict and update in batch mode without a batch of control input us. | ||
| * | ||
| * @ref https://filterpy.readthedocs.io/en/latest/_modules/filterpy/kalman/kalman_filter.html#KalmanFilter.batch_filter | ||
| * | ||
| * @param zs A batch of measurement inputs. | ||
| * | ||
| * @see BFType<T> KalmanFilter<T>::batch_filter(array_type const & zs, array_type const & us) | ||
| * @see struct BFType<T>; | ||
| */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Clarify what is filter.py.
| .def( | ||
| "batch_filter", | ||
| [](wrapped_type & self, array_type const & zs, array_type const & us) | ||
| { | ||
| return self.batch_filter(zs, us).to_tuple(); | ||
| }, | ||
| py::arg("zs"), | ||
| py::arg("us")) | ||
| .def( | ||
| "batch_filter", | ||
| [](wrapped_type & self, array_type const & zs) | ||
| { | ||
| return self.batch_filter(zs).to_tuple(); | ||
| }, | ||
| py::arg("zs")); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Tuple is hard to maintain. Python invented named tuple to mitigate.
But we are using C++ already. Why don't you just wrap the array container (BFType) to Python and return it? It will work just like a named tuple in Python.
Doing it will need to turn BFType to a class with accessors, though.
89ef61c to
0a079c5
Compare
ThreeMonth03
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@yungyuc Please review this pull request again. Thanks.
I did not see your response to all my comments. In the future, when changing the code, please also leave comments in the review to make it smoother.
Points to address:
- Clearly define
BFTypein the header comment block. Currently it only says it's the return type and it is not informative enough.- Move the logic in
BFType::to_tupleto the Python wrapper (pybind11).- Clarify what is "filter.py".
- Evaluate if it reasonable to just wrap the array container (
BFType) to Python and return it from C++ to Python.
@yungyuc You could review this pull request when you are available. Thanks.
cpp/modmesh/linalg/kalman_filter.hpp
Outdated
| /** | ||
| * @brief `StatsInfo` includes prior and posterior states and their covariances, | ||
| * and it is the return type of `KalmanFilter<T>::batch_filter(...)`. | ||
| * | ||
| * @details | ||
| * Due to the iteration of the predict and update steps in `KalmanFilter<T>::batch_filter(...)`, the | ||
| * intermediate results are stored for each time step, including | ||
| * - prior_states | ||
| * - prior_states_covariance | ||
| * - posterior_states | ||
| * - posterior_states_covariance | ||
| * | ||
| * @see StatesInfo<T> KalmanFilter<T>::batch_filter(array_type const & zs) | ||
| * @see StatesInfo<T> KalmanFilter<T>::batch_filter(array_type const & zs, array_type const & us) | ||
| */ | ||
| template <typename T> | ||
| struct StatesInfo | ||
| { | ||
| using tuple_type = std::tuple<SimpleArray<T>, SimpleArray<T>, SimpleArray<T>, SimpleArray<T>>; | ||
|
|
||
| StatesInfo(size_t observation_size, size_t state_size) | ||
| { | ||
| small_vector<size_t> xs_shape{observation_size, state_size}; | ||
| small_vector<size_t> ps_shape{observation_size, state_size, state_size}; | ||
| prior_states = SimpleArray<T>(xs_shape); | ||
| prior_states_covariance = SimpleArray<T>(ps_shape); | ||
| posterior_states = SimpleArray<T>(xs_shape); | ||
| posterior_states_covariance = SimpleArray<T>(ps_shape); | ||
| } | ||
|
|
||
| SimpleArray<T> prior_states; | ||
| SimpleArray<T> prior_states_covariance; | ||
| SimpleArray<T> posterior_states; | ||
| SimpleArray<T> posterior_states_covariance; | ||
| }; /* end struct StatesInfo */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rename BFType to StatesInfo, and write a detail comment above.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is clear. Rename to KalmanStateInfo. StateInfo is too generic. Prefixing Kalman works like a namespace (but we do not want to use a real namespace).
| /** | ||
| * @brief Predict and update in batch mode without a batch of control input us. | ||
| * | ||
| * @ref https://filterpy.readthedocs.io/en/latest/_modules/filterpy/kalman/kalman_filter.html#KalmanFilter.batch_filter | ||
| * | ||
| * @param zs A batch of measurement inputs. | ||
| * | ||
| * @see BFType<T> KalmanFilter<T>::batch_filter(array_type const & zs, array_type const & us) | ||
| * @see struct BFType<T>; | ||
| */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Done.
| template <typename T> | ||
| class MODMESH_PYTHON_WRAPPER_VISIBILITY WrapStatesInfo | ||
| : public WrapBase<WrapStatesInfo<T>, StatesInfo<T>> | ||
| { | ||
| using base_type = WrapBase<WrapStatesInfo<T>, StatesInfo<T>>; | ||
| using wrapped_type = typename base_type::wrapped_type; | ||
| using array_type = SimpleArray<T>; | ||
|
|
||
| friend base_type; | ||
|
|
||
| WrapStatesInfo(pybind11::module & mod, char const * pyname, char const * pydoc) | ||
| : base_type(mod, pyname, pydoc) | ||
| { | ||
| namespace py = pybind11; | ||
|
|
||
| (*this) | ||
| .def( | ||
| py::init( | ||
| [](size_t observation_size, size_t state_size) | ||
| { | ||
| return wrapped_type(observation_size, state_size); | ||
| }), | ||
| py::arg("observation_size"), | ||
| py::arg("state_size")) | ||
| .def_readwrite( | ||
| "prior_states", &wrapped_type::prior_states) | ||
| .def_readwrite( | ||
| "prior_states_covariance", &wrapped_type::prior_states_covariance) | ||
| .def_readwrite( | ||
| "posterior_states", &wrapped_type::posterior_states) | ||
| .def_readwrite( | ||
| "posterior_states_covariance", &wrapped_type::posterior_states_covariance); | ||
| } | ||
|
|
||
| }; /* end class StatesInfo */ | ||
|
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Wrap StatesInfo to python.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One more point to address:
- Rename
StatesInfotoKalmanStateInfo.
cpp/modmesh/linalg/kalman_filter.hpp
Outdated
| } /* end namespace detail */ | ||
|
|
||
| /** | ||
| * @brief `StatsInfo` includes prior and posterior states and their covariances, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix the typo StatsInfo here in the brief (missing "e").
cpp/modmesh/linalg/kalman_filter.hpp
Outdated
| /** | ||
| * @brief `StatsInfo` includes prior and posterior states and their covariances, | ||
| * and it is the return type of `KalmanFilter<T>::batch_filter(...)`. | ||
| * | ||
| * @details | ||
| * Due to the iteration of the predict and update steps in `KalmanFilter<T>::batch_filter(...)`, the | ||
| * intermediate results are stored for each time step, including | ||
| * - prior_states | ||
| * - prior_states_covariance | ||
| * - posterior_states | ||
| * - posterior_states_covariance | ||
| * | ||
| * @see StatesInfo<T> KalmanFilter<T>::batch_filter(array_type const & zs) | ||
| * @see StatesInfo<T> KalmanFilter<T>::batch_filter(array_type const & zs, array_type const & us) | ||
| */ | ||
| template <typename T> | ||
| struct StatesInfo | ||
| { | ||
| using tuple_type = std::tuple<SimpleArray<T>, SimpleArray<T>, SimpleArray<T>, SimpleArray<T>>; | ||
|
|
||
| StatesInfo(size_t observation_size, size_t state_size) | ||
| { | ||
| small_vector<size_t> xs_shape{observation_size, state_size}; | ||
| small_vector<size_t> ps_shape{observation_size, state_size, state_size}; | ||
| prior_states = SimpleArray<T>(xs_shape); | ||
| prior_states_covariance = SimpleArray<T>(ps_shape); | ||
| posterior_states = SimpleArray<T>(xs_shape); | ||
| posterior_states_covariance = SimpleArray<T>(ps_shape); | ||
| } | ||
|
|
||
| SimpleArray<T> prior_states; | ||
| SimpleArray<T> prior_states_covariance; | ||
| SimpleArray<T> posterior_states; | ||
| SimpleArray<T> posterior_states_covariance; | ||
| }; /* end struct StatesInfo */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is clear. Rename to KalmanStateInfo. StateInfo is too generic. Prefixing Kalman works like a namespace (but we do not want to use a real namespace).
| /** | ||
| * @brief Predict and update in batch mode without a batch of control input us. | ||
| * | ||
| * @ref https://filterpy.readthedocs.io/en/latest/_modules/filterpy/kalman/kalman_filter.html#KalmanFilter.batch_filter | ||
| * | ||
| * @param zs A batch of measurement inputs. | ||
| * | ||
| * @see BFType<T> KalmanFilter<T>::batch_filter(array_type const & zs, array_type const & us) | ||
| * @see struct BFType<T>; | ||
| */ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It's clear.
… and update KalmanFilter.
0a079c5 to
ae53248
Compare
ThreeMonth03
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
One more point to address:
- Rename
StatesInfotoKalmanStateInfo.
@yungyuc Please review this pull request. Thanks.
| template <typename T> | ||
| struct KalmanStateInfo | ||
| { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Rename StatesInfo to KalmanStateInfo.
| } /* end namespace detail */ | ||
|
|
||
| /** | ||
| * @brief `KalmanStateInfo` includes prior and posterior states and their covariances, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix typo.
yungyuc
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The code looks good. Please update the commit log and the PR leading comment with a summary of what you did.
Problem
As metioned in #601 , we currently get state value by iterating api
predict()andupdate(). If there are many time series data-points, these api cannot deal with the data in one step.Solution
To use handy, the new api
batch_filter()is implemented in this pull request. There is a simple example intests/test_linalg.py, if we pass the argument of observations and contorls, the member functionkf.batch_filter(zs_sa, us_sa)would return(prior_state, prior_covariance, posterior_state, posterior_covariance).