@@ -12,9 +12,13 @@ Licensed under Apache2 license (see LICENSE file in main directory)
12
12
13
13
#include < ct/optcon/optcon.h>
14
14
#include < CustomController.h> // Using the custom controller from ct_core examples.
15
+ #include " exampleDir.h"
15
16
16
17
int main (int argc, char ** argv)
17
18
{
19
+ // file with kalman weights
20
+ std::string pathToWeights = ct::optcon::exampleDir + " /kalmanFilterWeights.info" ;
21
+
18
22
// a damped oscillator has two states, position and velocity
19
23
const size_t STATE_DIM = ct::core::SecondOrderSystem::STATE_DIM; // = 2
20
24
const size_t CONTROL_DIM = ct::core::SecondOrderSystem::CONTROL_DIM; // = 1
@@ -46,9 +50,14 @@ int main(int argc, char** argv)
46
50
ct::core::ControlVectorArray<CONTROL_DIM> controls;
47
51
ct::core::tpl::TimeArray<double > times;
48
52
53
+ ct::core::StateMatrix<STATE_DIM> process_var;
54
+ ct::core::loadMatrix (pathToWeights, " process_noise.process_var" , process_var);
55
+
56
+ ct::core::GaussianNoise position_process_noise (0.0 , process_var (0 , 0 ));
57
+ ct::core::GaussianNoise velocity_process_noise (0.0 , process_var (1 , 1 ));
58
+
49
59
// simulate 100 steps
50
60
double dt = 0.001 ;
51
- double t0 = 0.0 ;
52
61
size_t nSteps = 100 ;
53
62
states.push_back (x);
54
63
for (size_t i = 0 ; i < nSteps; i++)
@@ -59,6 +68,10 @@ int main(int argc, char** argv)
59
68
controls.push_back (u_temp);
60
69
61
70
integrator.integrate_n_steps (x, i * dt, 1 , dt);
71
+
72
+ position_process_noise.noisify (x (0 )); // Position noise.
73
+ velocity_process_noise.noisify (x (1 )); // Velocity noise.
74
+
62
75
states.push_back (x);
63
76
times.push_back (i * dt);
64
77
}
@@ -67,57 +80,105 @@ int main(int argc, char** argv)
67
80
ct::core::OutputStateMatrix<OUTPUT_DIM, STATE_DIM> C;
68
81
C.setIdentity ();
69
82
70
- // create Kalman Filter weighting matrices
71
- ct::core::StateMatrix<STATE_DIM, double > Q = ct::core::StateMatrix<STATE_DIM, double >::Identity ();
72
- ct::core::OutputMatrix<OUTPUT_DIM, double > R = 10 * ct::core::OutputMatrix<OUTPUT_DIM, double >::Identity ();
83
+ // load Kalman Filter weighting matrices from file
84
+ ct::core::StateMatrix<STATE_DIM> Q, dFdv;
85
+ ct::core::OutputMatrix<OUTPUT_DIM> R;
86
+ ct::core::loadMatrix (pathToWeights, " kalman_weights.Q" , Q);
87
+ ct::core::loadMatrix (pathToWeights, " kalman_weights.R" , R);
88
+ std::cout << " Loaded Kalman R as " << std::endl << R << std::endl;
89
+ std::cout << " Loaded Kalman Q as " << std::endl << Q << std::endl;
90
+
91
+ dFdv.setIdentity (); // todo tune me!
73
92
74
93
// create a sensitivity approximator to compute A and B matrices
75
94
std::shared_ptr<ct::core::SystemLinearizer<STATE_DIM, CONTROL_DIM>> linearizer (
76
95
new ct::core::SystemLinearizer<STATE_DIM, CONTROL_DIM>(oscillator));
77
96
ct::core::SensitivityApproximation<STATE_DIM, CONTROL_DIM> sensApprox (dt, linearizer);
78
97
79
98
// set up Extended Kalman Filter
80
- ct::optcon::ExtendedKalmanFilter<STATE_DIM> ekf (states[0 ]);
99
+ ct::optcon::ExtendedKalmanFilter<STATE_DIM> ekf (states[0 ], R );
81
100
82
101
// the observer is supplied with a dynamic model identical to the one used above for data generation
83
102
std::shared_ptr<ct::core::SecondOrderSystem> oscillator_observer_model (new ct::core::SecondOrderSystem (w_n));
84
-
103
+
85
104
// initialize the observer
86
105
ct::optcon::StateObserver<OUTPUT_DIM, STATE_DIM, CONTROL_DIM, ct::optcon::ExtendedKalmanFilter<STATE_DIM>>
87
- stateObserver (oscillator_observer_model, sensApprox, dt, C, ekf, Q, R);
106
+ stateObserver (oscillator_observer_model, sensApprox, C, R, ekf, Q, R, dFdv);
107
+
88
108
89
- ct::core::GaussianNoise position_measurement_noise ( 0 , 0.01 ) ;
90
- ct::core::GaussianNoise velocity_measurement_noise ( 0 , 0.1 );
109
+ ct::core::StateMatrix<STATE_DIM> meas_var ;
110
+ ct::core::loadMatrix (pathToWeights, " measurement_noise.measurement_var " , meas_var );
91
111
92
- ct::core::StateVectorArray<STATE_DIM> states_est;
93
- states_est.push_back (states[0 ]);
94
- ct::core::StateVector<STATE_DIM> xt;
112
+ ct::core::GaussianNoise position_measurement_noise (0.0 , meas_var (0 , 0 ));
113
+ ct::core::GaussianNoise velocity_measurement_noise (0.0 , meas_var (1 , 1 ));
114
+
115
+ ct::core::StateVectorArray<STATE_DIM> states_est (states.size ());
116
+ ct::core::StateVectorArray<STATE_DIM> states_meas (states.size ());
117
+ states_est[0 ] = states[0 ];
118
+ states_meas[0 ] = states[0 ];
95
119
96
120
// run the filter over the simulated data
97
121
for (size_t i = 1 ; i < states.size (); ++i)
98
122
{
99
123
// compute an observation
100
- xt = states[i];
101
- position_measurement_noise.noisify (xt[0 ]); // Position noise.
102
- velocity_measurement_noise.noisify (xt[1 ]); // Velocity noise.
103
- ct::core::OutputVector<OUTPUT_DIM> y = C * xt;
124
+ states_meas[i] = states[i];
125
+
126
+ // todo this is technically not correct, the noise enters not on the state but on the output!!!
127
+ position_measurement_noise.noisify (states_meas[i](0 )); // Position noise.
128
+ velocity_measurement_noise.noisify (states_meas[i](1 )); // Velocity noise.
129
+ ct::core::OutputVector<OUTPUT_DIM> y = C * states_meas[i];
104
130
105
131
// Kalman filter prediction step
106
- stateObserver.predict (controls[i], dt * i);
132
+ stateObserver.predict (controls[i], dt, dt * i);
107
133
108
134
// Kalman filter estimation step
109
- ct::core::StateVector<STATE_DIM> x_est = stateObserver.update (y);
135
+ ct::core::StateVector<STATE_DIM> x_est = stateObserver.update (y, dt, dt * i );
110
136
111
137
// and log for printing
112
- states_est.push_back (x_est);
138
+ states_est[i] = x_est;
139
+ }
140
+
141
+
142
+ // plot if plotting library built.
143
+ #ifdef PLOTTING_ENABLED
144
+
145
+ std::vector<double > time_plot, pos_est_plot, vel_est_plot, pos_plot, vel_plot, pos_meas_plot, vel_meas_plot;
146
+ for (size_t i = 0 ; i < times.size (); i++)
147
+ {
148
+ time_plot.push_back (times[i]);
149
+ pos_est_plot.push_back (states_est[i](0 ));
150
+ vel_est_plot.push_back (states_est[i](1 ));
151
+ pos_plot.push_back (states[i](0 ));
152
+ vel_plot.push_back (states[i](1 ));
153
+ pos_meas_plot.push_back (states_meas[i](0 ));
154
+ vel_meas_plot.push_back (states_meas[i](1 ));
113
155
}
114
156
115
- // print results
157
+ // plot position
158
+ ct::core::plot::subplot (2 , 1 , 1 );
159
+ ct::core::plot::labelPlot (" pos est" , time_plot, pos_est_plot);
160
+ ct::core::plot::labelPlot (" ground truth" , time_plot, pos_plot, " r--" );
161
+ ct::core::plot::labelPlot (" pos meas" , time_plot, pos_meas_plot, " k--" );
162
+ ct::core::plot::legend ();
163
+ ct::core::plot::ylabel (" pos [m]" );
164
+
165
+ // plot velocity
166
+ ct::core::plot::subplot (2 , 1 , 2 );
167
+ ct::core::plot::labelPlot (" vel est" , time_plot, vel_est_plot);
168
+ ct::core::plot::labelPlot (" ground truth" , time_plot, vel_plot, " r--" );
169
+ ct::core::plot::labelPlot (" vel meas" , time_plot, vel_meas_plot, " k--" );
170
+ ct::core::plot::ylabel (" vel [m/sec]" );
171
+ ct::core::plot::xlabel (" time [sec]" );
172
+ ct::core::plot::legend ();
173
+
174
+ ct::core::plot::show ();
175
+ #else // print results to command line
116
176
for (size_t i = 0 ; i < states_est.size (); ++i)
117
177
std::cout << " State\t\t State_est\n "
118
178
<< std::fixed << std::setprecision (6 ) << states[i][0 ] << " \t " << states_est[i][0 ] << std::endl
119
179
<< states[i][1 ] << " \t " << states_est[i][1 ] << std::endl
120
180
<< std::endl;
181
+ #endif
121
182
122
183
return 0 ;
123
184
}
0 commit comments