Skip to content

Commit 3544fb4

Browse files
committed
refactor our rts_backward
1 parent 3db239f commit 3544fb4

1 file changed

Lines changed: 66 additions & 64 deletions

File tree

src/smsfusion/_smoothing.py

Lines changed: 66 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -102,17 +102,19 @@ def _smooth(self):
102102
self._x = np.empty((0, 16), dtype="float64")
103103
self._P = np.empty((0, *self._ains.P.shape), dtype="float64")
104104
elif n_samples == 1:
105-
self._x = np.asarray_chkfinite(self._x_buf)
106-
self._P = np.asarray_chkfinite(self._P_buf)
105+
self._x = np.asarray(self._x_buf)
106+
self._P = np.asarray(self._P_buf)
107107
elif n_samples != len(self._x):
108-
self._x, self._P = self._backward_sweep(
108+
x, P = _rts_backward_sweep(
109109
self._x_buf,
110110
self._dx_buf,
111111
self._P_buf,
112112
self._P_prior_buf,
113113
self._phi_buf,
114114
cov_smoothing=self._cov_smoothing,
115115
)
116+
self._x = np.asarray(x)
117+
self._P = np.asarray(P)
116118

117119
@property
118120
def x(self) -> NDArray:
@@ -239,68 +241,68 @@ def euler(self, degrees: bool = False) -> NDArray:
239241
theta = np.array([_euler_from_quaternion(q_i) for q_i in q])
240242
return np.degrees(theta) if degrees else theta
241243

242-
@staticmethod
243-
def _backward_sweep(
244-
x: NDArray,
245-
dx: NDArray,
246-
P: NDArray,
247-
P_prior: NDArray,
248-
phi: NDArray,
249-
cov_smoothing: bool,
250-
) -> tuple[NDArray, NDArray]:
251-
"""
252-
Perform a backward sweep with the RTS algorithm [1].
253244

254-
Parameters
255-
----------
256-
x : NDArray, shape (n_samples, 16)
257-
The state vector.
258-
dx : NDArray, shape (n_samples, 15) or (n_samples, 12)
259-
The error state vector.
260-
P : NDArray, shape (n_samples, 15, 15) or (n_samples, 12, 12)
261-
The covariance matrix.
262-
P_prior : NDArray, shape (n_samples, 15, 15) or (n_samples, 12, 12)
263-
The a priori covariance matrix.
264-
phi : NDArray, shape (n_samples, 15, 15) or (n_samples, 12, 12)
265-
The state transition matrix.
266-
cov_smoothing : bool
267-
Whether to include the error covariance matrix in the smoothing process.
245+
def _rts_backward_sweep(
246+
x: list[NDArray],
247+
dx: list[NDArray],
248+
P: list[NDArray],
249+
P_prior: list[NDArray],
250+
phi: list[NDArray],
251+
cov_smoothing: bool,
252+
) -> tuple[list[NDArray], list[NDArray]]:
253+
"""
254+
Perform a backward sweep with the RTS algorithm [1].
268255
269-
Returns
270-
-------
271-
x_smth : NDArray, shape (n_samples, 15) or (n_samples, 12)
272-
The smoothed state vector.
273-
P_smth : NDArray, shape (n_samples, 15, 15) or (n_samples, 12, 12)
274-
The smoothed covariance matrix if include_cov is True, otherwise None.
256+
Parameters
257+
----------
258+
x : NDArray, shape (n_samples, 16)
259+
The state vector.
260+
dx : NDArray, shape (n_samples, 15) or (n_samples, 12)
261+
The error state vector.
262+
P : NDArray, shape (n_samples, 15, 15) or (n_samples, 12, 12)
263+
The covariance matrix.
264+
P_prior : NDArray, shape (n_samples, 15, 15) or (n_samples, 12, 12)
265+
The a priori covariance matrix.
266+
phi : NDArray, shape (n_samples, 15, 15) or (n_samples, 12, 12)
267+
The state transition matrix.
268+
cov_smoothing : bool
269+
Whether to include the error covariance matrix in the smoothing process.
270+
271+
Returns
272+
-------
273+
x_smth : NDArray, shape (n_samples, 15) or (n_samples, 12)
274+
The smoothed state vector.
275+
P_smth : NDArray, shape (n_samples, 15, 15) or (n_samples, 12, 12)
276+
The smoothed covariance matrix if include_cov is True, otherwise None.
275277
276-
References
277-
----------
278-
[1] R. G. Brown and P. Y. C. Hwang, "Random signals and applied Kalman
279-
filtering with MATLAB exercises", 4th ed. Wiley, pp. 208-212, 2012.
280-
"""
278+
References
279+
----------
280+
[1] R. G. Brown and P. Y. C. Hwang, "Random signals and applied Kalman
281+
filtering with MATLAB exercises", 4th ed. Wiley, pp. 208-212, 2012.
282+
"""
281283

282-
x = np.asarray_chkfinite(x).copy()
283-
dx = np.asarray_chkfinite(dx).copy()
284-
P = np.asarray_chkfinite(P).copy()
285-
286-
# Backward sweep
287-
for k in range(len(x) - 2, -1, -1):
288-
# Smoothed error-state estimate and corresponding covariance
289-
A = P[k] @ phi[k].T @ np.linalg.inv(P_prior[k + 1])
290-
ddx = A @ dx[k + 1]
291-
dx[k, :] += ddx
292-
if cov_smoothing:
293-
P[k, :, :] += A @ (P[k + 1] - P_prior[k + 1]) @ A.T
294-
295-
# Reset
296-
dda = ddx[6:9]
297-
ddq = (1.0 / np.sqrt(4.0 + dda.T @ dda)) * np.r_[2.0, dda]
298-
x[k, :3] = x[k, :3] + ddx[:3]
299-
x[k, 3:6] = x[k, 3:6] + ddx[3:6]
300-
x[k, 6:10] = _quaternion_product(x[k, 6:10], ddq)
301-
x[k, 6:10] = _normalize(x[k, 6:10])
302-
x[k, -3:] = x[k, -3:] + ddx[-3:]
303-
if dx.shape[1] == 15:
304-
x[k, 10:13] = x[k, 10:13] + ddx[9:12]
305-
306-
return x, P
284+
x = x.copy() # np.asarray_chkfinite(x).copy()
285+
dx = dx.copy() # np.asarray_chkfinite(dx).copy()
286+
P = P.copy() # np.asarray_chkfinite(P).copy()
287+
288+
# Backward sweep
289+
for k in range(len(x) - 2, -1, -1):
290+
# Smoothed error-state estimate and corresponding covariance
291+
A = P[k] @ phi[k].T @ np.linalg.inv(P_prior[k + 1])
292+
ddx = A @ dx[k + 1]
293+
dx[k] += ddx
294+
if cov_smoothing:
295+
P[k] += A @ (P[k + 1] - P_prior[k + 1]) @ A.T
296+
297+
# Reset
298+
dda = ddx[6:9]
299+
ddq = (1.0 / np.sqrt(4.0 + dda.T @ dda)) * np.r_[2.0, dda]
300+
x[k][:3] = x[k][:3] + ddx[:3]
301+
x[k][3:6] = x[k][3:6] + ddx[3:6]
302+
x[k][6:10] = _quaternion_product(x[k][6:10], ddq)
303+
x[k][6:10] = _normalize(x[k][6:10])
304+
x[k][-3:] = x[k][-3:] + ddx[-3:]
305+
if dx[k].size == 15:
306+
x[k][10:13] = x[k][10:13] + ddx[9:12]
307+
308+
return x, P

0 commit comments

Comments
 (0)