├── .gitignore ├── README.md ├── data ├── dataset1.mat └── dataset1_4x.mov ├── doc └── Papais_AER1513_Assignment_1_v2.pdf ├── lg_batch_rts_smoother.py └── out ├── est_and_tru_10000steps.png ├── est_and_tru_1000steps.png ├── est_and_tru_100steps.png ├── est_and_tru_10steps.png ├── est_and_tru_1steps.png ├── est_err_and_3std_10000steps.png ├── est_err_and_3std_1000steps.png ├── est_err_and_3std_100steps.png ├── est_err_and_3std_10steps.png ├── est_err_and_3std_1steps.png ├── est_err_hist_10000steps.png ├── est_err_hist_1000steps.png ├── est_err_hist_100steps.png ├── est_err_hist_10steps.png ├── est_err_hist_1steps.png ├── hist_model_noise.png ├── meas_and_true_vs_t.png ├── meas_vs_t.png ├── model_noise_vs_t.png └── qq_model_noise.png /.gitignore: -------------------------------------------------------------------------------- 1 | .idea/ 2 | venv/ 3 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Linear Gaussian Batch Estimation and RTS Smoother 2 | 3 | This project uses the batch linear-Gaussian algorithm to estimate the robot's position from odometry and laser measurements. 4 | 5 | ![](out/meas_vs_t.png) 6 | 7 | ## Measurement Data Analysis 8 | 9 | In order to perform linear-Gaussian estimation we must assume zero-mean normally distributed noise. Using the ground truth position information from the Vicon motion capture system, we can rearrange the motion and observation model to solve for the process and measurement noise. 10 | 11 | The mean of the measurement model and motion model noise was computed to be 1.005e-15 m and 4.505e-5 m respectively, which is quite small relative to the mean true position magnitude 1.780 m. Therefore, the assumption of zero-mean measurement model noise is reasonable over small time scales. However, since the motion model noise has an additive effect this will lead to 0.45 m of error over 1000 seconds if left uncorrected. 12 | 13 | ![](out/model_noise_vs_t.png) 14 | 15 | The assumption that the noise follows a Gaussian distribution can be qualitatively assessed by plotting the histogram of the noise against a best fit normal distribution. We can also assess the fit using a Quantile-Quantile Plot, which shows the fraction of points below the given value in the data against that of the best first normal distribution. Based on these plots, it is reasonable to claim that the measurement and modified process noise roughly follow a normal distribution. However, it is not a perfect fit and can be seen that the measurement model noise has a significant deviation from normal at the edges of the distribution where there is less data. 16 | 17 | ![](out/hist_model_noise.png) 18 | 19 | ![](out/qq_model_noise.png) 20 | 21 | The variances of the process model and observation model noise are computed to be 0.00002 m^2 and 0.00037 m^2 respectively. However, these values were later found to provide an inconsistent variance estimate in the smoother due to overconfidence in the process model. For a more consistent smoother uncertainty, the variance of the process model noise was inflated to 0.002 m^2. 22 | 23 | ## Batch Estimation 24 | 25 | Our goal is to find the most likely values for the state, meaning the state values that maximize the posterior probability density function given all our measurements of the state. We can solve the weighted least squares optimization problem using calculus to find minimum of the objective function as the derivative of the objective function with respect to the state variable. This leads to a linear system of equations in the form of Ax=b. 26 | 27 | ## Recursive Smoothing Method 28 | 29 | In order to solve the system of equations we require the inverse of a large matrix of size12709 x 12709. The matrix has a symmetric tridiagonal sparsity pattern. This pattern allows us to solve for the inverse more efficiently than using traditional algorithms, such as Gaussian elimination, which typically run in O(n^3) time. Given the tridiagonal sparsity pattern, we can invert the matrix using the tridiagonal matrix algorithm (also known as the forward block tridiagonal or Thomas algorithm), Rauch-Tung-Striebel (RTS) Smoother, or Cholesky Smoother. All three of these algorithms can be shown to be equivalent. The algorithms use a single forward pass followed by a single backward substitution pass and run in O(n) time. Once A inverse is found we can compute the most likely state estimate and confidence in our solution as x* = inv(A) b, P* = inv(A). 30 | 31 | The algorithm chosen is the RTS Smoother. The first predicted state estimate is assigned the first measurement and the first predicted state variance is assigned the measurement noise variance. For subsequent steps during the forward pass the predicted state variance and estimate is computed for the current step based on the previous state variance, estimate, and process model. If our iterator is divisible by the range measurement update interval, then we compute the Kalman gain, otherwise it is set to zero. When range measurements are available, we use the Kalman gain to solve for the corrected state variance and estimate using the optimal weighting of the predicted state and measurement. In the backwards pass we apply the backward substitution smoothing equation to solve for the optimal state estimate and variance. 32 | 33 | ## RTS Smoother Results 34 | 35 | A Python script was created to solve for the robots position estimate and uncertainty at all K time steps. Four cases were considered with different range measurement update step sizes of and 1, 10, 100, 1000. Over each the trajectories we see that at each of the range measurement updates our uncertainty in our estimate is the smallest, while at the mid-point between measurement updates our uncertainty is the largest. This is to be expected since the range measurement provides an exteroceptive update which can correct any drift accumulated by the interoceptive odemetry measurements and the process model. In all scenarios a filter estimation error is consistent with the filter posterior variance was achieved, meaning that the estimation error rarely exceeds the three sigma uncertianty. As we increase the time step of the range measurement update we see increases in the error estimate variance and the upper bound of our uncertainty over the trajectory, however the lower bound of of the uncertainty does not change. However, these results required the manual tuning of the process noise, since the initial value found based on analysis of the odometery data led to an overconfident estimate. Since the real world process and model noise don't perfectly follow a zero-mean normal distribution it is expected that tuning is required for consistent results. 36 | 37 | ![](out/est_err_and_3std_1steps.png) 38 | 39 | ![](out/est_err_and_3std_100steps.png) 40 | 41 | ![](out/est_err_and_3std_1000steps.png) 42 | -------------------------------------------------------------------------------- /data/dataset1.mat: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandropapais/batch_rts_smoother/b338956afb93e69eaec36058274dc2c058806bc3/data/dataset1.mat -------------------------------------------------------------------------------- /data/dataset1_4x.mov: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandropapais/batch_rts_smoother/b338956afb93e69eaec36058274dc2c058806bc3/data/dataset1_4x.mov -------------------------------------------------------------------------------- /doc/Papais_AER1513_Assignment_1_v2.pdf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandropapais/batch_rts_smoother/b338956afb93e69eaec36058274dc2c058806bc3/doc/Papais_AER1513_Assignment_1_v2.pdf -------------------------------------------------------------------------------- /lg_batch_rts_smoother.py: -------------------------------------------------------------------------------- 1 | from os.path import dirname, join 2 | import scipy.io as sio 3 | import matplotlib.pyplot as plt 4 | import numpy as np 5 | from scipy.stats import norm 6 | from statsmodels.graphics.gofplots import qqplot 7 | 8 | 9 | def read_data_mat(): 10 | # Load .mat file 11 | data_dir = join(dirname(__file__), 'data') 12 | mat_file_name = join(data_dir, 'dataset1.mat') 13 | mat_contents = sio.loadmat(mat_file_name) 14 | return mat_contents 15 | 16 | 17 | def compute_measurement_stats(mat_contents): 18 | # Unpack data and flatten to 1D 19 | range_meas = mat_contents['r'].flatten() 20 | pos_true = mat_contents['x_true'].flatten() 21 | pos_true = pos_true.flatten() 22 | t = mat_contents['t'].flatten() 23 | vel_meas = mat_contents['v'].flatten() 24 | pos_cyl = mat_contents['l'].flatten() 25 | # range_meas_var = mat_contents['r_var'].flatten() # unused 26 | # vel_meas_var = mat_contents['v_var'].flatten() # unused 27 | samples_count = pos_true.size 28 | t_step = t[1] 29 | 30 | # Measurement model and motion model noise 31 | pos_meas = pos_cyl - range_meas 32 | pos_meas_err = pos_meas - pos_true # measurement model noise 33 | pos_prop_err = np.zeros(samples_count) # motion model noise 34 | for i in range(1, samples_count): 35 | pos_prop_err[i] = pos_true[i] - pos_true[0] - t_step * np.sum(vel_meas[:i + 1]) - np.sum(pos_prop_err[:i]) 36 | 37 | # Fit data and compute statistics 38 | pos_true_mean = np.mean(pos_true) 39 | meas_err_mean, meas_err_std = norm.fit(pos_meas_err) 40 | prop_err_mean, prop_err_std = norm.fit(pos_prop_err) 41 | q_proc_noise_cov = prop_err_std ** 2 42 | r_meas_noise_cov = meas_err_std ** 2 43 | print('*** PREPROCESS ***\n' 44 | f'Position mean = {pos_true_mean:1.3f} m\n' 45 | f'Measurement noise: mean={meas_err_mean:1.3e} m, std={meas_err_std:1.3f} m,' 46 | f' 3-sigma={3 * meas_err_std:1.3f}m\n' 47 | f'Propagation noise: mean={prop_err_mean:1.3e} m, std={prop_err_std:1.3f} m, ' 48 | f'3-sigma={3 * prop_err_std:1.3f}m') 49 | 50 | # PLOT01: Measurements 51 | fig1, axs1 = plt.subplots(2, 1) 52 | axs1[0].plot(t, range_meas) 53 | axs1[0].set_ylabel('Laser Rangefinder (m)') 54 | axs1[0].set_title("Measurements") 55 | axs1[1].plot(t, vel_meas) 56 | axs1[1].set_xlabel('Time (s)') 57 | axs1[1].set_ylabel('Odometry (m/s)') 58 | fig1.savefig('out/meas_vs_t.png') 59 | 60 | # PLOT02: Model Noise 61 | fig2, axs2 = plt.subplots(2, 1) 62 | axs2[0].plot(t, pos_meas_err) 63 | axs2[0].set_ylabel('Measurement\nModel Noise (m)') 64 | axs2[0].set_title("Model Noise") 65 | axs2[1].plot(t, pos_prop_err) 66 | axs2[1].set_xlabel('Time (s)') 67 | axs2[1].set_ylabel('Motion\nModel Noise (m)') 68 | fig2.tight_layout(pad=0.2) 69 | fig2.savefig('out/model_noise_vs_t.png') 70 | 71 | # PLOT03: Model Noise Histogram 72 | fig3, axs3 = plt.subplots(2, 1) 73 | n_pts_plot = 100 74 | bins = axs3[0].hist(pos_meas_err, 20, density=1)[1] 75 | meas_err_fit_bins = np.linspace(bins[0], bins[-1], n_pts_plot) 76 | meas_err_fit = norm.pdf(meas_err_fit_bins, meas_err_mean, meas_err_std) 77 | axs3[0].plot(meas_err_fit_bins, meas_err_fit) 78 | axs3[0].set_xlabel('Measurement Model Noise (m)') 79 | axs3[0].text(0.95, 0.95, fr'$\mu={meas_err_mean:1.3e}, \sigma={meas_err_std:1.3f}$', 80 | horizontalalignment='right', verticalalignment='top', transform=axs3[0].transAxes) 81 | axs3[0].set_title("Model Noise Histogram") 82 | bins = axs3[1].hist(pos_prop_err, 20, density=1)[1] 83 | prop_err_fit_bins = np.linspace(bins[0], bins[-1], n_pts_plot) 84 | prop_err_fit = norm.pdf(prop_err_fit_bins, prop_err_mean, prop_err_std) 85 | axs3[1].plot(prop_err_fit_bins, prop_err_fit) 86 | axs3[1].set_xlabel('Motion Model Noise (m)') 87 | axs3[1].text(0.95, 0.95, fr'$\mu={prop_err_mean:1.3e}, \sigma={prop_err_std:1.3f}$', 88 | horizontalalignment='right', verticalalignment='top', transform=axs3[1].transAxes) 89 | fig3.tight_layout(pad=0.2) 90 | fig3.savefig('out/hist_model_noise.png') 91 | 92 | # PLOT04: Model Noise Q-Q 93 | fig4 = plt.figure() 94 | ax4 = fig4.add_subplot(2, 1, 1) 95 | qqplot(pos_meas_err, ax=ax4, line='s') 96 | ax4.set_ylabel('Measurement\nModel Noise') 97 | ax4.set_title("Model Noise Q-Q") 98 | ax4 = fig4.add_subplot(2, 1, 2) 99 | qqplot(pos_prop_err, ax=ax4, line='s') 100 | ax4.set_ylabel('Motion\nModel Noise') 101 | fig4.tight_layout(pad=0.2) 102 | fig4.savefig('out/qq_model_noise.png') 103 | 104 | return pos_meas, vel_meas, pos_true, t, samples_count, t_step, q_proc_noise_cov, r_meas_noise_cov 105 | 106 | 107 | def rts_smoother(pos_meas, vel_meas, pos_true, t, samples_count, t_step, q_proc_noise_cov, r_meas_noise_cov, 108 | flg_debug_prop_only, flg_debug_fwd_only, update_interval_indices, a_trans_mat, c_obs_mat): 109 | # RTS smoother initialization 110 | pos_est_ini = pos_meas[0] 111 | pos_var_ini = q_proc_noise_cov 112 | pos_est_pred_fwd = np.zeros(samples_count) 113 | pos_est_corr_fwd = np.zeros(samples_count) 114 | pos_est_corr = np.zeros(samples_count) 115 | pos_var_pred_fwd = np.zeros(samples_count) 116 | pos_var_corr_fwd = np.zeros(samples_count) 117 | pos_var_corr = np.zeros(samples_count) 118 | 119 | # RTS smoother forward pass 120 | for i in range(0, samples_count): 121 | if i == 0: 122 | pos_est_pred_fwd[0] = pos_est_ini 123 | pos_var_pred_fwd[0] = pos_var_ini 124 | else: 125 | pos_var_pred_fwd[i] = a_trans_mat * pos_var_corr_fwd[i - 1] * a_trans_mat + q_proc_noise_cov 126 | pos_est_pred_fwd[i] = a_trans_mat * pos_est_corr_fwd[i - 1] + t_step * vel_meas[i] 127 | if flg_debug_prop_only == 1: 128 | kalman_gain = 0 129 | elif (i % update_interval_indices) == 0: 130 | kalman_gain = pos_var_pred_fwd[i] * c_obs_mat / ( 131 | c_obs_mat * pos_var_pred_fwd[i] * c_obs_mat + r_meas_noise_cov) 132 | else: 133 | kalman_gain = 0 134 | pos_var_corr_fwd[i] = (1 - kalman_gain * c_obs_mat) * pos_var_pred_fwd[i] 135 | pos_est_corr_fwd[i] = pos_est_pred_fwd[i] + kalman_gain * (pos_meas[i] - c_obs_mat * pos_est_pred_fwd[i]) 136 | 137 | # RTS smoother backward pass 138 | if flg_debug_fwd_only == 1: 139 | pos_var_corr = pos_var_corr_fwd 140 | pos_est_corr = pos_est_corr_fwd 141 | else: 142 | pos_est_corr[-1] = pos_est_corr_fwd[-1] 143 | pos_var_corr[-1] = pos_var_corr_fwd[-1] 144 | for i in range(samples_count - 1, 0, -1): 145 | pos_est_corr[i - 1] = \ 146 | pos_est_corr_fwd[i - 1] + (pos_var_corr_fwd[i - 1] * a_trans_mat / pos_var_pred_fwd[i]) * \ 147 | (pos_est_corr[i] - pos_est_pred_fwd[i]) 148 | pos_var_corr[i - 1] = \ 149 | pos_var_corr_fwd[i - 1] + (pos_var_corr_fwd[i - 1] * a_trans_mat / pos_var_pred_fwd[i]) * \ 150 | (pos_var_corr[i] - pos_var_pred_fwd[i]) * (pos_var_corr_fwd[i - 1] * a_trans_mat / pos_var_pred_fwd[i]) 151 | 152 | # Post process results 153 | pos_est_err = pos_est_corr - pos_true 154 | pos_est_err_mean = np.mean(pos_est_err) 155 | pos_est_err_mod_avg = np.mean(np.abs(pos_est_err)) 156 | pos_est_rmse = np.sqrt(np.sum(pos_est_err ** 2) / samples_count) 157 | pos_est_err_std = np.std(pos_est_err) 158 | pos_3sigma = 3 * np.sqrt(pos_var_corr) 159 | print('*** POST-PROCESS ****\n' 160 | f'Process model variance = {q_proc_noise_cov:1.5f}\n' 161 | f'Measurement model variance = {r_meas_noise_cov:1.5f}\n' 162 | f'Average error magnitude = {pos_est_err_mod_avg:1.3f} m\n' 163 | f'Root mean square error = {pos_est_rmse:1.3f} m\n' 164 | f'3 sigma error = {3 * pos_est_err_std:1.3f} m') 165 | 166 | # PLOT05: Estimation Error and Uncertainty 167 | fig5, ax5 = plt.subplots() 168 | ax5.plot(t, pos_est_err, label=r'$\hat x_k - x_k$') 169 | ax5.plot(t, pos_3sigma, 'r--', label=r'$\pm3\hat\sigma_{x_k}$') 170 | ax5.plot(t, -pos_3sigma, 'r--') 171 | ax5.set_xlabel('Time (s)') 172 | ax5.set_ylabel('Position (m)') 173 | ax5.set_title("Estimation Error and Uncertainty") 174 | ax5.legend() 175 | fig5.savefig(f'out/est_err_and_3std_{update_interval_indices}steps.png') 176 | 177 | # PLOT06: Estimation Error Histogram 178 | fig6, ax6 = plt.subplots() 179 | n_pts_plot = 1000 180 | bins = ax6.hist(pos_est_err, 20, density=1)[1] 181 | pos_est_err_fit_bins = np.linspace(bins[0], bins[-1], n_pts_plot) 182 | pos_est_err_fit = norm.pdf(pos_est_err_fit_bins, 0, pos_est_err_std) 183 | ax6.plot(pos_est_err_fit_bins, pos_est_err_fit) 184 | ax6.set_xlabel('Position Estimate Error (m)') 185 | ax6.set_title("Estimation Error Histogram") 186 | plt.text(0.95, 0.95, fr'$\mu={pos_est_err_mean:1.3e}, \sigma={pos_est_err_std:1.3f}$', 187 | horizontalalignment='right', verticalalignment='top', transform=ax6.transAxes) 188 | fig6.savefig(f'out/est_err_hist_{update_interval_indices}steps.png') 189 | 190 | # PLOT07: Estimation and Uncertainty 191 | fig7, ax7 = plt.subplots() 192 | ax7.plot(t, pos_est_corr, label=r'$\hat{x_k}$') 193 | ax7.plot(t, pos_true, label=r'$x_k$') 194 | ax7.plot(t, pos_est_corr + pos_3sigma, 'r--', label=r'$\hat{x_k}\pm3\hat\sigma_{x_k}$') 195 | ax7.plot(t, pos_est_corr - pos_3sigma, 'r--') 196 | ax7.set_xlabel('Time (s)') 197 | ax7.set_ylabel('Position (m)') 198 | ax7.set_title("Estimation and Uncertainty") 199 | ax7.legend() 200 | fig7.savefig(f'out/est_and_tru_{update_interval_indices}steps.png') 201 | 202 | 203 | def main(): 204 | # Define flags 205 | flg_plot_show = 0 # 0, 1 206 | flg_debug_prop_only = 0 # 0, 1 207 | flg_debug_fwd_only = 0 # 0, 1 208 | # Define RTS smoother parameters 209 | update_interval_indices = 1000 # 1, 10, 100, 1000 210 | a_trans_mat = 1 211 | c_obs_mat = 1 212 | # Load data file 213 | mat_contents = read_data_mat() 214 | # Q1: Preprocess data for statistics 215 | pos_meas, vel_meas, pos_true, t, samples_count, t_step, q_proc_noise_cov, r_meas_noise_cov = \ 216 | compute_measurement_stats(mat_contents) 217 | # Q5: Call RTS smoother on data 218 | q_proc_noise_cov = 0.002 # instead of using prop_err_std ** 2, we inflate the process noise 219 | rts_smoother(pos_meas, vel_meas, pos_true, t, samples_count, t_step, q_proc_noise_cov, r_meas_noise_cov, 220 | flg_debug_prop_only, flg_debug_fwd_only, update_interval_indices, a_trans_mat, c_obs_mat) 221 | # Plotting 222 | if flg_plot_show == 1: 223 | plt.show() 224 | 225 | 226 | if __name__ == "__main__": 227 | main() 228 | -------------------------------------------------------------------------------- /out/est_and_tru_10000steps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandropapais/batch_rts_smoother/b338956afb93e69eaec36058274dc2c058806bc3/out/est_and_tru_10000steps.png -------------------------------------------------------------------------------- /out/est_and_tru_1000steps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandropapais/batch_rts_smoother/b338956afb93e69eaec36058274dc2c058806bc3/out/est_and_tru_1000steps.png -------------------------------------------------------------------------------- /out/est_and_tru_100steps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandropapais/batch_rts_smoother/b338956afb93e69eaec36058274dc2c058806bc3/out/est_and_tru_100steps.png -------------------------------------------------------------------------------- /out/est_and_tru_10steps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandropapais/batch_rts_smoother/b338956afb93e69eaec36058274dc2c058806bc3/out/est_and_tru_10steps.png -------------------------------------------------------------------------------- /out/est_and_tru_1steps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandropapais/batch_rts_smoother/b338956afb93e69eaec36058274dc2c058806bc3/out/est_and_tru_1steps.png -------------------------------------------------------------------------------- /out/est_err_and_3std_10000steps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandropapais/batch_rts_smoother/b338956afb93e69eaec36058274dc2c058806bc3/out/est_err_and_3std_10000steps.png -------------------------------------------------------------------------------- /out/est_err_and_3std_1000steps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandropapais/batch_rts_smoother/b338956afb93e69eaec36058274dc2c058806bc3/out/est_err_and_3std_1000steps.png -------------------------------------------------------------------------------- /out/est_err_and_3std_100steps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandropapais/batch_rts_smoother/b338956afb93e69eaec36058274dc2c058806bc3/out/est_err_and_3std_100steps.png -------------------------------------------------------------------------------- /out/est_err_and_3std_10steps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandropapais/batch_rts_smoother/b338956afb93e69eaec36058274dc2c058806bc3/out/est_err_and_3std_10steps.png -------------------------------------------------------------------------------- /out/est_err_and_3std_1steps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandropapais/batch_rts_smoother/b338956afb93e69eaec36058274dc2c058806bc3/out/est_err_and_3std_1steps.png -------------------------------------------------------------------------------- /out/est_err_hist_10000steps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandropapais/batch_rts_smoother/b338956afb93e69eaec36058274dc2c058806bc3/out/est_err_hist_10000steps.png -------------------------------------------------------------------------------- /out/est_err_hist_1000steps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandropapais/batch_rts_smoother/b338956afb93e69eaec36058274dc2c058806bc3/out/est_err_hist_1000steps.png -------------------------------------------------------------------------------- /out/est_err_hist_100steps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandropapais/batch_rts_smoother/b338956afb93e69eaec36058274dc2c058806bc3/out/est_err_hist_100steps.png -------------------------------------------------------------------------------- /out/est_err_hist_10steps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandropapais/batch_rts_smoother/b338956afb93e69eaec36058274dc2c058806bc3/out/est_err_hist_10steps.png -------------------------------------------------------------------------------- /out/est_err_hist_1steps.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandropapais/batch_rts_smoother/b338956afb93e69eaec36058274dc2c058806bc3/out/est_err_hist_1steps.png -------------------------------------------------------------------------------- /out/hist_model_noise.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandropapais/batch_rts_smoother/b338956afb93e69eaec36058274dc2c058806bc3/out/hist_model_noise.png -------------------------------------------------------------------------------- /out/meas_and_true_vs_t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandropapais/batch_rts_smoother/b338956afb93e69eaec36058274dc2c058806bc3/out/meas_and_true_vs_t.png -------------------------------------------------------------------------------- /out/meas_vs_t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandropapais/batch_rts_smoother/b338956afb93e69eaec36058274dc2c058806bc3/out/meas_vs_t.png -------------------------------------------------------------------------------- /out/model_noise_vs_t.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandropapais/batch_rts_smoother/b338956afb93e69eaec36058274dc2c058806bc3/out/model_noise_vs_t.png -------------------------------------------------------------------------------- /out/qq_model_noise.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/sandropapais/batch_rts_smoother/b338956afb93e69eaec36058274dc2c058806bc3/out/qq_model_noise.png --------------------------------------------------------------------------------