3939#include < Eigen/Core>
4040
4141#include < cmath>
42+ #include < numeric>
4243#include < string>
4344
4445#include < rclcpp/logging.hpp>
@@ -158,7 +159,7 @@ Eigen::Matrix<T, 2, 2, Eigen::RowMajor> rotationMatrix2D(const T angle)
158159 * @param[in] rpy Pointer to the roll, pitch, yaw array (3x1)
159160 * @param[in] jacobian Pointer to the jacobian matrix (3x4, optional)
160161 */
161- static inline void quaternion2rpy (const double * q, double * rpy, double * jacobian = nullptr )
162+ static inline void quaternion2rpy (const double * q, double * rpy, double * jacobian = nullptr )
162163{
163164 rpy[0 ] = fuse_core::getRoll (q[0 ], q[1 ], q[2 ], q[3 ]);
164165 rpy[1 ] = fuse_core::getPitch (q[0 ], q[1 ], q[2 ], q[3 ]);
@@ -170,8 +171,8 @@ static inline void quaternion2rpy(const double * q, double * rpy, double * jacob
170171 const double qx = q[1 ];
171172 const double qy = q[2 ];
172173 const double qz = q[3 ];
173- const double discr = qw * qy - qx * qz;
174- const double gl_limit = 0.5 - 2.0 * std::numeric_limits<double >::epsilon ();
174+ const double discr = qw * qy - qx * qz;
175+ const double gl_limit = 0.5 - 2.0 * std::numeric_limits<double >::epsilon ();
175176
176177 if (discr > gl_limit) {
177178 // pitch = 90 deg
@@ -189,82 +190,114 @@ static inline void quaternion2rpy(const double * q, double * rpy, double * jacob
189190 // Non-degenerate case:
190191 jacobian_map (0 , 0 ) =
191192 -(2.0 * qx) /
192- ((std::pow ((2.0 * qw * qx + 2.0 * qy * qz), 2.0 ) / std::pow ((2.0 * qx * qx + 2.0 * qy * qy - 1.0 ), 2.0 ) +
193+ ((std::pow (
194+ (2.0 * qw * qx + 2.0 * qy * qz),
195+ 2.0 ) / std::pow ((2.0 * qx * qx + 2.0 * qy * qy - 1.0 ), 2.0 ) +
193196 1.0 ) *
194197 (2.0 * qx * qx + 2.0 * qy * qy - 1.0 ));
195198 jacobian_map (0 , 1 ) =
196199 -((2.0 * qw) / (2.0 * qx * qx + 2.0 * qy * qy - 1.0 ) -
197- (4.0 * qx * (2.0 * qw * qx + 2.0 * qy * qz)) / std::pow ((2.0 * qx * qx + 2.0 * qy * qy - 1.0 ), 2.0 )) /
198- (std::pow ((2.0 * qw * qx + 2.0 * qy * qz), 2.0 ) / std::pow ((2.0 * qx * qx + 2.0 * qy * qy - 1.0 ), 2.0 ) + 1.0 );
200+ (4.0 * qx * (2.0 * qw * qx + 2.0 * qy * qz)) /
201+ std::pow ((2.0 * qx * qx + 2.0 * qy * qy - 1.0 ), 2.0 )) /
202+ (std::pow (
203+ (2.0 * qw * qx + 2.0 * qy * qz),
204+ 2.0 ) / std::pow ((2.0 * qx * qx + 2.0 * qy * qy - 1.0 ), 2.0 ) + 1.0 );
199205 jacobian_map (0 , 2 ) =
200206 -((2.0 * qz) / (2.0 * qx * qx + 2.0 * qy * qy - 1.0 ) -
201- (4.0 * qy * (2.0 * qw * qx + 2.0 * qy * qz)) / std::pow ((2.0 * qx * qx + 2.0 * qy * qy - 1.0 ), 2.0 )) /
202- (std::pow ((2.0 * qw * qx + 2.0 * qy * qz), 2.0 ) / std::pow ((2.0 * qx * qx + 2.0 * qy * qy - 1.0 ), 2.0 ) + 1.0 );
207+ (4.0 * qy * (2.0 * qw * qx + 2.0 * qy * qz)) /
208+ std::pow ((2.0 * qx * qx + 2.0 * qy * qy - 1.0 ), 2.0 )) /
209+ (std::pow (
210+ (2.0 * qw * qx + 2.0 * qy * qz),
211+ 2.0 ) / std::pow ((2.0 * qx * qx + 2.0 * qy * qy - 1.0 ), 2.0 ) + 1.0 );
203212 jacobian_map (0 , 3 ) =
204213 -(2.0 * qy) /
205- ((std::pow ((2.0 * qw * qx + 2.0 * qy * qz), 2.0 ) / std::pow ((2.0 * qx * qx + 2.0 * qy * qy - 1.0 ), 2.0 ) +
214+ ((std::pow (
215+ (2.0 * qw * qx + 2.0 * qy * qz),
216+ 2.0 ) / std::pow ((2.0 * qx * qx + 2.0 * qy * qy - 1.0 ), 2.0 ) +
206217 1.0 ) *
207218 (2.0 * qx * qx + 2.0 * qy * qy - 1.0 ));
208219
209- jacobian_map (1 , 0 ) = (2.0 * qy) / std::sqrt (1.0 - std::pow ((2.0 * qw * qy - 2.0 * qx * qz), 2.0 ));
210- jacobian_map (1 , 1 ) = -(2.0 * qz) / std::sqrt (1.0 - std::pow ((2.0 * qw * qy - 2.0 * qx * qz), 2.0 ));
211- jacobian_map (1 , 2 ) = (2.0 * qw) / std::sqrt (1.0 - std::pow ((2.0 * qw * qy - 2.0 * qx * qz), 2.0 ));
212- jacobian_map (1 , 3 ) = -(2.0 * qx) / std::sqrt (1.0 - std::pow ((2.0 * qw * qy - 2.0 * qx * qz), 2.0 ));
220+ jacobian_map (
221+ 1 ,
222+ 0 ) = (2.0 * qy) / std::sqrt (1.0 - std::pow ((2.0 * qw * qy - 2.0 * qx * qz), 2.0 ));
223+ jacobian_map (
224+ 1 ,
225+ 1 ) = -(2.0 * qz) / std::sqrt (1.0 - std::pow ((2.0 * qw * qy - 2.0 * qx * qz), 2.0 ));
226+ jacobian_map (
227+ 1 ,
228+ 2 ) = (2.0 * qw) / std::sqrt (1.0 - std::pow ((2.0 * qw * qy - 2.0 * qx * qz), 2.0 ));
229+ jacobian_map (
230+ 1 ,
231+ 3 ) = -(2.0 * qx) / std::sqrt (1.0 - std::pow ((2.0 * qw * qy - 2.0 * qx * qz), 2.0 ));
213232
214233 jacobian_map (2 , 0 ) =
215234 -(2.0 * qz) /
216- ((std::pow ((2.0 * qw * qz + 2.0 * qx * qy), 2.0 ) / std::pow ((2.0 * qy * qy + 2.0 * qz * qz - 1.0 ), 2.0 ) +
235+ ((std::pow (
236+ (2.0 * qw * qz + 2.0 * qx * qy),
237+ 2.0 ) / std::pow ((2.0 * qy * qy + 2.0 * qz * qz - 1.0 ), 2.0 ) +
217238 1.0 ) *
218239 (2.0 * qy * qy + 2.0 * qz * qz - 1.0 ));
219240 jacobian_map (2 , 1 ) =
220241 -(2.0 * qy) /
221- ((std::pow ((2.0 * qw * qz + 2.0 * qx * qy), 2.0 ) / std::pow ((2.0 * qy * qy + 2.0 * qz * qz - 1.0 ), 2.0 ) +
242+ ((std::pow (
243+ (2.0 * qw * qz + 2.0 * qx * qy),
244+ 2.0 ) / std::pow ((2.0 * qy * qy + 2.0 * qz * qz - 1.0 ), 2.0 ) +
222245 1.0 ) *
223246 (2.0 * qy * qy + 2.0 * qz * qz - 1.0 ));
224247 jacobian_map (2 , 2 ) =
225248 -((2.0 * qx) / (2.0 * qy * qy + 2.0 * qz * qz - 1.0 ) -
226- (4.0 * qy * (2.0 * qw * qz + 2.0 * qx * qy)) / std::pow ((2.0 * qy * qy + 2.0 * qz * qz - 1.0 ), 2.0 )) /
227- (std::pow ((2.0 * qw * qz + 2.0 * qx * qy), 2.0 ) / std::pow ((2.0 * qy * qy + 2.0 * qz * qz - 1.0 ), 2.0 ) + 1.0 );
249+ (4.0 * qy * (2.0 * qw * qz + 2.0 * qx * qy)) /
250+ std::pow ((2.0 * qy * qy + 2.0 * qz * qz - 1.0 ), 2.0 )) /
251+ (std::pow (
252+ (2.0 * qw * qz + 2.0 * qx * qy),
253+ 2.0 ) / std::pow ((2.0 * qy * qy + 2.0 * qz * qz - 1.0 ), 2.0 ) + 1.0 );
228254 jacobian_map (2 , 3 ) =
229255 -((2.0 * qw) / (2.0 * qy * qy + 2.0 * qz * qz - 1.0 ) -
230- (4.0 * qz * (2.0 * qw * qz + 2.0 * qx * qy)) / std::pow ((2.0 * qy * qy + 2.0 * qz * qz - 1.0 ), 2.0 )) /
231- (std::pow ((2.0 * qw * qz + 2.0 * qx * qy), 2.0 ) / std::pow ((2.0 * qy * qy + 2.0 * qz * qz - 1.0 ), 2.0 ) + 1.0 );
256+ (4.0 * qz * (2.0 * qw * qz + 2.0 * qx * qy)) /
257+ std::pow ((2.0 * qy * qy + 2.0 * qz * qz - 1.0 ), 2.0 )) /
258+ (std::pow (
259+ (2.0 * qw * qz + 2.0 * qx * qy),
260+ 2.0 ) / std::pow ((2.0 * qy * qy + 2.0 * qz * qz - 1.0 ), 2.0 ) + 1.0 );
232261 }
233262 }
234263}
235264
236265/* *
237266 * @brief Compute product of two quaternions and the function jacobian
238- * TODO(giafranchini): parametric jacobian computation? Atm this function is only used in
267+ * TODO(giafranchini): parametric jacobian computation? Atm this function is only used in
239268 * normal_prior_pose_3d cost function. There we only need the derivatives wrt quaternion W,
240269 * so at the time we are only computing the jacobian wrt W
241- *
270+ *
242271 * @param[in] z Pointer to the first quaternion array (4x1)
243272 * @param[in] w Pointer to the second quaternion array (4x1)
244273 * @param[in] zw Pointer to the output quaternion array (4x1) that will be populated with the result of z * w
245274 * @param[in] jacobian Pointer to the jacobian of zw with respect to w (4x4, optional)
246275 */
247- static inline void quaternionProduct (const double * z, const double * w, double * zw, double * jacobian = nullptr )
276+ static inline void quaternionProduct (
277+ const double * z, const double * w, double * zw,
278+ double * jacobian = nullptr )
248279{
249280 ceres::QuaternionProduct (z, w, zw);
250281 if (jacobian) {
251282 Eigen::Map<Eigen::Matrix<double , 4 , 4 , Eigen::RowMajor>> jacobian_map (jacobian);
252- jacobian_map <<
283+ jacobian_map <<
253284 z[0 ], -z[1 ], -z[2 ], -z[3 ],
254- z[1 ], z[0 ], -z[3 ], z[2 ],
255- z[2 ], z[3 ], z[0 ], -z[1 ],
256- z[3 ], -z[2 ], z[1 ], z[0 ];
285+ z[1 ], z[0 ], -z[3 ], z[2 ],
286+ z[2 ], z[3 ], z[0 ], -z[1 ],
287+ z[3 ], -z[2 ], z[1 ], z[0 ];
257288 }
258289}
259290
260291/* *
261292 * @brief Compute quaternion to AngleAxis conversion and the function jacobian
262- *
293+ *
263294 * @param[in] q Pointer to the quaternion array (4x1)
264- * @param[in] angle_axis Pointer to the angle_axis array (3x1)
295+ * @param[in] angle_axis Pointer to the angle_axis array (3x1)
265296 * @param[in] jacobian Pointer to the jacobian matrix (3x4, optional)
266297 */
267- static inline void quaternionToAngleAxis (const double * q, double * angle_axis, double * jacobian = nullptr )
298+ static inline void quaternionToAngleAxis (
299+ const double * q, double * angle_axis,
300+ double * jacobian = nullptr )
268301{
269302 ceres::QuaternionToAngleAxis (q, angle_axis);
270303 if (jacobian) {
@@ -275,47 +308,51 @@ static inline void quaternionToAngleAxis(const double * q, double * angle_axis,
275308 const double & q3 = q[3 ];
276309 const double q_sum2 = q0 * q0 + q1 * q1 + q2 * q2 + q3 * q3;
277310 const double sin_theta2 = q1 * q1 + q2 * q2 + q3 * q3;
278- const double sin_theta = std::sqrt (sin_theta2 );
311+ const double sin_theta = std::hypot (q1, q2, q3 );
279312 const double cos_theta = q0;
280313
281- if (std::fpclassify (sin_theta) != FP_ZERO) {
282- const double two_theta = 2.0 *
283- (cos_theta < 0.0 ? std::atan2 (-sin_theta, -cos_theta) : std::atan2 (sin_theta, cos_theta));
314+ const double cond = std::pow (sin_theta2, 1.5 );
315+ if (std::fpclassify (cond) != FP_ZERO) {
316+ const double two_theta = 2.0 *
317+ (cos_theta < 0.0 ? std::atan2 (-sin_theta, -cos_theta) : std::atan2 (sin_theta, cos_theta));
318+ const double a = two_theta / sin_theta;
319+ const double b = sin_theta2 * q_sum2;
320+ const double c = two_theta / cond;
284321 jacobian_map (0 , 0 ) = -2.0 * q1 / q_sum2;
285- jacobian_map (0 , 1 ) =
286- two_theta / sin_theta +
287- (2.0 * q0 * q1 * q1) / (sin_theta2 * q_sum2) -
288- (q1 * q1 * two_theta) / std::pow (sin_theta2, 1.5 );
289- jacobian_map (0 , 2 ) =
290- (2.0 * q0 * q1 * q2) / (sin_theta2 * q_sum2) -
291- (q1 * q2 * two_theta) / std::pow (sin_theta2, 1.5 );
322+ jacobian_map (0 , 1 ) =
323+ two_theta / sin_theta +
324+ (2.0 * q0 * q1 * q1) / b -
325+ (q1 * q1 * c );
326+ jacobian_map (0 , 2 ) =
327+ (2.0 * q0 * q1 * q2) / b -
328+ (q1 * q2 * c );
292329 jacobian_map (0 , 3 ) =
293- (2.0 * q0 * q1 * q3) / (sin_theta2 * q_sum2) -
294- (q1 * q3 * two_theta) / std::pow (sin_theta2, 1.5 );
295-
330+ (2.0 * q0 * q1 * q3) / b -
331+ (q1 * q3 * c );
332+
296333 jacobian_map (1 , 0 ) = -2.0 * q2 / q_sum2;
297- jacobian_map (1 , 1 ) =
298- (2.0 * q0 * q1 * q2) / (sin_theta2 * q_sum2) -
299- (q1 * q2 * two_theta) / std::pow (sin_theta2, 1.5 );
300- jacobian_map (1 , 2 ) =
301- two_theta / sin_theta +
302- (2.0 * q0 * q2 * q2) / (sin_theta2 * q_sum2) -
303- (q2 * q2 * two_theta) / std::pow (sin_theta2, 1.5 );
304- jacobian_map (1 , 3 ) =
305- (2.0 * q0 * q2 * q3) / (sin_theta2 * q_sum2) -
306- (q2 * q3 * two_theta) / std::pow (sin_theta2, 1.5 );
307-
334+ jacobian_map (1 , 1 ) =
335+ (2.0 * q0 * q1 * q2) / b -
336+ (q1 * q2 * c );
337+ jacobian_map (1 , 2 ) =
338+ two_theta / sin_theta +
339+ (2.0 * q0 * q2 * q2) / b -
340+ (q2 * q2 * c );
341+ jacobian_map (1 , 3 ) =
342+ (2.0 * q0 * q2 * q3) / b -
343+ (q2 * q3 * c );
344+
308345 jacobian_map (2 , 0 ) = -2.0 * q3 / q_sum2;
309- jacobian_map (2 , 1 ) =
310- (2.0 * q0 * q1 * q3) / (sin_theta2 * q_sum2) -
311- (q1 * q3 * two_theta) / std::pow (sin_theta2, 1.5 );
312- jacobian_map (2 , 2 ) =
313- (2.0 * q0 * q2 * q3) / (sin_theta2 * q_sum2) -
314- (q2 * q3 * two_theta) / std::pow (sin_theta2, 1.5 );
346+ jacobian_map (2 , 1 ) =
347+ (2.0 * q0 * q1 * q3) / b -
348+ (q1 * q3 * c );
349+ jacobian_map (2 , 2 ) =
350+ (2.0 * q0 * q2 * q3) / b -
351+ (q2 * q3 * c );
315352 jacobian_map (2 , 3 ) =
316- two_theta / sin_theta +
317- (2.0 * q0 * q3 * q3) / (sin_theta2 * q_sum2) -
318- (q3 * q3 * two_theta) / std::pow (sin_theta2, 1.5 );
353+ two_theta / sin_theta +
354+ (2.0 * q0 * q3 * q3) / b -
355+ (q3 * q3 * c );
319356 } else {
320357 jacobian_map.setZero ();
321358 jacobian_map (0 , 1 ) = 2.0 ;
0 commit comments