ekf.cpp
Go to the documentation of this file.
1 /*********************************************************************
2 * Copyright (c) 2017 Robert Bosch GmbH.
3 * All rights reserved.
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 * *********************************************************************/
17 
18 #include <cmath>
19 
22 
23 namespace steering
24 {
25 
26 EKF::EKF()
27 {
28  I_ = Matrix3d::Identity();
29 }
30 
31 void EKF::set_parameters(const Motion_Noise &motion_noise, const Measurement_Noise &measurement_noise,
32  const Controller &controller)
33 {
34  motion_noise_ = motion_noise;
35  measurement_noise_ = measurement_noise;
36  controller_ = controller;
37 }
38 
39 Matrix3d EKF::covariance_to_eigen(const double covariance[16]) const
40 {
41  Matrix3d covariance_eigen;
42  for (int i = 0, n = covariance_eigen.rows(); i < n; ++i)
43  {
44  for (int j = 0, m = covariance_eigen.cols(); j < m; ++j)
45  {
46  covariance_eigen(i, j) = covariance[(i << 2) + j]; // bitwise operation for: covariance[i * 4 + j]
47  }
48  }
49  return covariance_eigen;
50 }
51 
52 void EKF::eigen_to_covariance(const Matrix3d &covariance_eigen, double covariance[16]) const
53 {
54  for (int i = 0, n = covariance_eigen.rows(); i < n; ++i)
55  {
56  for (int j = 0, m = covariance_eigen.cols(); j < m; ++j)
57  {
58  covariance[(i << 2) + j] = covariance_eigen(i, j); // bitwise operation for: covariance[i * 4 + j]
59  }
60  }
61 }
62 
63 void EKF::get_motion_jacobi(const State &state, const Control &control, double integration_step, Matrix3d &F_x,
64  Matrix32d &F_u) const
65 {
66  double d(sgn(control.delta_s));
67 
68  if (fabs(control.sigma) > get_epsilon())
69  {
70  double sgn_sigma = sgn(control.sigma);
71  double abs_sigma = fabs(control.sigma);
72  double sqrt_sigma_inv = 1 / sqrt(abs_sigma);
73  double k1 = state.theta - 0.5 * d * state.kappa * state.kappa / control.sigma;
74  double k2 = SQRT_PI_INV * sqrt_sigma_inv * (abs_sigma * integration_step + sgn_sigma * state.kappa);
75  double k3 = SQRT_PI_INV * sqrt_sigma_inv * sgn_sigma * state.kappa;
76  double k4 = k1 + d * sgn_sigma * HALF_PI * k2 * k2;
77  double k5 = k1 + d * sgn_sigma * HALF_PI * k3 * k3;
78  double cos_k1 = cos(k1);
79  double sin_k1 = sin(k1);
80  double cos_k4 = cos(k4);
81  double sin_k4 = sin(k4);
82  double cos_k5 = cos(k5);
83  double sin_k5 = sin(k5);
84  double fresnel_s_k2;
85  double fresnel_c_k2;
86  double fresnel_s_k3;
87  double fresnel_c_k3;
88  fresnel(k2, fresnel_s_k2, fresnel_c_k2);
89  fresnel(k3, fresnel_s_k3, fresnel_c_k3);
90 
91  // df/dx
92  F_x(0, 0) = 1.0;
93  F_x(1, 1) = 1.0;
94 
95  F_x(0, 2) = SQRT_PI * sqrt_sigma_inv *
96  (-d * sin_k1 * (fresnel_c_k2 - fresnel_c_k3) - sgn_sigma * cos_k1 * (fresnel_s_k2 - fresnel_s_k3));
97  F_x(1, 2) = SQRT_PI * sqrt_sigma_inv *
98  (d * cos_k1 * (fresnel_c_k2 - fresnel_c_k3) - sgn_sigma * sin_k1 * (fresnel_s_k2 - fresnel_s_k3));
99  F_x(2, 2) = 1.0;
100 
101  // df/du
102  F_u(0, 0) = cos_k4;
103  F_u(1, 0) = sin_k4;
104  F_u(2, 0) = state.kappa + control.sigma * integration_step;
105 
106  F_u(0, 1) = SQRT_PI * sqrt_sigma_inv * state.kappa *
107  (sgn_sigma * sin_k1 * (fresnel_c_k2 - fresnel_c_k3) + d * cos_k1 * (fresnel_s_k2 - fresnel_s_k3)) /
108  abs_sigma +
109  d * (cos_k4 - cos_k5) / control.sigma;
110  F_u(1, 1) = SQRT_PI * sqrt_sigma_inv * state.kappa *
111  (-sgn_sigma * cos_k1 * (fresnel_c_k2 - fresnel_c_k3) + d * sin_k1 * (fresnel_s_k2 - fresnel_s_k3)) /
112  abs_sigma +
113  d * (sin_k4 - sin_k5) / control.sigma;
114  F_u(2, 1) = d * integration_step;
115  }
116  else
117  {
118  if (fabs(state.kappa) > get_epsilon())
119  {
120  double sin_th = sin(state.theta);
121  double cos_th = cos(state.theta);
122  double k9 = state.theta + d * integration_step * state.kappa;
123  double cos_k9 = cos(k9);
124  double sin_k9 = sin(k9);
125 
126  // df/dx
127  F_x(0, 0) = 1.0;
128  F_x(1, 1) = 1.0;
129 
130  F_x(0, 2) = (-cos_th + cos_k9) / state.kappa;
131  F_x(1, 2) = (-sin_th + sin_k9) / state.kappa;
132  F_x(2, 2) = 1.0;
133 
134  // df/du
135  F_u(0, 0) = cos_k9;
136  F_u(1, 0) = sin_k9;
137  F_u(2, 0) = state.kappa;
138 
139  F_u(0, 1) = (sin_th - sin_k9) / (state.kappa * state.kappa) + d * integration_step * cos_k9 / state.kappa;
140  F_u(1, 1) = (-cos_th + cos_k9) / (state.kappa * state.kappa) + d * integration_step * sin_k9 / state.kappa;
141  F_u(2, 1) = d * integration_step;
142  }
143  else
144  {
145  double cos_th = cos(state.theta);
146  double sin_th = sin(state.theta);
147 
148  // df/dx
149  F_x(0, 0) = 1.0;
150  F_x(1, 1) = 1.0;
151 
152  F_x(0, 2) = -d * integration_step * sin_th;
153  F_x(1, 2) = d * integration_step * cos_th;
154  F_x(2, 2) = 1.0;
155 
156  // df/du
157  F_u(0, 0) = cos_th;
158  F_u(1, 0) = sin_th;
159  F_u(2, 0) = state.kappa;
160 
161  F_u(2, 1) = d * integration_step;
162  }
163  }
164 }
165 
167 {
168  return I_;
169 }
170 
171 Matrix2d EKF::get_motion_covariance(const State &state, const Control &control, double integration_step) const
172 {
173  Matrix2d Q(Matrix2d::Zero());
174  Q(0, 0) =
175  motion_noise_.alpha1 * integration_step * integration_step + motion_noise_.alpha2 * state.kappa * state.kappa;
176  Q(1, 1) =
177  motion_noise_.alpha3 * integration_step * integration_step + motion_noise_.alpha4 * state.kappa * state.kappa;
178  return Q;
179 }
180 
182 {
183  Matrix3d R(Matrix3d::Zero());
187  return R;
188 }
189 
190 Matrix23d EKF::get_controller_gain(const Control &control) const
191 {
192  Matrix23d K(Matrix23d::Zero());
193  K(0, 0) = controller_.k1;
194  K(1, 1) = controller_.k2;
195  K(1, 2) = sgn(control.delta_s) * controller_.k3;
196  return K;
197 }
198 
199 Matrix3d EKF::get_rotation_matrix(double angle) const
200 {
201  Matrix3d R(Matrix3d::Zero());
202  double cos_angle = cos(angle);
203  double sin_angle = sin(angle);
204  R(0, 0) = cos_angle;
205  R(1, 0) = -sin_angle;
206  R(0, 1) = sin_angle;
207  R(1, 1) = cos_angle;
208  R(2, 2) = 1.0;
209  return R;
210 }
211 
212 void EKF::predict(const State_With_Covariance &state, const Control &control, double integration_step,
213  State_With_Covariance &state_pred) const
214 {
215  Matrix3d Sigma = covariance_to_eigen(state.Sigma);
216  Matrix3d Lambda = covariance_to_eigen(state.Lambda);
217 
218  // Sigma_pred
219  Matrix3d F_x(Matrix3d::Zero());
220  Matrix32d F_u(Matrix32d::Zero());
221  get_motion_jacobi(state.state, control, integration_step, F_x, F_u);
222  Matrix2d Q = get_motion_covariance(state.state, control, integration_step);
223  Matrix3d Sigma_pred = F_x * Sigma * F_x.transpose() + F_u * Q * F_u.transpose();
224 
225  // Lambda_pred
226  Matrix23d K = get_controller_gain(control);
228  Matrix3d F_K = F_x - F_u * K * R_1I;
229  Matrix3d Lambda_pred = F_K * Lambda * F_K.transpose();
230 
231  eigen_to_covariance(Sigma_pred, state_pred.Sigma);
232  eigen_to_covariance(Lambda_pred, state_pred.Lambda);
233  eigen_to_covariance(Sigma_pred + Lambda_pred, state_pred.covariance);
234 }
235 
236 void EKF::update(const State_With_Covariance &state_pred, State_With_Covariance &state_corr) const
237 {
238  Matrix3d Sigma_pred = covariance_to_eigen(state_pred.Sigma);
239  Matrix3d Lambda_pred = covariance_to_eigen(state_pred.Lambda);
240 
241  // Kalman gain L
244  Matrix3d Sigma_xz = Sigma_pred * H_x.transpose();
245  Matrix3d Sigma_z = H_x * Sigma_xz + R;
246  Matrix3d L = Sigma_xz * Sigma_z.inverse();
247 
248  // Sigma_corr (Joseph's form)
249  Matrix3d I_LH_x = I_ - L * H_x;
250  Matrix3d Sigma_corr = I_LH_x * Sigma_pred * I_LH_x.transpose() + L * R * L.transpose();
251 
252  // Lambda_corr
253  Matrix3d Lambda_corr = Lambda_pred + L * Sigma_xz.transpose();
254 
255  eigen_to_covariance(Sigma_corr, state_corr.Sigma);
256  eigen_to_covariance(Lambda_corr, state_corr.Lambda);
257  eigen_to_covariance(Sigma_corr + Lambda_corr, state_corr.covariance);
258 }
259 
260 } // namespace steering
steering::EKF::get_motion_jacobi
void get_motion_jacobi(const State &state, const Control &control, double integration_step, Matrix3d &F_x, Matrix32d &F_u) const
Computes the Jacobians of the motion equations with respect to the state and control.
Definition: ekf.cpp:78
SQRT_PI
#define SQRT_PI
Definition: utilities.hpp:34
steering::State_With_Covariance::state
State state
Expected state of the robot.
Definition: steering_functions.hpp:66
steering::State_With_Covariance::covariance
double covariance[16]
Covariance of the state given by Sigma + Lambda: (x_x x_y x_theta x_kappa y_x y_y y_theta y_kappa the...
Definition: steering_functions.hpp:78
steering::EKF::measurement_noise_
Measurement_Noise measurement_noise_
Measurement noise.
Definition: ekf.hpp:99
steering::EKF::EKF
EKF()
Definition: ekf.cpp:41
steering::Matrix32d
Eigen::Matrix< double, 3, 2 > Matrix32d
Definition: ekf.hpp:45
angle
TFSIMD_FORCE_INLINE tfScalar angle(const Quaternion &q1, const Quaternion &q2)
steering::EKF::covariance_to_eigen
Matrix3d covariance_to_eigen(const double covariance[16]) const
Converts a covariance given by a double array to an Eigen matrix.
Definition: ekf.cpp:54
steering::EKF::get_observation_jacobi
Matrix3d get_observation_jacobi() const
Computes the Jacobian of the observation equations with respect to the state.
Definition: ekf.cpp:181
steering::Controller::k1
double k1
Weight on longitudinal error.
Definition: steering_functions.hpp:124
steering::Measurement_Noise::std_theta
double std_theta
Standard deviation of localization in theta.
Definition: steering_functions.hpp:117
steering::Controller::k2
double k2
Weight on lateral error.
Definition: steering_functions.hpp:127
steering::State::theta
double theta
Orientation of the robot.
Definition: steering_functions.hpp:70
steering::State_With_Covariance::Sigma
double Sigma[16]
Covariance of the state estimation due to motion and measurement noise.
Definition: steering_functions.hpp:69
Matrix3d
Eigen::Matrix< double, 3, 3 > Matrix3d
Definition: jacobian_test.cpp:42
steering::Motion_Noise::alpha2
double alpha2
Definition: steering_functions.hpp:100
Matrix32d
Eigen::Matrix< double, 3, 2 > Matrix32d
Definition: jacobian_test.cpp:43
steering::EKF::I_
Matrix3d I_
Identity matrix.
Definition: ekf.hpp:105
steering::EKF::get_motion_covariance
Matrix2d get_motion_covariance(const State &state, const Control &control, double integration_step) const
Returns the motion covariance in control space.
Definition: ekf.cpp:186
ekf.hpp
steering::Matrix3d
Eigen::Matrix< double, 3, 3 > Matrix3d
Definition: ekf.hpp:44
steering::Control
Description of a path segment with its corresponding control inputs.
Definition: steering_functions.hpp:82
steering::EKF::update
void update(const State_With_Covariance &state_pred, State_With_Covariance &state_corr) const
Predicts the covariances.
Definition: ekf.cpp:251
steering::EKF::set_parameters
void set_parameters(const Motion_Noise &motion_noise, const Measurement_Noise &measurement_noise, const Controller &_controller)
Sets the parameters required by the EKF.
Definition: ekf.cpp:46
steering::fresnel
void fresnel(double s, double &S_f, double &C_f)
Fresnel integrals: S_f = int_0_s(sin(pi/2 u*u)du), C_f = int_0_s(cos(pi/2 u*u)du) approximated with C...
Definition: utilities.cpp:161
steering::Motion_Noise::alpha3
double alpha3
Variance in lateral direction: alpha3*delta_s*delta_s + alpha4*kappa*kappa.
Definition: steering_functions.hpp:103
steering::EKF::motion_noise_
Motion_Noise motion_noise_
Motion noise.
Definition: ekf.hpp:96
steering::EKF::get_controller_gain
Matrix23d get_controller_gain(const Control &control) const
Returns the gain of the controller.
Definition: ekf.cpp:205
steering::EKF::controller_
Controller controller_
Feedback controller.
Definition: ekf.hpp:102
steering::EKF::predict
void predict(const State_With_Covariance &state, const Control &control, double integration_step, State_With_Covariance &state_pred) const
Predicts the covariances based on the paper: Rapidly-exploring random belief trees for motion plannin...
Definition: ekf.cpp:227
steering::EKF::get_rotation_matrix
Matrix3d get_rotation_matrix(double angle) const
Returns the rotation matrix from a global frame to a local frame.
Definition: ekf.cpp:214
steering::Control::delta_s
double delta_s
Signed arc length of a segment.
Definition: steering_functions.hpp:85
steering::State_With_Covariance::Lambda
double Lambda[16]
Covariance of the state estimate due to the absence of measurements.
Definition: steering_functions.hpp:72
steering::EKF::eigen_to_covariance
void eigen_to_covariance(const Matrix3d &covariance_eigen, double covariance[16]) const
Converts a covariance given by an Eigen matrix to a double array.
Definition: ekf.cpp:67
steering::Controller::k3
double k3
Weight on heading error.
Definition: steering_functions.hpp:130
steering::get_epsilon
double get_epsilon()
Return value of epsilon.
Definition: utilities.cpp:57
plot_states.d
d
Definition: plot_states.py:107
steering::Motion_Noise::alpha4
double alpha4
Definition: steering_functions.hpp:104
steering::Measurement_Noise::std_y
double std_y
Standard deviation of localization in y.
Definition: steering_functions.hpp:114
steering::State_With_Covariance
Description of a kinematic car's state with covariance.
Definition: steering_functions.hpp:63
steering
Definition: dubins_state_space.hpp:70
steering::sgn
double sgn(double x)
Return sign of a number.
Definition: utilities.cpp:62
steering::Matrix2d
Eigen::Matrix< double, 2, 2 > Matrix2d
Definition: ekf.hpp:43
steering::EKF::get_observation_covariance
Matrix3d get_observation_covariance() const
Returns the observation covariance.
Definition: ekf.cpp:196
steering::Measurement_Noise::std_x
double std_x
Standard deviation of localization in x.
Definition: steering_functions.hpp:111
SQRT_PI_INV
#define SQRT_PI_INV
Definition: utilities.hpp:35
HALF_PI
#define HALF_PI
Definition: utilities.hpp:32
steering::Motion_Noise::alpha1
double alpha1
Variance in longitudinal direction: alpha1*delta_s*delta_s + alpha2*kappa*kappa
Definition: steering_functions.hpp:99
utilities.hpp
Matrix2d
Eigen::Matrix< double, 2, 2 > Matrix2d
Definition: jacobian_test.cpp:41
steering::Matrix23d
Eigen::Matrix< double, 2, 3 > Matrix23d
Definition: ekf.hpp:46


steering_functions
Author(s): Holger Banzhaf
autogenerated on Mon Dec 11 2023 03:27:43