Merge pull request #243 from borglab/feature/rot3-angle
Axis-Angle (in radians) representation for Rot3 matricesrelease/4.3a0
commit
2c44ee459b
4
gtsam.h
4
gtsam.h
|
@ -639,6 +639,7 @@ class Rot3 {
|
|||
static gtsam::Rot3 Roll(double t); // positive roll is to right (increasing yaw in aircraft)
|
||||
static gtsam::Rot3 Ypr(double y, double p, double r);
|
||||
static gtsam::Rot3 Quaternion(double w, double x, double y, double z);
|
||||
static gtsam::Rot3 AxisAngle(const gtsam::Point3& axis, double angle);
|
||||
static gtsam::Rot3 Rodrigues(Vector v);
|
||||
static gtsam::Rot3 Rodrigues(double wx, double wy, double wz);
|
||||
static gtsam::Rot3 ClosestTo(const Matrix M);
|
||||
|
@ -674,6 +675,7 @@ class Rot3 {
|
|||
double roll() const;
|
||||
double pitch() const;
|
||||
double yaw() const;
|
||||
pair<gtsam::Unit3, double> axisAngle() const;
|
||||
// Vector toQuaternion() const; // FIXME: Can't cast to Vector properly
|
||||
Vector quaternion() const;
|
||||
gtsam::Rot3 slerp(double t, const gtsam::Rot3& other) const;
|
||||
|
@ -1310,7 +1312,7 @@ class SymbolicBayesTree {
|
|||
// class SymbolicBayesTreeClique {
|
||||
// BayesTreeClique();
|
||||
// BayesTreeClique(CONDITIONAL* conditional);
|
||||
// // BayesTreeClique(const std::pair<typename ConditionalType::shared_ptr, typename ConditionalType::FactorType::shared_ptr>& result) : Base(result) {}
|
||||
// // BayesTreeClique(const pair<typename ConditionalType::shared_ptr, typename ConditionalType::FactorType::shared_ptr>& result) : Base(result) {}
|
||||
//
|
||||
// bool equals(const This& other, double tol) const;
|
||||
// void print(string s) const;
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
* @author Christian Potthast
|
||||
* @author Frank Dellaert
|
||||
* @author Richard Roberts
|
||||
* @author Varun Agrawal
|
||||
*/
|
||||
|
||||
#include <gtsam/geometry/Rot3.h>
|
||||
|
@ -185,6 +186,12 @@ Vector Rot3::quaternion() const {
|
|||
return v;
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
pair<Unit3, double> Rot3::axisAngle() const {
|
||||
const Vector3 omega = Rot3::Logmap(*this);
|
||||
return std::pair<Unit3, double>(Unit3(omega), omega.norm());
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
Matrix3 Rot3::ExpmapDerivative(const Vector3& x) {
|
||||
return SO3::ExpmapDerivative(x);
|
||||
|
|
|
@ -17,6 +17,7 @@
|
|||
* @author Frank Dellaert
|
||||
* @author Richard Roberts
|
||||
* @author Luca Carlone
|
||||
* @author Varun Agrawal
|
||||
*/
|
||||
// \callgraph
|
||||
|
||||
|
@ -194,7 +195,7 @@ namespace gtsam {
|
|||
|
||||
/**
|
||||
* Convert from axis/angle representation
|
||||
* @param axisw is the rotation axis, unit length
|
||||
* @param axis is the rotation axis, unit length
|
||||
* @param angle rotation angle
|
||||
* @return incremental rotation
|
||||
*/
|
||||
|
@ -429,7 +430,7 @@ namespace gtsam {
|
|||
|
||||
/**
|
||||
* Use RQ to calculate roll-pitch-yaw angle representation
|
||||
* @return a vector containing ypr s.t. R = Rot3::Ypr(y,p,r)
|
||||
* @return a vector containing rpy s.t. R = Rot3::Ypr(y,p,r)
|
||||
*/
|
||||
Vector3 rpy() const;
|
||||
|
||||
|
@ -461,6 +462,16 @@ namespace gtsam {
|
|||
/// @name Advanced Interface
|
||||
/// @{
|
||||
|
||||
/**
|
||||
* Compute the Euler axis and angle (in radians) representation
|
||||
* of this rotation.
|
||||
* The angle is in the range [0, π]. If the angle is not in the range,
|
||||
* the axis is flipped around accordingly so that the returned angle is
|
||||
* within the specified range.
|
||||
* @return pair consisting of Unit3 axis and angle in radians
|
||||
*/
|
||||
std::pair<Unit3, double> axisAngle() const;
|
||||
|
||||
/** Compute the quaternion representation of this rotation.
|
||||
* @return The quaternion
|
||||
*/
|
||||
|
|
|
@ -14,6 +14,7 @@
|
|||
* @brief Unit tests for Rot3 class - common between Matrix and Quaternion
|
||||
* @author Alireza Fathi
|
||||
* @author Frank Dellaert
|
||||
* @author Varun Agrawal
|
||||
*/
|
||||
|
||||
#include <gtsam/geometry/Point3.h>
|
||||
|
@ -661,6 +662,65 @@ TEST(Rot3, ClosestTo) {
|
|||
EXPECT(assert_equal(expected, actual.matrix(), 1e-6));
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
TEST(Rot3, axisAngle) {
|
||||
Unit3 actualAxis;
|
||||
double actualAngle;
|
||||
|
||||
// not a lambda as otherwise we can't trace error easily
|
||||
#define CHECK_AXIS_ANGLE(expectedAxis, expectedAngle, rotation) \
|
||||
std::tie(actualAxis, actualAngle) = rotation.axisAngle(); \
|
||||
EXPECT(assert_equal(expectedAxis, actualAxis, 1e-9)); \
|
||||
EXPECT_DOUBLES_EQUAL(expectedAngle, actualAngle, 1e-9); \
|
||||
EXPECT(assert_equal(rotation, Rot3::AxisAngle(expectedAxis, expectedAngle)))
|
||||
|
||||
// CHECK R defined at top = Rot3::Rodrigues(0.1, 0.4, 0.2)
|
||||
Vector3 omega(0.1, 0.4, 0.2);
|
||||
Unit3 axis(omega), _axis(-omega);
|
||||
CHECK_AXIS_ANGLE(axis, omega.norm(), R);
|
||||
|
||||
// rotate by 90
|
||||
CHECK_AXIS_ANGLE(Unit3(1, 0, 0), M_PI_2, Rot3::Ypr(0, 0, M_PI_2))
|
||||
CHECK_AXIS_ANGLE(Unit3(0, 1, 0), M_PI_2, Rot3::Ypr(0, M_PI_2, 0))
|
||||
CHECK_AXIS_ANGLE(Unit3(0, 0, 1), M_PI_2, Rot3::Ypr(M_PI_2, 0, 0))
|
||||
CHECK_AXIS_ANGLE(axis, M_PI_2, Rot3::AxisAngle(axis, M_PI_2))
|
||||
|
||||
// rotate by -90
|
||||
CHECK_AXIS_ANGLE(Unit3(-1, 0, 0), M_PI_2, Rot3::Ypr(0, 0, -M_PI_2))
|
||||
CHECK_AXIS_ANGLE(Unit3(0, -1, 0), M_PI_2, Rot3::Ypr(0, -M_PI_2, 0))
|
||||
CHECK_AXIS_ANGLE(Unit3(0, 0, -1), M_PI_2, Rot3::Ypr(-M_PI_2, 0, 0))
|
||||
CHECK_AXIS_ANGLE(_axis, M_PI_2, Rot3::AxisAngle(axis, -M_PI_2))
|
||||
|
||||
// rotate by 270
|
||||
const double theta270 = M_PI + M_PI / 2;
|
||||
CHECK_AXIS_ANGLE(Unit3(-1, 0, 0), M_PI_2, Rot3::Ypr(0, 0, theta270))
|
||||
CHECK_AXIS_ANGLE(Unit3(0, -1, 0), M_PI_2, Rot3::Ypr(0, theta270, 0))
|
||||
CHECK_AXIS_ANGLE(Unit3(0, 0, -1), M_PI_2, Rot3::Ypr(theta270, 0, 0))
|
||||
CHECK_AXIS_ANGLE(_axis, M_PI_2, Rot3::AxisAngle(axis, theta270))
|
||||
|
||||
// rotate by -270
|
||||
const double theta_270 = -(M_PI + M_PI / 2); // 90 (or -270) degrees
|
||||
CHECK_AXIS_ANGLE(Unit3(1, 0, 0), M_PI_2, Rot3::Ypr(0, 0, theta_270))
|
||||
CHECK_AXIS_ANGLE(Unit3(0, 1, 0), M_PI_2, Rot3::Ypr(0, theta_270, 0))
|
||||
CHECK_AXIS_ANGLE(Unit3(0, 0, 1), M_PI_2, Rot3::Ypr(theta_270, 0, 0))
|
||||
CHECK_AXIS_ANGLE(axis, M_PI_2, Rot3::AxisAngle(axis, theta_270))
|
||||
|
||||
const double theta195 = 195 * M_PI / 180;
|
||||
const double theta165 = 165 * M_PI / 180;
|
||||
|
||||
/// Non-trivial angle 165
|
||||
CHECK_AXIS_ANGLE(Unit3(1, 0, 0), theta165, Rot3::Ypr(0, 0, theta165))
|
||||
CHECK_AXIS_ANGLE(Unit3(0, 1, 0), theta165, Rot3::Ypr(0, theta165, 0))
|
||||
CHECK_AXIS_ANGLE(Unit3(0, 0, 1), theta165, Rot3::Ypr(theta165, 0, 0))
|
||||
CHECK_AXIS_ANGLE(axis, theta165, Rot3::AxisAngle(axis, theta165))
|
||||
|
||||
/// Non-trivial angle 195
|
||||
CHECK_AXIS_ANGLE(Unit3(-1, 0, 0), theta165, Rot3::Ypr(0, 0, theta195))
|
||||
CHECK_AXIS_ANGLE(Unit3(0, -1, 0), theta165, Rot3::Ypr(0, theta195, 0))
|
||||
CHECK_AXIS_ANGLE(Unit3(0, 0, -1), theta165, Rot3::Ypr(theta195, 0, 0))
|
||||
CHECK_AXIS_ANGLE(_axis, theta165, Rot3::AxisAngle(axis, theta195))
|
||||
}
|
||||
|
||||
/* ************************************************************************* */
|
||||
int main() {
|
||||
TestResult tr;
|
||||
|
|
Loading…
Reference in New Issue