54 out.resize(m.rows()+n.rows(), m.cols());
64 out.resize(m.rows()+n.rows(), m.cols());
71 return Eigen::LLT<Eigen::MatrixXd>(matrix).matrixL();
75 std::vector<MatrixXd > out;
77 double gamma = std::sqrt((state.rows()+lambda));
78 MatrixXd sig_sqrt = gamma*
matrixSqrt(covariance);
84 for(
size_t i = 1; i <= state.rows(); i++){
85 out.push_back(state + sig_sqrt.col(i-1));
89 for(
size_t i = state.rows() + 1; i <= 2*state.rows(); i++){
90 out.push_back(state - sig_sqrt.col(i-(state.rows()+1)));
96 MatrixXd meanFromSigmaPoints(std::vector<MatrixXd >& sigma_points,
double n,
double lambda){
97 double weight_zero = lambda / (n + lambda);
98 MatrixXd out = weight_zero * sigma_points[0];
99 double weight_i = 1.0/(2*(n + lambda));
100 for(
size_t i = 1; i <= 2*n; i++){
101 out = out + weight_i * sigma_points[i];
107 MatrixXd
covarianceFromSigmaPoints(std::vector<MatrixXd >& sigma_points, MatrixXd& mean, MatrixXd process_noise,
double n,
double alpha,
double beta,
double lambda){
108 double cov_weight_zero = lambda / (n + lambda) + (1 - alpha*alpha + beta);
109 MatrixXd out = cov_weight_zero * (sigma_points[0] - mean) * (sigma_points[0] - mean).transpose();
110 double weight_i = 1.0/(2*(n + lambda));
111 for(
size_t i = 1; i <= 2*n; i++){
112 out = out + weight_i * (sigma_points[i] - mean) * (sigma_points[i] - mean).transpose();
114 return out+process_noise;
117 MatrixXd
crossCovariance(std::vector<MatrixXd >& sigma_points, MatrixXd& mean, std::vector<MatrixXd >& meas_sigma_points, MatrixXd& meas_mean,
double alpha,
double beta,
double lambda){
118 double n = sigma_points[0].rows();
119 double cov_weight_zero = lambda / (n + lambda) + (1 - alpha*alpha + beta);
120 MatrixXd out = cov_weight_zero * (sigma_points[0] - mean) * (meas_sigma_points[0] - meas_mean).transpose();
121 double weight_i = 1.0/(2*(n + lambda));
122 for(
size_t i = 1; i <= 2*n; i++){
123 out = out + weight_i * (sigma_points[i] - mean) * (meas_sigma_points[i] - meas_mean).transpose();
129 Matrix<double, 4, 4> out;
130 out << 0, wx, wy, wz,
138 double q_mag = std::sqrt(q(0)*q(0) + q(1)*q(1) + q(2)*q(2) + q(3)*q(3));
142 Matrix<double, 4, 1>
updatedQuaternion(
const Matrix<double, 4, 1>& q,
const double wx,
const double wy,
const double wz,
double dt){
143 Matrix<double, 4, 1> out;
144 Matrix<double, 4, 4> I = Matrix<double, 4, 4>::Identity();
145 double s = 1.0/2.0 * std::sqrt(wx*wx*dt*dt + wy*wy*dt*dt + wz*wz*dt*dt);
147 double q_mag = std::sqrt(q(0)*q(0) + q(1)*q(1) + q(2)*q(2) + q(3)*q(3));
148 double err = 1.0 - q_mag*q_mag;
150 double correction_factor = 1 - 1.0/2.0*
s*
s + 1.0/24.0*
s*
s*
s*
s + k * dt * err;
151 MatrixXd correction = I*(correction_factor);
152 double update_factor = 1.0/2.0*dt*(1.0 - 1.0/6.0*
s*
s + 1.0/120.0*
s*
s*
s*
s);
154 MatrixXd
update = update_factor*quaterion_update_matrix;
155 out = (correction-
update)*q;
158 double out_mag = std::sqrt(out(0)*out(0) + out(1)*out(1) + out(2)*out(2) + out(3)*out(3));
159 double out_err = 1.0 - out_mag*out_mag;
165 Matrix<double, SIZE, 1> out;
167 Matrix<double, 4, 1> new_q =
updatedQuaternion(x.block(0, 0, 4, 1), x(4), x(5), x(6), dt);
168 out.block(0, 0, 4, 1) = new_q;
176 graft::GraftState::Ptr out(
new graft::GraftState());
177 out->pose.orientation.w = state(0);
178 out->pose.orientation.x = state(1);
179 out->pose.orientation.y = state(2);
180 out->pose.orientation.z = state(3);
181 out->twist.angular.x = state(4);
182 out->twist.angular.y = state(5);
183 out->twist.angular.z = state(6);
188 std::vector<MatrixXd > out;
189 for(
size_t i = 0; i < sigma_points.size(); i++){
190 out.push_back(
f(sigma_points[i], dt));
200 graft::GraftStatePtr msg(
new graft::GraftState());
201 msg->pose.orientation.w = state(0);
202 msg->pose.orientation.x = state(1);
203 msg->pose.orientation.y = state(2);
204 msg->pose.orientation.z = state(3);
205 msg->twist.angular.x = state(4);
206 msg->twist.angular.y = state(5);
207 msg->twist.angular.z = state(6);
209 for(
size_t i = 0; i <
SIZE*
SIZE; i++){
210 msg->covariance[i] = covariance(i);
221 VectorXd out(vec.size() + 1);
227 MatrixXd out(mat.rows() + 1, 1);
228 MatrixXd small(1, 1);
229 small(0,0) = element;
238 geometry_msgs::Vector3 out;
239 double mag = std::sqrt(accel.x*accel.x + accel.y*accel.y + accel.z*accel.z);
240 out.x = accel.x / mag;
241 out.y = accel.y / mag;
242 out.z = accel.z / mag;
248 VectorXd actual_measurement;
249 output_measurement_sigmas.clear();
250 VectorXd innovation_covariance_diagonal;
251 innovation_covariance_diagonal.resize(0);
253 std::vector<graft::GraftState::ConstPtr> predicted_sigma_msgs;
254 for(
size_t i = 0; i < predicted_sigma_points.size(); i++){
256 output_measurement_sigmas.push_back(MatrixXd());
261 for(
size_t i = 0; i < topics.size(); i++){
263 graft::GraftSensorResidual::ConstPtr meas = topics[i]->z();
265 std::vector<graft::GraftSensorResidual::ConstPtr> residuals_msgs;
266 for(
size_t j = 0; j < predicted_sigma_msgs.size(); j++){
267 graft::GraftSensorResidual::Ptr msg = topics[i]->h(*predicted_sigma_msgs[j]);
268 residuals_msgs.push_back(msg);
276 if(meas->twist_covariance[21] > 1e-20){
278 innovation_covariance_diagonal =
addElementToVector(innovation_covariance_diagonal, meas->twist_covariance[21]);
279 for(
size_t j = 0; j < residuals_msgs.size(); j++){
280 output_measurement_sigmas[j] =
addElementToColumnMatrix(output_measurement_sigmas[j], residuals_msgs[j]->twist.angular.x);
284 if(meas->twist_covariance[28] > 1e-20){
286 innovation_covariance_diagonal =
addElementToVector(innovation_covariance_diagonal, meas->twist_covariance[28]);
287 for(
size_t j = 0; j < residuals_msgs.size(); j++){
288 output_measurement_sigmas[j] =
addElementToColumnMatrix(output_measurement_sigmas[j], residuals_msgs[j]->twist.angular.y);
292 if(meas->twist_covariance[35] > 1e-20){
294 innovation_covariance_diagonal =
addElementToVector(innovation_covariance_diagonal, meas->twist_covariance[35]);
295 for(
size_t j = 0; j < residuals_msgs.size(); j++){
296 output_measurement_sigmas[j] =
addElementToColumnMatrix(output_measurement_sigmas[j], residuals_msgs[j]->twist.angular.z);
300 if(meas->accel_covariance[0] > 1e-20 && meas->accel_covariance[4] > 1e-20 && meas->accel_covariance[8] > 1e-20){
305 innovation_covariance_diagonal =
addElementToVector(innovation_covariance_diagonal, meas->accel_covariance[0]);
306 innovation_covariance_diagonal =
addElementToVector(innovation_covariance_diagonal, meas->accel_covariance[4]);
307 innovation_covariance_diagonal =
addElementToVector(innovation_covariance_diagonal, meas->accel_covariance[8]);
308 for(
size_t j = 0; j < residuals_msgs.size(); j++){
318 output_innovation_covariance = innovation_covariance_diagonal.asDiagonal();
320 return actual_measurement;
324 for(
size_t i = 0; i < topics.size(); i++){
325 topics[i]->clearMessage();
336 ROS_WARN(
"Negative dt, skipping update.");
345 std::vector<MatrixXd > predicted_sigma_points =
predict_sigma_points(previous_sigma_points, dt);
346 MatrixXd predicted_mean = meanFromSigmaPoints(predicted_sigma_points,
graft_state_.rows(), lambda);
350 std::vector<MatrixXd> observation_sigma_points =
generateSigmaPoints(predicted_mean, predicted_covariance, lambda);
351 std::vector<MatrixXd> predicted_observation_sigma_points;
352 MatrixXd measurement_noise;
353 MatrixXd z =
getMeasurements(
topics_, observation_sigma_points, predicted_observation_sigma_points, measurement_noise);
357 MatrixXd predicted_measurement = meanFromSigmaPoints(predicted_observation_sigma_points,
graft_state_.rows(), lambda);
359 MatrixXd cross_covariance =
crossCovariance(observation_sigma_points, predicted_mean, predicted_observation_sigma_points, predicted_measurement,
alpha_,
beta_, lambda);
360 MatrixXd K = cross_covariance * predicted_measurement_uncertainty.partialPivLu().inverse();
361 graft_state_ = predicted_mean + K*(z - predicted_measurement);
363 graft_covariance_ = predicted_covariance - K*predicted_measurement_uncertainty*K.transpose();
377 for(
size_t i = 0; i < P.size(); i++){
380 }
else if(P.size() == diagonal_size){
381 for(
size_t i = 0; i < P.size(); i++){
385 ROS_ERROR(
"initial_covariance is size %zu, expected %zu.\nUsing Identity.\nThis probably won't work well.", P.size(),
graft_covariance_.size());
393 size_t diagonal_size = std::sqrt(
Q_.size());
394 if(Q.size() ==
Q_.size()){
395 for(
size_t i = 0; i < Q.size(); i++){
398 }
else if(Q.size() == diagonal_size){
399 for(
size_t i = 0; i < Q.size(); i++){
400 Q_(i*(diagonal_size+1)) = Q[i];
403 ROS_ERROR(
"Process noise parameter 'Q' is size %zu, expected %zu.\nUsing 0.1*Identity.\nThis probably won't work well.", Q.size(),
Q_.size());