Skip to content

Conversation

@ThreeMonth03
Copy link
Collaborator

Problem

As metioned in #601 , we currently get state value by iterating api predict() and update(). 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 in tests/test_linalg.py, if we pass the argument of observations and contorls, the member function kf.batch_filter(zs_sa, us_sa) would return (prior_state, prior_covariance, posterior_state, posterior_covariance).

def test_batchfilter_with_control(self):
        # ...
        kf = mm.KalmanFilterFp64(
            x=x_sa, f=f_sa, b=b_sa, h=h_sa,
            process_noise=sigma_w,
            measurement_noise=1.0,
        )
        bps = kf.batch_filter(zs_sa, us_sa)
        xs_pred, ps_pred, xs_upd, ps_upd = bps

Copy link
Collaborator Author

@ThreeMonth03 ThreeMonth03 left a 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.

Comment on lines 551 to 668
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);
}
Copy link
Collaborator Author

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.

Copy link
Member

@yungyuc yungyuc left a 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_type needs a helper class.

We are about to have a hammer. Let's find a nail.

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>;
Copy link
Member

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.

@yungyuc yungyuc requested a review from j8xixo12 January 20, 2026 14:53
@yungyuc yungyuc added the array Multi-dimensional array implementation label Jan 20, 2026
Comment on lines 505 to 512
if (u.shape(0) > 0)
{
predict(u);
}
else
{
predict();
}
Copy link
Collaborator

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 ?

Copy link
Collaborator Author

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.

Copy link
Collaborator Author

@ThreeMonth03 ThreeMonth03 left a 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_type needs 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.

Comment on lines 43 to 84
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 */
Copy link
Collaborator Author

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.

Comment on lines 550 to 640
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;
}
Copy link
Collaborator Author

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.

Copy link
Member

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.

Copy link
Collaborator Author

@ThreeMonth03 ThreeMonth03 Jan 22, 2026

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.

Comment on lines 97 to 147
.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"));
Copy link
Collaborator Author

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.

Copy link
Member

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.

@ThreeMonth03 ThreeMonth03 requested a review from yungyuc January 21, 2026 10:50
Copy link
Member

@yungyuc yungyuc left a 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 BatchFilterHelper and give the class a better name.
  • Evaluate if BatchFilterHelper should have accessors removed and changed to be struct.
  • ALERT: Are you sure you want to force data copy for calling predict?

} /* end namespace detail */

template <typename T>
class BatchFilterHelper
Copy link
Member

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.

}

private:
SimpleArray<T> m_prior_xs;
Copy link
Member

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.


// 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));
Copy link
Member

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?

Comment on lines 550 to 640
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;
}
Copy link
Member

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.

}

template <typename T>
BatchFilterHelper<T> KalmanFilter<T>::batch_filter(array_type const & zs, std::unique_ptr<array_type> const & us_ptr)
Copy link
Member

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.


private:

void predict(std::unique_ptr<array_type> const & u_ptr)
Copy link
Member

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.

void predict_state();
void predict_state(array_type const & u);
// void predict_state();
void predict_state(std::unique_ptr<array_type> const & u_ptr);
Copy link
Member

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.

@ThreeMonth03 ThreeMonth03 force-pushed the batch_filter branch 3 times, most recently from c948592 to 9d141e7 Compare January 24, 2026 09:20
@ThreeMonth03 ThreeMonth03 requested a review from yungyuc January 24, 2026 10:59
Copy link
Collaborator Author

@ThreeMonth03 ThreeMonth03 left a 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 BatchFilterHelper and give the class a better name.
  • Evaluate if BatchFilterHelper should have accessors removed and changed to be struct.
  • The use of unique_ptr is not necessary and should be removed from the PR.

@yungyuc Please review this pull request again. Thanks.

Comment on lines 54 to 76
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 */
Copy link
Collaborator Author

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.

Comment on lines 243 to 258
/**
* @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>;
*/
Copy link
Collaborator Author

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.

Copy link
Member

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.

Copy link
Collaborator Author

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.

Copy link
Member

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.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's clear.

Copy link
Member

@yungyuc yungyuc left a 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 BFType in 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_tuple to 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.

} /* end namespace detail */

/**
* @brief Return type for `KalmanFilter<T>::batch_filter(...)`.
Copy link
Member

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.

posterior_state = SimpleArray<T>(xs_shape);
posterior_state_covariance = SimpleArray<T>(ps_shape);
}
tuple_type to_tuple() const
Copy link
Member

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).

Comment on lines 243 to 258
/**
* @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>;
*/
Copy link
Member

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.

Comment on lines 97 to 147
.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"));
Copy link
Member

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.

@ThreeMonth03 ThreeMonth03 force-pushed the batch_filter branch 2 times, most recently from 89ef61c to 0a079c5 Compare February 2, 2026 11:30
Copy link
Collaborator Author

@ThreeMonth03 ThreeMonth03 left a 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 BFType in 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_tuple to 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.

Comment on lines 43 to 77
/**
* @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 */
Copy link
Collaborator Author

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.

Copy link
Member

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).

Comment on lines 243 to 258
/**
* @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>;
*/
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done.

Comment on lines 39 to 74
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 */

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wrap StatesInfo to python.

@ThreeMonth03 ThreeMonth03 requested a review from yungyuc February 2, 2026 12:17
Copy link
Member

@yungyuc yungyuc left a 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 StatesInfo to KalmanStateInfo.

} /* end namespace detail */

/**
* @brief `StatsInfo` includes prior and posterior states and their covariances,
Copy link
Member

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").

Comment on lines 43 to 77
/**
* @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 */
Copy link
Member

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).

Comment on lines 243 to 258
/**
* @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>;
*/
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's clear.

Copy link
Collaborator Author

@ThreeMonth03 ThreeMonth03 left a 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 StatesInfo to KalmanStateInfo.

@yungyuc Please review this pull request. Thanks.

Comment on lines +58 to +60
template <typename T>
struct KalmanStateInfo
{
Copy link
Collaborator Author

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,
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fix typo.

@ThreeMonth03 ThreeMonth03 requested a review from yungyuc February 2, 2026 15:35
@yungyuc yungyuc changed the title Feat: Implement batch filter Implement batch filter Feb 3, 2026
@yungyuc yungyuc changed the title Implement batch filter Implement batch API for Kalman filter Feb 3, 2026
Copy link
Member

@yungyuc yungyuc left a 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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

array Multi-dimensional array implementation

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants