-
Notifications
You must be signed in to change notification settings - Fork 13.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ekf2: fill pose and vel covariance in odometry #16929
Closed
Closed
Changes from all commits
Commits
File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -843,6 +843,56 @@ void EKF2::PublishLocalPosition(const hrt_abstime ×tamp) | |
_local_position_pub.publish(lpos); | ||
} | ||
|
||
matrix::SquareMatrix<float, 3> EKF2::propagate_covariances_from_quat_to_euler(const matrix::Quatf &q, | ||
const matrix::SquareMatrix<float, 4> &quat_covariances) const | ||
{ | ||
// Jacobian matrix (3x4) containing the partial derivatives of the | ||
// Euler angle equations with respect to the quaternions | ||
matrix::Matrix<float, 3, 4> G; | ||
|
||
// quaternion components | ||
float q1 = q(0); | ||
float q2 = q(1); | ||
float q3 = q(2); | ||
float q4 = q(3); | ||
|
||
// numerator components | ||
float n1 = 2 * q1 * q2 + 2 * q2 * q4; | ||
float n2 = -2 * q2 * q2 - 2 * q3 * q3 + 1; | ||
float n3 = 2 * q1 * q4 + 2 * q2 * q3; | ||
float n4 = -2 * q3 * q3 - 2 * q4 * q4 + 1; | ||
float n5 = 2 * q1 * q3 + 2 * q2 * q4; | ||
float n6 = -2 * q1 * q2 - 2 * q2 * q4; | ||
float n7 = -2 * q1 * q4 - 2 * q2 * q3; | ||
|
||
// Protect against division by 0 | ||
float d1 = n1 * n1 + n2 * n2; | ||
float d2 = n3 * n3 + n4 * n4; | ||
d1 = math::max(0.0f, d1); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This doesn't protect against /0 where we divide by d1. Likewise for d2. |
||
d2 = math::max(0.0f, d2); | ||
|
||
// Protect against square root of negative numbers | ||
float x = math::max(-n5 * n5 + 1, 0.0f); | ||
|
||
// compute G matrix | ||
float sqrt_x = sqrtf(x); | ||
float g00_03 = 2 * q2 * n2 / d1; | ||
G(0, 0) = g00_03; | ||
G(0, 1) = -4 * q2 * n6 / d1 + (2 * q1 + 2 * q4) * n2 / d1; | ||
G(0, 2) = -4 * q3 * n6 / d1; | ||
G(0, 3) = g00_03; | ||
G(1, 0) = 2 * q3 / sqrt_x; | ||
G(1, 1) = 2 * q4 / sqrt_x; | ||
G(1, 2) = 2 * q1 / sqrt_x; | ||
G(1, 3) = 2 * q2 / sqrt_x; | ||
G(2, 0) = 2 * q4 * n4 / d2; | ||
G(2, 1) = 2 * q3 * n4 / d2; | ||
G(2, 2) = 2 * q2 * n4 / d2 - 4 * q3 * n7 / d2; | ||
G(2, 3) = 2 * q1 * n4 / d2 - 4 * q4 * n7 / d2; | ||
|
||
return G * quat_covariances * G.transpose(); | ||
} | ||
|
||
void EKF2::PublishOdometry(const hrt_abstime ×tamp, const imuSample &imu) | ||
{ | ||
// generate vehicle odometry data | ||
|
@@ -874,36 +924,19 @@ void EKF2::PublishOdometry(const hrt_abstime ×tamp, const imuSample &imu) | |
odom.pitchspeed = rates(1) - gyro_bias(1); | ||
odom.yawspeed = rates(2) - gyro_bias(2); | ||
|
||
// get the covariance matrix size | ||
static constexpr size_t POS_URT_SIZE = sizeof(odom.pose_covariance) / sizeof(odom.pose_covariance[0]); | ||
static constexpr size_t VEL_URT_SIZE = sizeof(odom.velocity_covariance) / sizeof(odom.velocity_covariance[0]); | ||
|
||
// Get covariances to vehicle odometry | ||
float covariances[24]; | ||
_ekf.covariances_diagonal().copyTo(covariances); | ||
|
||
// initially set pose covariances to 0 | ||
for (size_t i = 0; i < POS_URT_SIZE; i++) { | ||
odom.pose_covariance[i] = 0.0; | ||
} | ||
|
||
// set the position variances | ||
odom.pose_covariance[odom.COVARIANCE_MATRIX_X_VARIANCE] = covariances[7]; | ||
odom.pose_covariance[odom.COVARIANCE_MATRIX_Y_VARIANCE] = covariances[8]; | ||
odom.pose_covariance[odom.COVARIANCE_MATRIX_Z_VARIANCE] = covariances[9]; | ||
|
||
// TODO: implement propagation from quaternion covariance to Euler angle covariance | ||
// by employing the covariance law | ||
|
||
// initially set velocity covariances to 0 | ||
for (size_t i = 0; i < VEL_URT_SIZE; i++) { | ||
odom.velocity_covariance[i] = 0.0; | ||
} | ||
|
||
// set the linear velocity variances | ||
odom.velocity_covariance[odom.COVARIANCE_MATRIX_VX_VARIANCE] = covariances[4]; | ||
odom.velocity_covariance[odom.COVARIANCE_MATRIX_VY_VARIANCE] = covariances[5]; | ||
odom.velocity_covariance[odom.COVARIANCE_MATRIX_VZ_VARIANCE] = covariances[6]; | ||
// Row-major representation of 6x6 pose cross-covariance matrix URT. | ||
// Order: x, y, z, rotation about X axis, rotation about Y axis, rotation about Z axis | ||
matrix::SquareMatrix<float, 6> pose_cov{matrix::nans<6, 6>()}; | ||
pose_cov.slice<3, 3>(0, 0) = _ekf.covariances().slice<3, 3>(7, 7); | ||
pose_cov.slice<3, 3>(3, 3) = propagate_covariances_from_quat_to_euler(_ekf.getQuaternion(), | ||
_ekf.covariances().slice<4, 4>(0, 0)); | ||
pose_cov.upper_right_triangle().copyTo(odom.pose_covariance); | ||
|
||
// Row-major representation of 6x6 velocity cross-covariance matrix URT. | ||
// Order: vx, vy, vz, rotation rate about X axis, rotation rate about Y axis, rotation rate about Z axis | ||
matrix::SquareMatrix<float, 6> vel_cov{matrix::nans<6, 6>()}; | ||
vel_cov.slice<3, 3>(0, 0) = _ekf.covariances().slice<3, 3>(4, 4); | ||
vel_cov.upper_right_triangle().copyTo(odom.velocity_covariance); | ||
|
||
// publish vehicle odometry data | ||
odom.timestamp = _replay_mode ? timestamp : hrt_absolute_time(); | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Where did these come from?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I will see if this derivation can be added to our existing sympy script.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
See https://github.com/priseborough/PX4-Autopilot/tree/pr-ekf2_derivation_update for a symbolic derivation
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Nuno's original PR for context. #11092