Cached Rot3::transpose(). Inspired by @cbeall3 fix of Unit3, I realized that with one million points and 1000 cameras, the same Matrix3 (R_.transpose()) was computed a 1000 more times than needed. Especially with quaternions this would be expensive, even with Rot3Q.
parent
4a854f7e22
commit
c4bf680e96
|
@ -263,7 +263,7 @@ Point3 Pose3::transform_to(const Point3& p, boost::optional<Matrix36&> Dpose,
|
||||||
boost::optional<Matrix3&> Dpoint) const {
|
boost::optional<Matrix3&> Dpoint) const {
|
||||||
// Only get transpose once, to avoid multiple allocations,
|
// Only get transpose once, to avoid multiple allocations,
|
||||||
// as well as multiple conversions in the Quaternion case
|
// as well as multiple conversions in the Quaternion case
|
||||||
Matrix3 Rt(R_.transpose());
|
const Matrix3& Rt = R_.transpose();
|
||||||
const Point3 q(Rt*(p - t_).vector());
|
const Point3 q(Rt*(p - t_).vector());
|
||||||
if (Dpose) {
|
if (Dpose) {
|
||||||
const double wx = q.x(), wy = q.y(), wz = q.z();
|
const double wx = q.x(), wy = q.y(), wz = q.z();
|
||||||
|
@ -280,7 +280,7 @@ Point3 Pose3::transform_to(const Point3& p, boost::optional<Matrix36&> Dpose,
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
Point3 Pose3::transform_to(const Point3& p, boost::optional<Matrix&> Dpose,
|
Point3 Pose3::transform_to(const Point3& p, boost::optional<Matrix&> Dpose,
|
||||||
boost::optional<Matrix&> Dpoint) const {
|
boost::optional<Matrix&> Dpoint) const {
|
||||||
Matrix3 Rt(R_.transpose());
|
const Matrix3& Rt = R_.transpose();
|
||||||
const Point3 q(Rt*(p - t_).vector());
|
const Point3 q(Rt*(p - t_).vector());
|
||||||
if (Dpose) {
|
if (Dpose) {
|
||||||
const double wx = q.x(), wy = q.y(), wz = q.z();
|
const double wx = q.x(), wy = q.y(), wz = q.z();
|
||||||
|
|
|
@ -101,7 +101,7 @@ Unit3 Rot3::operator*(const Unit3& p) const {
|
||||||
// see doc/math.lyx, SO(3) section
|
// see doc/math.lyx, SO(3) section
|
||||||
Point3 Rot3::unrotate(const Point3& p, boost::optional<Matrix3&> H1,
|
Point3 Rot3::unrotate(const Point3& p, boost::optional<Matrix3&> H1,
|
||||||
boost::optional<Matrix3&> H2) const {
|
boost::optional<Matrix3&> H2) const {
|
||||||
Matrix3 Rt(transpose());
|
const Matrix3& Rt = transpose();
|
||||||
Point3 q(Rt * p.vector()); // q = Rt*p
|
Point3 q(Rt * p.vector()); // q = Rt*p
|
||||||
const double wx = q.x(), wy = q.y(), wz = q.z();
|
const double wx = q.x(), wy = q.y(), wz = q.z();
|
||||||
if (H1)
|
if (H1)
|
||||||
|
@ -115,7 +115,7 @@ Point3 Rot3::unrotate(const Point3& p, boost::optional<Matrix3&> H1,
|
||||||
// see doc/math.lyx, SO(3) section
|
// see doc/math.lyx, SO(3) section
|
||||||
Point3 Rot3::unrotate(const Point3& p,
|
Point3 Rot3::unrotate(const Point3& p,
|
||||||
boost::optional<Matrix&> H1, boost::optional<Matrix&> H2) const {
|
boost::optional<Matrix&> H1, boost::optional<Matrix&> H2) const {
|
||||||
Matrix3 Rt(transpose());
|
const Matrix3& Rt = transpose();
|
||||||
Point3 q(Rt * p.vector()); // q = Rt*p
|
Point3 q(Rt * p.vector()); // q = Rt*p
|
||||||
const double wx = q.x(), wy = q.y(), wz = q.z();
|
const double wx = q.x(), wy = q.y(), wz = q.z();
|
||||||
if (H1) {
|
if (H1) {
|
||||||
|
|
|
@ -70,6 +70,12 @@ namespace gtsam {
|
||||||
Matrix3 rot_;
|
Matrix3 rot_;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* transpose() is used millions of times in linearize, so cache it
|
||||||
|
* This also avoids multiple expensive conversions in the quaternion case
|
||||||
|
*/
|
||||||
|
mutable boost::optional<Matrix3> transpose_; ///< Cached R_.transpose()
|
||||||
|
|
||||||
public:
|
public:
|
||||||
|
|
||||||
/// @name Constructors and named constructors
|
/// @name Constructors and named constructors
|
||||||
|
@ -368,8 +374,15 @@ namespace gtsam {
|
||||||
/** return 3*3 rotation matrix */
|
/** return 3*3 rotation matrix */
|
||||||
Matrix3 matrix() const;
|
Matrix3 matrix() const;
|
||||||
|
|
||||||
/** return 3*3 transpose (inverse) rotation matrix */
|
/**
|
||||||
Matrix3 transpose() const;
|
* Return 3*3 transpose (inverse) rotation matrix
|
||||||
|
* Actually returns cached transpose, or computes it if not yet done
|
||||||
|
*/
|
||||||
|
const Matrix3& transpose() const {
|
||||||
|
if (!transpose_)
|
||||||
|
transpose_.reset(inverse().matrix());
|
||||||
|
return *transpose_;
|
||||||
|
}
|
||||||
|
|
||||||
/// @deprecated, this is base 1, and was just confusing
|
/// @deprecated, this is base 1, and was just confusing
|
||||||
Point3 column(int index) const;
|
Point3 column(int index) const;
|
||||||
|
@ -439,6 +452,7 @@ namespace gtsam {
|
||||||
GTSAM_EXPORT friend std::ostream &operator<<(std::ostream &os, const Rot3& p);
|
GTSAM_EXPORT friend std::ostream &operator<<(std::ostream &os, const Rot3& p);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
||||||
/** Serialization function */
|
/** Serialization function */
|
||||||
friend class boost::serialization::access;
|
friend class boost::serialization::access;
|
||||||
template<class ARCHIVE>
|
template<class ARCHIVE>
|
||||||
|
@ -463,6 +477,7 @@ namespace gtsam {
|
||||||
ar & boost::serialization::make_nvp("z", quaternion_.z());
|
ar & boost::serialization::make_nvp("z", quaternion_.z());
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// @}
|
/// @}
|
||||||
|
|
|
@ -295,11 +295,6 @@ Matrix3 Rot3::matrix() const {
|
||||||
return rot_;
|
return rot_;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
|
||||||
Matrix3 Rot3::transpose() const {
|
|
||||||
return rot_.transpose();
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
Point3 Rot3::r1() const { return Point3(rot_.col(0)); }
|
Point3 Rot3::r1() const { return Point3(rot_.col(0)); }
|
||||||
|
|
||||||
|
|
|
@ -156,9 +156,6 @@ namespace gtsam {
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
Matrix3 Rot3::matrix() const {return quaternion_.toRotationMatrix();}
|
Matrix3 Rot3::matrix() const {return quaternion_.toRotationMatrix();}
|
||||||
|
|
||||||
/* ************************************************************************* */
|
|
||||||
Matrix3 Rot3::transpose() const {return quaternion_.toRotationMatrix().transpose();}
|
|
||||||
|
|
||||||
/* ************************************************************************* */
|
/* ************************************************************************* */
|
||||||
Point3 Rot3::r1() const { return Point3(quaternion_.toRotationMatrix().col(0)); }
|
Point3 Rot3::r1() const { return Point3(quaternion_.toRotationMatrix().col(0)); }
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue