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 
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 
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 
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);
227  Matrix3d R_1I = get_rotation_matrix(state.state.theta);
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
double k1
Weight on longitudinal error.
double get_epsilon()
Return value of epsilon.
Definition: utilities.cpp:34
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:31
double sgn(double x)
Return sign of a number.
Definition: utilities.cpp:39
double std_y
Standard deviation of localization in y.
Eigen::Matrix< double, 2, 3 > Matrix23d
Definition: ekf.hpp:31
double delta_s
Signed arc length of a segment.
double Lambda[16]
Covariance of the state estimate due to the absence of measurements.
Matrix3d get_observation_jacobi() const
Computes the Jacobian of the observation equations with respect to the state.
Definition: ekf.cpp:166
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:52
Matrix2d get_motion_covariance(const State &state, const Control &control, double integration_step) const
Returns the motion covariance in control space.
Definition: ekf.cpp:171
Controller controller_
Feedback controller.
Definition: ekf.hpp:87
Eigen::Matrix< double, 3, 3 > Matrix3d
Definition: ekf.hpp:29
#define SQRT_PI_INV
Definition: utilities.hpp:35
double std_x
Standard deviation of localization in x.
Eigen::Matrix< double, 3, 2 > Matrix32d
Definition: ekf.hpp:30
double k2
Weight on lateral error.
Matrix3d covariance_to_eigen(const double covariance[16]) const
Converts a covariance given by a double array to an Eigen matrix.
Definition: ekf.cpp:39
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:138
#define SQRT_PI
Definition: utilities.hpp:34
Motion_Noise motion_noise_
Motion noise.
Definition: ekf.hpp:81
Parameters of the motion noise model according to the book: Probabilistic Robotics, S. Thrun and others, MIT Press, 2006, p. 127-128 and p.204-206.
Description of a path segment with its corresponding control inputs.
void update(const State_With_Covariance &state_pred, State_With_Covariance &state_corr) const
Predicts the covariances.
Definition: ekf.cpp:236
State state
Expected state of the robot.
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...
Description of a kinematic car&#39;s state with covariance.
Parameters of the measurement noise.
double k3
Weight on heading error.
Parameters of the feedback controller.
INLINE Rall1d< T, V, S > sqrt(const Rall1d< T, V, S > &arg)
#define HALF_PI
Definition: utilities.hpp:32
Matrix3d get_observation_covariance() const
Returns the observation covariance.
Definition: ekf.cpp:181
double alpha1
Variance in longitudinal direction: alpha1*delta_s*delta_s + alpha2*kappa*kappa.
Description of a kinematic car&#39;s state.
Eigen::Matrix< double, 2, 2 > Matrix2d
Definition: ekf.hpp:28
double sigma
Sharpness (derivative of curvature with respect to arc length) of a segment.
double std_theta
Standard deviation of localization in theta.
Matrix23d get_controller_gain(const Control &control) const
Returns the gain of the controller.
Definition: ekf.cpp:190
double Sigma[16]
Covariance of the state estimation due to motion and measurement noise.
Matrix3d get_rotation_matrix(double angle) const
Returns the rotation matrix from a global frame to a local frame.
Definition: ekf.cpp:199
double alpha3
Variance in lateral direction: alpha3*delta_s*delta_s + alpha4*kappa*kappa.
double kappa
Curvature at position (x,y)
INLINE Rall1d< T, V, S > cos(const Rall1d< T, V, S > &arg)
Matrix3d I_
Identity matrix.
Definition: ekf.hpp:90
INLINE Rall1d< T, V, S > sin(const Rall1d< T, V, S > &arg)
double theta
Orientation of the robot.
Measurement_Noise measurement_noise_
Measurement noise.
Definition: ekf.hpp:84
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:212
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:63


steering_functions
Author(s): Holger Banzhaf
autogenerated on Thu Aug 18 2022 02:09:46