2009-08-29 09:24:26 +08:00
|
|
|
/**
|
|
|
|
* @file Pose2.h
|
2009-12-14 11:02:05 +08:00
|
|
|
* @brief 2D Pose
|
2009-08-29 09:24:26 +08:00
|
|
|
* @author: Frank Dellaert
|
2009-12-14 11:02:05 +08:00
|
|
|
* @author: Richard Roberts
|
2009-08-29 09:24:26 +08:00
|
|
|
*/
|
|
|
|
|
|
|
|
// \callgraph
|
|
|
|
|
|
|
|
#pragma once
|
|
|
|
|
2010-01-12 10:08:41 +08:00
|
|
|
#include <boost/optional.hpp>
|
2010-08-20 01:23:19 +08:00
|
|
|
#include <gtsam/base/Matrix.h>
|
|
|
|
#include <gtsam/base/Testable.h>
|
|
|
|
#include <gtsam/base/Lie.h>
|
|
|
|
#include <gtsam/geometry/Point2.h>
|
|
|
|
#include <gtsam/geometry/Rot2.h>
|
2009-08-29 09:24:26 +08:00
|
|
|
|
|
|
|
namespace gtsam {
|
|
|
|
|
2009-12-14 11:02:05 +08:00
|
|
|
/**
|
2009-12-15 08:00:02 +08:00
|
|
|
* A 2D pose (Point2,Rot2)
|
2009-12-14 11:02:05 +08:00
|
|
|
*/
|
2010-01-10 07:15:06 +08:00
|
|
|
class Pose2: Testable<Pose2>, public Lie<Pose2> {
|
2009-12-15 08:00:02 +08:00
|
|
|
private:
|
|
|
|
Rot2 r_;
|
2010-03-20 04:32:19 +08:00
|
|
|
Point2 t_;
|
2009-12-15 08:00:02 +08:00
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
|
|
/** default constructor = origin */
|
Rot2 "named constructors" (http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.8):
/** Named constructor from angle == exponential map at identity */
static Rot2 fromAngle(double theta) { return Rot2(cos(theta),sin(theta));}
/** Named constructor from cos(theta),sin(theta) pair, will *not* normalize! */
static Rot2 fromCosSin(double c, double s);
/** Named constructor that behaves as atan2, i.e., y,x order (!) and normalizes */
static Rot2 atan2(double y, double x);
which are a bit more verbose, but at least won't cause hours of bug-tracking :-(
I also made most compose, inverse, and rotate functions into methods, with the global functions mostly calling the methods. Methods have privileged access to members and hence are typically much more readable.
2010-03-03 11:31:53 +08:00
|
|
|
Pose2() {} // default is origin
|
2009-12-15 08:00:02 +08:00
|
|
|
|
|
|
|
/** copy constructor */
|
2010-03-20 04:32:19 +08:00
|
|
|
Pose2(const Pose2& pose) : r_(pose.r_), t_(pose.t_) {}
|
2009-12-15 08:00:02 +08:00
|
|
|
|
|
|
|
/**
|
|
|
|
* construct from (x,y,theta)
|
|
|
|
* @param x x coordinate
|
|
|
|
* @param y y coordinate
|
|
|
|
* @param theta angle with positive X-axis
|
|
|
|
*/
|
Rot2 "named constructors" (http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.8):
/** Named constructor from angle == exponential map at identity */
static Rot2 fromAngle(double theta) { return Rot2(cos(theta),sin(theta));}
/** Named constructor from cos(theta),sin(theta) pair, will *not* normalize! */
static Rot2 fromCosSin(double c, double s);
/** Named constructor that behaves as atan2, i.e., y,x order (!) and normalizes */
static Rot2 atan2(double y, double x);
which are a bit more verbose, but at least won't cause hours of bug-tracking :-(
I also made most compose, inverse, and rotate functions into methods, with the global functions mostly calling the methods. Methods have privileged access to members and hence are typically much more readable.
2010-03-03 11:31:53 +08:00
|
|
|
Pose2(double x, double y, double theta) :
|
2010-03-20 04:32:19 +08:00
|
|
|
r_(Rot2::fromAngle(theta)), t_(x, y) {
|
Rot2 "named constructors" (http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.8):
/** Named constructor from angle == exponential map at identity */
static Rot2 fromAngle(double theta) { return Rot2(cos(theta),sin(theta));}
/** Named constructor from cos(theta),sin(theta) pair, will *not* normalize! */
static Rot2 fromCosSin(double c, double s);
/** Named constructor that behaves as atan2, i.e., y,x order (!) and normalizes */
static Rot2 atan2(double y, double x);
which are a bit more verbose, but at least won't cause hours of bug-tracking :-(
I also made most compose, inverse, and rotate functions into methods, with the global functions mostly calling the methods. Methods have privileged access to members and hence are typically much more readable.
2010-03-03 11:31:53 +08:00
|
|
|
}
|
2009-12-15 08:00:02 +08:00
|
|
|
|
|
|
|
/** construct from rotation and translation */
|
Rot2 "named constructors" (http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.8):
/** Named constructor from angle == exponential map at identity */
static Rot2 fromAngle(double theta) { return Rot2(cos(theta),sin(theta));}
/** Named constructor from cos(theta),sin(theta) pair, will *not* normalize! */
static Rot2 fromCosSin(double c, double s);
/** Named constructor that behaves as atan2, i.e., y,x order (!) and normalizes */
static Rot2 atan2(double y, double x);
which are a bit more verbose, but at least won't cause hours of bug-tracking :-(
I also made most compose, inverse, and rotate functions into methods, with the global functions mostly calling the methods. Methods have privileged access to members and hence are typically much more readable.
2010-03-03 11:31:53 +08:00
|
|
|
Pose2(double theta, const Point2& t) :
|
2010-03-20 04:32:19 +08:00
|
|
|
r_(Rot2::fromAngle(theta)), t_(t) {
|
Rot2 "named constructors" (http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.8):
/** Named constructor from angle == exponential map at identity */
static Rot2 fromAngle(double theta) { return Rot2(cos(theta),sin(theta));}
/** Named constructor from cos(theta),sin(theta) pair, will *not* normalize! */
static Rot2 fromCosSin(double c, double s);
/** Named constructor that behaves as atan2, i.e., y,x order (!) and normalizes */
static Rot2 atan2(double y, double x);
which are a bit more verbose, but at least won't cause hours of bug-tracking :-(
I also made most compose, inverse, and rotate functions into methods, with the global functions mostly calling the methods. Methods have privileged access to members and hence are typically much more readable.
2010-03-03 11:31:53 +08:00
|
|
|
}
|
2010-03-20 04:32:19 +08:00
|
|
|
Pose2(const Rot2& r, const Point2& t) : r_(r), t_(t) {}
|
2009-12-15 08:00:02 +08:00
|
|
|
|
Rot2 "named constructors" (http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.8):
/** Named constructor from angle == exponential map at identity */
static Rot2 fromAngle(double theta) { return Rot2(cos(theta),sin(theta));}
/** Named constructor from cos(theta),sin(theta) pair, will *not* normalize! */
static Rot2 fromCosSin(double c, double s);
/** Named constructor that behaves as atan2, i.e., y,x order (!) and normalizes */
static Rot2 atan2(double y, double x);
which are a bit more verbose, but at least won't cause hours of bug-tracking :-(
I also made most compose, inverse, and rotate functions into methods, with the global functions mostly calling the methods. Methods have privileged access to members and hence are typically much more readable.
2010-03-03 11:31:53 +08:00
|
|
|
/** Constructor from 3*3 matrix */
|
|
|
|
Pose2(const Matrix &T) :
|
2010-03-03 13:34:08 +08:00
|
|
|
r_(Rot2::atan2(T(1, 0), T(0, 0))), t_(T(0, 2), T(1, 2)) {}
|
Rot2 "named constructors" (http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.8):
/** Named constructor from angle == exponential map at identity */
static Rot2 fromAngle(double theta) { return Rot2(cos(theta),sin(theta));}
/** Named constructor from cos(theta),sin(theta) pair, will *not* normalize! */
static Rot2 fromCosSin(double c, double s);
/** Named constructor that behaves as atan2, i.e., y,x order (!) and normalizes */
static Rot2 atan2(double y, double x);
which are a bit more verbose, but at least won't cause hours of bug-tracking :-(
I also made most compose, inverse, and rotate functions into methods, with the global functions mostly calling the methods. Methods have privileged access to members and hence are typically much more readable.
2010-03-03 11:31:53 +08:00
|
|
|
|
2009-12-15 08:00:02 +08:00
|
|
|
/** print with optional string */
|
|
|
|
void print(const std::string& s = "") const;
|
|
|
|
|
|
|
|
/** assert equality up to a tolerance */
|
|
|
|
bool equals(const Pose2& pose, double tol = 1e-9) const;
|
|
|
|
|
2010-02-19 00:27:01 +08:00
|
|
|
/** return transformation matrix */
|
|
|
|
Matrix matrix() const;
|
|
|
|
|
2009-12-15 08:00:02 +08:00
|
|
|
/** get functions for x, y, theta */
|
2010-02-24 14:14:43 +08:00
|
|
|
inline double x() const { return t_.x(); }
|
|
|
|
inline double y() const { return t_.y(); }
|
|
|
|
inline double theta() const { return r_.theta(); }
|
|
|
|
|
|
|
|
inline const Point2& t() const { return t_; }
|
|
|
|
inline const Rot2& r() const { return r_; }
|
2009-12-15 08:00:02 +08:00
|
|
|
|
2010-01-20 10:28:23 +08:00
|
|
|
static inline size_t dim() { return 3; };
|
|
|
|
|
2010-03-12 22:20:29 +08:00
|
|
|
private:
|
|
|
|
// Serialization function
|
|
|
|
friend class boost::serialization::access;
|
|
|
|
template<class Archive>
|
|
|
|
void serialize(Archive & ar, const unsigned int version) {
|
|
|
|
ar & BOOST_SERIALIZATION_NVP(t_);
|
|
|
|
ar & BOOST_SERIALIZATION_NVP(r_);
|
|
|
|
}
|
2010-01-08 08:40:17 +08:00
|
|
|
}; // Pose2
|
2009-12-18 08:09:54 +08:00
|
|
|
|
Rot2 "named constructors" (http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.8):
/** Named constructor from angle == exponential map at identity */
static Rot2 fromAngle(double theta) { return Rot2(cos(theta),sin(theta));}
/** Named constructor from cos(theta),sin(theta) pair, will *not* normalize! */
static Rot2 fromCosSin(double c, double s);
/** Named constructor that behaves as atan2, i.e., y,x order (!) and normalizes */
static Rot2 atan2(double y, double x);
which are a bit more verbose, but at least won't cause hours of bug-tracking :-(
I also made most compose, inverse, and rotate functions into methods, with the global functions mostly calling the methods. Methods have privileged access to members and hence are typically much more readable.
2010-03-03 11:31:53 +08:00
|
|
|
/** print using member print function, currently used by LieConfig */
|
|
|
|
inline void print(const Pose2& obj, const std::string& str = "") { obj.print(str); }
|
2009-12-15 08:00:02 +08:00
|
|
|
|
2010-01-08 08:40:17 +08:00
|
|
|
/** return DOF, dimensionality of tangent space = 3 */
|
|
|
|
inline size_t dim(const Pose2&) { return 3; }
|
2009-12-15 08:00:02 +08:00
|
|
|
|
Rot2 "named constructors" (http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.8):
/** Named constructor from angle == exponential map at identity */
static Rot2 fromAngle(double theta) { return Rot2(cos(theta),sin(theta));}
/** Named constructor from cos(theta),sin(theta) pair, will *not* normalize! */
static Rot2 fromCosSin(double c, double s);
/** Named constructor that behaves as atan2, i.e., y,x order (!) and normalizes */
static Rot2 atan2(double y, double x);
which are a bit more verbose, but at least won't cause hours of bug-tracking :-(
I also made most compose, inverse, and rotate functions into methods, with the global functions mostly calling the methods. Methods have privileged access to members and hence are typically much more readable.
2010-03-03 11:31:53 +08:00
|
|
|
/**
|
|
|
|
* Exponential map from se(2) to SE(2)
|
|
|
|
*/
|
|
|
|
template<> Pose2 expmap(const Vector& v);
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Inverse of exponential map, from SE(2) to se(2)
|
|
|
|
*/
|
|
|
|
Vector logmap(const Pose2& p);
|
|
|
|
|
2010-02-28 17:10:39 +08:00
|
|
|
/**
|
|
|
|
* Calculate Adjoint map
|
|
|
|
* Ad_pose is 3*3 matrix that when applied to twist xi, returns Ad_pose(xi)
|
|
|
|
*/
|
|
|
|
Matrix AdjointMap(const Pose2& p);
|
2010-03-05 11:02:23 +08:00
|
|
|
inline Vector Adjoint(const Pose2& p, const Vector& xi) { return AdjointMap(p)*xi;}
|
2010-02-28 17:10:39 +08:00
|
|
|
|
Rot2 "named constructors" (http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.8):
/** Named constructor from angle == exponential map at identity */
static Rot2 fromAngle(double theta) { return Rot2(cos(theta),sin(theta));}
/** Named constructor from cos(theta),sin(theta) pair, will *not* normalize! */
static Rot2 fromCosSin(double c, double s);
/** Named constructor that behaves as atan2, i.e., y,x order (!) and normalizes */
static Rot2 atan2(double y, double x);
which are a bit more verbose, but at least won't cause hours of bug-tracking :-(
I also made most compose, inverse, and rotate functions into methods, with the global functions mostly calling the methods. Methods have privileged access to members and hence are typically much more readable.
2010-03-03 11:31:53 +08:00
|
|
|
/**
|
|
|
|
* wedge for SE(2):
|
|
|
|
* @param xi 3-dim twist (v,omega) where
|
|
|
|
* omega is angular velocity
|
|
|
|
* v (vx,vy) = 2D velocity
|
|
|
|
* @return xihat, 3*3 element of Lie algebra that can be exponentiated
|
|
|
|
*/
|
|
|
|
inline Matrix wedge(double vx, double vy, double w) {
|
|
|
|
return Matrix_(3,3,
|
|
|
|
0.,-w, vx,
|
|
|
|
w, 0., vy,
|
|
|
|
0., 0., 0.);
|
|
|
|
}
|
|
|
|
|
|
|
|
template <>
|
|
|
|
inline Matrix wedge<Pose2>(const Vector& xi) {
|
|
|
|
return wedge(xi(0),xi(1),xi(2));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* inverse transformation
|
|
|
|
*/
|
2010-02-28 17:10:39 +08:00
|
|
|
Pose2 inverse(const Pose2& pose);
|
|
|
|
Matrix Dinverse(const Pose2& pose);
|
2009-12-15 08:00:02 +08:00
|
|
|
|
Rot2 "named constructors" (http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.8):
/** Named constructor from angle == exponential map at identity */
static Rot2 fromAngle(double theta) { return Rot2(cos(theta),sin(theta));}
/** Named constructor from cos(theta),sin(theta) pair, will *not* normalize! */
static Rot2 fromCosSin(double c, double s);
/** Named constructor that behaves as atan2, i.e., y,x order (!) and normalizes */
static Rot2 atan2(double y, double x);
which are a bit more verbose, but at least won't cause hours of bug-tracking :-(
I also made most compose, inverse, and rotate functions into methods, with the global functions mostly calling the methods. Methods have privileged access to members and hence are typically much more readable.
2010-03-03 11:31:53 +08:00
|
|
|
/**
|
|
|
|
* compose this transformation onto another (first p1 and then p2)
|
|
|
|
*/
|
2010-05-24 13:40:59 +08:00
|
|
|
inline Pose2 operator*(const Pose2& p1, const Pose2& p2) {
|
|
|
|
return Pose2(p1.r()*p2.r(), p1.t() + p1.r()*p2.t()); }
|
|
|
|
inline Pose2 compose(const Pose2& p1, const Pose2& p2) { return p1*p2; }
|
|
|
|
Pose2 compose(const Pose2& p1, const Pose2& p2,
|
|
|
|
boost::optional<Matrix&> H1,
|
|
|
|
boost::optional<Matrix&> H2 = boost::none);
|
2010-02-26 18:55:41 +08:00
|
|
|
Matrix Dcompose1(const Pose2& p1, const Pose2& p2);
|
|
|
|
Matrix Dcompose2(const Pose2& p1, const Pose2& p2);
|
2009-12-15 08:00:02 +08:00
|
|
|
|
Rot2 "named constructors" (http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.8):
/** Named constructor from angle == exponential map at identity */
static Rot2 fromAngle(double theta) { return Rot2(cos(theta),sin(theta));}
/** Named constructor from cos(theta),sin(theta) pair, will *not* normalize! */
static Rot2 fromCosSin(double c, double s);
/** Named constructor that behaves as atan2, i.e., y,x order (!) and normalizes */
static Rot2 atan2(double y, double x);
which are a bit more verbose, but at least won't cause hours of bug-tracking :-(
I also made most compose, inverse, and rotate functions into methods, with the global functions mostly calling the methods. Methods have privileged access to members and hence are typically much more readable.
2010-03-03 11:31:53 +08:00
|
|
|
/**
|
|
|
|
* Return point coordinates in pose coordinate frame
|
|
|
|
*/
|
|
|
|
inline Point2 transform_to(const Pose2& pose, const Point2& point)
|
|
|
|
{ return unrotate(pose.r(), point - pose.t());}
|
2010-01-12 10:08:41 +08:00
|
|
|
Point2 transform_to(const Pose2& pose, const Point2& point,
|
2010-03-02 10:27:09 +08:00
|
|
|
boost::optional<Matrix&> H1, boost::optional<Matrix&> H2);
|
2009-12-15 08:00:02 +08:00
|
|
|
|
Rot2 "named constructors" (http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.8):
/** Named constructor from angle == exponential map at identity */
static Rot2 fromAngle(double theta) { return Rot2(cos(theta),sin(theta));}
/** Named constructor from cos(theta),sin(theta) pair, will *not* normalize! */
static Rot2 fromCosSin(double c, double s);
/** Named constructor that behaves as atan2, i.e., y,x order (!) and normalizes */
static Rot2 atan2(double y, double x);
which are a bit more verbose, but at least won't cause hours of bug-tracking :-(
I also made most compose, inverse, and rotate functions into methods, with the global functions mostly calling the methods. Methods have privileged access to members and hence are typically much more readable.
2010-03-03 11:31:53 +08:00
|
|
|
/**
|
|
|
|
* Return point coordinates in global frame
|
|
|
|
*/
|
|
|
|
inline Point2 transform_from(const Pose2& pose, const Point2& point)
|
|
|
|
{ return rotate(pose.r(), point) + pose.t();}
|
2010-02-28 16:51:43 +08:00
|
|
|
Point2 transform_from(const Pose2& pose, const Point2& point,
|
2010-03-02 10:27:09 +08:00
|
|
|
boost::optional<Matrix&> H1, boost::optional<Matrix&> H2);
|
Rot2 "named constructors" (http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.8):
/** Named constructor from angle == exponential map at identity */
static Rot2 fromAngle(double theta) { return Rot2(cos(theta),sin(theta));}
/** Named constructor from cos(theta),sin(theta) pair, will *not* normalize! */
static Rot2 fromCosSin(double c, double s);
/** Named constructor that behaves as atan2, i.e., y,x order (!) and normalizes */
static Rot2 atan2(double y, double x);
which are a bit more verbose, but at least won't cause hours of bug-tracking :-(
I also made most compose, inverse, and rotate functions into methods, with the global functions mostly calling the methods. Methods have privileged access to members and hence are typically much more readable.
2010-03-03 11:31:53 +08:00
|
|
|
inline Point2 operator*(const Pose2& pose, const Point2& point)
|
|
|
|
{ return transform_from(pose, point);}
|
2009-12-15 08:00:02 +08:00
|
|
|
|
Rot2 "named constructors" (http://www.parashift.com/c++-faq-lite/ctors.html#faq-10.8):
/** Named constructor from angle == exponential map at identity */
static Rot2 fromAngle(double theta) { return Rot2(cos(theta),sin(theta));}
/** Named constructor from cos(theta),sin(theta) pair, will *not* normalize! */
static Rot2 fromCosSin(double c, double s);
/** Named constructor that behaves as atan2, i.e., y,x order (!) and normalizes */
static Rot2 atan2(double y, double x);
which are a bit more verbose, but at least won't cause hours of bug-tracking :-(
I also made most compose, inverse, and rotate functions into methods, with the global functions mostly calling the methods. Methods have privileged access to members and hence are typically much more readable.
2010-03-03 11:31:53 +08:00
|
|
|
/**
|
|
|
|
* Return relative pose between p1 and p2, in p1 coordinate frame
|
|
|
|
*/
|
2010-01-16 09:16:59 +08:00
|
|
|
Pose2 between(const Pose2& p1, const Pose2& p2,
|
2010-03-02 10:27:09 +08:00
|
|
|
boost::optional<Matrix&> H1, boost::optional<Matrix&> H2);
|
2010-01-08 08:40:17 +08:00
|
|
|
|
2010-01-16 09:16:59 +08:00
|
|
|
/**
|
|
|
|
* Calculate bearing to a landmark
|
|
|
|
* @param pose 2D pose of robot
|
|
|
|
* @param point 2D location of landmark
|
|
|
|
* @return 2D rotation \in SO(2)
|
|
|
|
*/
|
|
|
|
Rot2 bearing(const Pose2& pose, const Point2& point);
|
|
|
|
Rot2 bearing(const Pose2& pose, const Point2& point,
|
|
|
|
boost::optional<Matrix&> H1, boost::optional<Matrix&> H2);
|
2010-01-10 07:15:06 +08:00
|
|
|
|
2010-01-16 09:16:59 +08:00
|
|
|
/**
|
|
|
|
* Calculate range to a landmark
|
|
|
|
* @param pose 2D pose of robot
|
|
|
|
* @param point 2D location of landmark
|
|
|
|
* @return range (double)
|
|
|
|
*/
|
|
|
|
double range(const Pose2& pose, const Point2& point);
|
|
|
|
double range(const Pose2& pose, const Point2& point,
|
|
|
|
boost::optional<Matrix&> H1, boost::optional<Matrix&> H2);
|
2010-01-10 07:15:06 +08:00
|
|
|
|
2009-08-29 09:24:26 +08:00
|
|
|
} // namespace gtsam
|
2010-01-10 07:15:06 +08:00
|
|
|
|