| 
									
										
										
										
											2012-05-04 01:03:16 +08:00
										 |  |  | /**
 | 
					
						
							|  |  |  |  * @file PoseRTV.cpp | 
					
						
							|  |  |  |  * @author Alex Cunningham | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-05-04 01:03:25 +08:00
										 |  |  | #include <gtsam_unstable/dynamics/PoseRTV.h>
 | 
					
						
							| 
									
										
										
										
											2015-05-26 14:50:00 +08:00
										 |  |  | #include <gtsam/geometry/Pose2.h>
 | 
					
						
							|  |  |  | #include <gtsam/base/Vector.h>
 | 
					
						
							| 
									
										
										
										
											2012-05-04 01:03:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace gtsam { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | using namespace std; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-04-16 08:01:22 +08:00
										 |  |  | static const Vector kGravity = Vector::Unit(3,2)*9.81; | 
					
						
							| 
									
										
										
										
											2012-05-04 01:03:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | double bound(double a, double min, double max) { | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   if (a < min) return min; | 
					
						
							|  |  |  |   else if (a > max) return max; | 
					
						
							|  |  |  |   else return a; | 
					
						
							| 
									
										
										
										
											2012-05-04 01:03:16 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2015-05-26 08:13:08 +08:00
										 |  |  | PoseRTV::PoseRTV(double roll, double pitch, double yaw, double x, double y, | 
					
						
							|  |  |  |     double z, double vx, double vy, double vz) : | 
					
						
							|  |  |  |     Base(Pose3(Rot3::RzRyRx(roll, pitch, yaw), Point3(x, y, z)), | 
					
						
							|  |  |  |         Velocity3(vx, vy, vz)) { | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2012-05-04 01:03:16 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2015-05-26 08:13:08 +08:00
										 |  |  | PoseRTV::PoseRTV(const Vector& rtv) : | 
					
						
							|  |  |  |     Base(Pose3(Rot3::RzRyRx(rtv.head(3)), Point3(rtv.segment(3, 3))), | 
					
						
							|  |  |  |         Velocity3(rtv.tail(3))) { | 
					
						
							| 
									
										
										
										
											2012-05-04 01:03:16 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | Vector PoseRTV::vector() const { | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   Vector rtv(9); | 
					
						
							| 
									
										
										
										
											2015-05-26 08:13:08 +08:00
										 |  |  |   rtv.head(3) = rotation().xyz(); | 
					
						
							| 
									
										
										
										
											2016-02-12 11:03:11 +08:00
										 |  |  |   rtv.segment(3,3) = translation(); | 
					
						
							| 
									
										
										
										
											2015-07-18 08:36:29 +08:00
										 |  |  |   rtv.tail(3) = velocity(); | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   return rtv; | 
					
						
							| 
									
										
										
										
											2012-05-04 01:03:16 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | bool PoseRTV::equals(const PoseRTV& other, double tol) const { | 
					
						
							| 
									
										
										
										
											2015-07-18 08:36:29 +08:00
										 |  |  |   return pose().equals(other.pose(), tol) | 
					
						
							|  |  |  |       && equal_with_abs_tol(velocity(), other.velocity(), tol); | 
					
						
							| 
									
										
										
										
											2012-05-04 01:03:16 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | void PoseRTV::print(const string& s) const { | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   cout << s << ":" << endl; | 
					
						
							|  |  |  |   gtsam::print((Vector)R().xyz(), "  R:rpy"); | 
					
						
							| 
									
										
										
										
											2016-02-12 11:03:11 +08:00
										 |  |  |   cout << "  T" << t().transpose() << endl; | 
					
						
							| 
									
										
										
										
											2015-07-18 08:36:29 +08:00
										 |  |  |   gtsam::print((Vector)velocity(), "  V"); | 
					
						
							| 
									
										
										
										
											2012-05-04 01:03:16 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | PoseRTV PoseRTV::planarDynamics(double vel_rate, double heading_rate, | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |     double max_accel, double dt) const { | 
					
						
							| 
									
										
										
										
											2012-05-04 01:03:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   // split out initial state
 | 
					
						
							|  |  |  |   const Rot3& r1 = R(); | 
					
						
							|  |  |  |   const Velocity3& v1 = v(); | 
					
						
							| 
									
										
										
										
											2012-05-04 01:03:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   // Update vehicle heading
 | 
					
						
							| 
									
										
										
										
											2014-11-23 08:35:27 +08:00
										 |  |  |   Rot3 r2 = r1.retract((Vector(3) << 0.0, 0.0, heading_rate * dt).finished()); | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   const double yaw2 = r2.ypr()(0); | 
					
						
							| 
									
										
										
										
											2012-05-04 01:03:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   // Update vehicle position
 | 
					
						
							|  |  |  |   const double mag_v1 = v1.norm(); | 
					
						
							| 
									
										
										
										
											2012-05-04 01:03:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   // FIXME: this doesn't account for direction in velocity bounds
 | 
					
						
							|  |  |  |   double dv = bound(vel_rate - mag_v1, - (max_accel * dt), max_accel * dt); | 
					
						
							|  |  |  |   double mag_v2 = mag_v1 + dv; | 
					
						
							|  |  |  |   Velocity3 v2 = mag_v2 * Velocity3(cos(yaw2), sin(yaw2), 0.0); | 
					
						
							| 
									
										
										
										
											2012-05-04 01:03:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   Point3 t2 = translationIntegration(r2, v2, dt); | 
					
						
							| 
									
										
										
										
											2012-05-04 01:03:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   return PoseRTV(r2, t2, v2); | 
					
						
							| 
									
										
										
										
											2012-05-04 01:03:16 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | PoseRTV PoseRTV::flyingDynamics( | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |     double pitch_rate, double heading_rate, double lift_control, double dt) const { | 
					
						
							|  |  |  |   // split out initial state
 | 
					
						
							|  |  |  |   const Rot3& r1 = R(); | 
					
						
							|  |  |  |   const Velocity3& v1 = v(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Update vehicle heading (and normalise yaw)
 | 
					
						
							| 
									
										
										
										
											2014-11-23 08:35:27 +08:00
										 |  |  |   Vector rot_rates = (Vector(3) << 0.0, pitch_rate, heading_rate).finished(); | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   Rot3 r2 = r1.retract(rot_rates*dt); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   // Work out dynamics on platform
 | 
					
						
							|  |  |  |   const double thrust = 50.0; | 
					
						
							|  |  |  |   const double lift   = 50.0; | 
					
						
							|  |  |  |   const double drag   = 0.1; | 
					
						
							|  |  |  |   double yaw2 = r2.yaw(); | 
					
						
							|  |  |  |   double pitch2 = r2.pitch(); | 
					
						
							|  |  |  |   double forward_accel = -thrust * sin(pitch2); // r2, pitch (in global frame?) controls forward force
 | 
					
						
							| 
									
										
										
										
											2019-09-19 03:24:09 +08:00
										 |  |  |   double loss_lift = lift*std::abs(sin(pitch2)); | 
					
						
							| 
									
										
										
										
											2016-01-27 15:09:58 +08:00
										 |  |  |   Rot3 yaw_correction_bn = Rot3::Yaw(yaw2); | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   Point3 forward(forward_accel, 0.0, 0.0); | 
					
						
							|  |  |  |   Vector Acc_n = | 
					
						
							| 
									
										
										
										
											2016-02-12 11:03:11 +08:00
										 |  |  |       yaw_correction_bn.rotate(forward)              // applies locally forward force in the global frame
 | 
					
						
							| 
									
										
										
										
											2014-11-23 08:35:27 +08:00
										 |  |  |       - drag * (Vector(3) << v1.x(), v1.y(), 0.0).finished()  // drag term dependent on v1
 | 
					
						
							| 
									
										
										
										
											2016-04-16 08:01:22 +08:00
										 |  |  |       + Vector::Unit(3,2)*(loss_lift - lift_control);                // falling due to lift lost from pitch
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Update Vehicle Position and Velocity
 | 
					
						
							|  |  |  |   Velocity3 v2 = v1 + Velocity3(Acc_n * dt); | 
					
						
							|  |  |  |   Point3 t2 = translationIntegration(r2, v2, dt); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return PoseRTV(r2, t2, v2); | 
					
						
							| 
									
										
										
										
											2012-05-04 01:03:16 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | PoseRTV PoseRTV::generalDynamics( | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |     const Vector& accel, const Vector& gyro, double dt) const { | 
					
						
							|  |  |  |   //  Integrate Attitude Equations
 | 
					
						
							|  |  |  |   Rot3 r2 = rotation().retract(gyro * dt); | 
					
						
							| 
									
										
										
										
											2012-05-04 01:03:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   //  Integrate Velocity Equations
 | 
					
						
							| 
									
										
										
										
											2015-05-26 08:13:08 +08:00
										 |  |  |   Velocity3 v2 = velocity() + Velocity3(dt * (r2.matrix() * accel + kGravity)); | 
					
						
							| 
									
										
										
										
											2012-05-04 01:03:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   //  Integrate Position Equations
 | 
					
						
							|  |  |  |   Point3 t2 = translationIntegration(r2, v2, dt); | 
					
						
							| 
									
										
										
										
											2012-05-04 01:03:16 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   return PoseRTV(t2, r2, v2); | 
					
						
							| 
									
										
										
										
											2012-05-04 01:03:16 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2014-11-04 22:41:14 +08:00
										 |  |  | Vector6 PoseRTV::imuPrediction(const PoseRTV& x2, double dt) const { | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   // split out states
 | 
					
						
							|  |  |  |   const Rot3      &r1 = R(), &r2 = x2.R(); | 
					
						
							|  |  |  |   const Velocity3 &v1 = v(), &v2 = x2.v(); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-11-04 22:41:14 +08:00
										 |  |  |   Vector6 imu; | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // acceleration
 | 
					
						
							| 
									
										
										
										
											2015-07-18 08:36:29 +08:00
										 |  |  |   Vector3 accel = (v2-v1) / dt; | 
					
						
							| 
									
										
										
										
											2015-05-26 08:13:08 +08:00
										 |  |  |   imu.head<3>() = r2.transpose() * (accel - kGravity); | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // rotation rates
 | 
					
						
							|  |  |  |   // just using euler angles based on matlab code
 | 
					
						
							|  |  |  |   // FIXME: this is silly - we shouldn't use differences in Euler angles
 | 
					
						
							|  |  |  |   Matrix Enb = RRTMnb(r1); | 
					
						
							| 
									
										
										
										
											2014-12-23 00:22:45 +08:00
										 |  |  |   Vector3 euler1 = r1.xyz(), euler2 = r2.xyz(); | 
					
						
							|  |  |  |   Vector3 dR = euler2 - euler1; | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // normalize yaw in difference (as per Mitch's code)
 | 
					
						
							|  |  |  |   dR(2) = Rot2::fromAngle(dR(2)).theta(); | 
					
						
							|  |  |  |   dR /= dt; | 
					
						
							| 
									
										
										
										
											2014-11-04 22:41:14 +08:00
										 |  |  |   imu.tail<3>() = Enb * dR; | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  | //  imu.tail(3) = r1.transpose() * dR;
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return imu; | 
					
						
							| 
									
										
										
										
											2012-05-04 01:03:16 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | Point3 PoseRTV::translationIntegration(const Rot3& r2, const Velocity3& v2, double dt) const { | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   // predict point for constraint
 | 
					
						
							|  |  |  |   // NOTE: uses simple Euler approach for prediction
 | 
					
						
							| 
									
										
										
										
											2016-02-09 05:27:38 +08:00
										 |  |  |   Point3 pred_t2 = t() + Point3(v2 * dt); | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   return pred_t2; | 
					
						
							| 
									
										
										
										
											2012-05-04 01:03:16 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | double PoseRTV::range(const PoseRTV& other, | 
					
						
							| 
									
										
										
										
											2014-12-23 06:42:52 +08:00
										 |  |  |     OptionalJacobian<1,9> H1, OptionalJacobian<1,9> H2) const { | 
					
						
							| 
									
										
										
										
											2015-05-26 14:50:00 +08:00
										 |  |  |   Matrix36 D_t1_pose, D_t2_other; | 
					
						
							|  |  |  |   const Point3 t1 = pose().translation(H1 ? &D_t1_pose : 0); | 
					
						
							|  |  |  |   const Point3 t2 = other.pose().translation(H2 ? &D_t2_other : 0); | 
					
						
							|  |  |  |   Matrix13 D_d_t1, D_d_t2; | 
					
						
							| 
									
										
										
										
											2016-06-07 12:57:52 +08:00
										 |  |  |   double d = distance3(t1, t2, H1 ? &D_d_t1 : 0, H2 ? &D_d_t2 : 0); | 
					
						
							| 
									
										
										
										
											2015-05-26 14:50:00 +08:00
										 |  |  |   if (H1) *H1 << D_d_t1 * D_t1_pose, 0,0,0; | 
					
						
							|  |  |  |   if (H2) *H2 << D_d_t2 * D_t2_other, 0,0,0; | 
					
						
							|  |  |  |   return d; | 
					
						
							| 
									
										
										
										
											2012-05-04 01:03:16 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2014-12-23 06:42:52 +08:00
										 |  |  | PoseRTV PoseRTV::transformed_from(const Pose3& trans, ChartJacobian Dglobal, | 
					
						
							|  |  |  |     OptionalJacobian<9, 6> Dtrans) const { | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  | 
 | 
					
						
							|  |  |  |   // Pose3 transform is just compose
 | 
					
						
							| 
									
										
										
										
											2015-05-26 14:50:00 +08:00
										 |  |  |   Matrix6 D_newpose_trans, D_newpose_pose; | 
					
						
							|  |  |  |   Pose3 newpose = trans.compose(pose(), D_newpose_trans, D_newpose_pose); | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-26 14:50:00 +08:00
										 |  |  |   // Note that we rotate the velocity
 | 
					
						
							|  |  |  |   Matrix3 D_newvel_R, D_newvel_v; | 
					
						
							| 
									
										
										
										
											2016-02-12 11:03:11 +08:00
										 |  |  |   Velocity3 newvel = trans.rotation().rotate(Point3(velocity()), D_newvel_R, D_newvel_v); | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-26 14:50:00 +08:00
										 |  |  |   if (Dglobal) { | 
					
						
							|  |  |  |     Dglobal->setZero(); | 
					
						
							|  |  |  |     Dglobal->topLeftCorner<6,6>() = D_newpose_pose; | 
					
						
							|  |  |  |     Dglobal->bottomRightCorner<3,3>() = D_newvel_v; | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   if (Dtrans) { | 
					
						
							| 
									
										
										
										
											2015-05-26 14:50:00 +08:00
										 |  |  |     Dtrans->setZero(); | 
					
						
							|  |  |  |     Dtrans->topLeftCorner<6,6>() = D_newpose_trans; | 
					
						
							|  |  |  |     Dtrans->bottomLeftCorner<3,3>() = D_newvel_R; | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   } | 
					
						
							|  |  |  |   return PoseRTV(newpose, newvel); | 
					
						
							| 
									
										
										
										
											2012-05-04 01:03:16 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2012-06-06 21:04:47 +08:00
										 |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2015-07-22 02:23:42 +08:00
										 |  |  | Matrix PoseRTV::RRTMbn(const Vector3& euler) { | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   assert(euler.size() == 3); | 
					
						
							| 
									
										
										
										
											2015-07-22 02:23:42 +08:00
										 |  |  |   const double s1 = sin(euler.x()), c1 = cos(euler.x()); | 
					
						
							|  |  |  |   const double t2 = tan(euler.y()), c2 = cos(euler.y()); | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   Matrix Ebn(3,3); | 
					
						
							|  |  |  |   Ebn << 1.0, s1 * t2, c1 * t2, | 
					
						
							|  |  |  |          0.0,      c1,     -s1, | 
					
						
							|  |  |  |          0.0, s1 / c2, c1 / c2; | 
					
						
							|  |  |  |   return Ebn; | 
					
						
							| 
									
										
										
										
											2012-06-06 21:04:47 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | Matrix PoseRTV::RRTMbn(const Rot3& att) { | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   return PoseRTV::RRTMbn(att.rpy()); | 
					
						
							| 
									
										
										
										
											2012-06-06 21:04:47 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2015-07-22 02:23:42 +08:00
										 |  |  | Matrix PoseRTV::RRTMnb(const Vector3& euler) { | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   Matrix Enb(3,3); | 
					
						
							| 
									
										
										
										
											2015-07-22 02:23:42 +08:00
										 |  |  |   const double s1 = sin(euler.x()), c1 = cos(euler.x()); | 
					
						
							|  |  |  |   const double s2 = sin(euler.y()), c2 = cos(euler.y()); | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   Enb << 1.0, 0.0,   -s2, | 
					
						
							| 
									
										
										
										
											2012-06-06 21:04:47 +08:00
										 |  |  |          0.0,  c1, s1*c2, | 
					
						
							|  |  |  |          0.0, -s1, c1*c2; | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   return Enb; | 
					
						
							| 
									
										
										
										
											2012-06-06 21:04:47 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							|  |  |  | Matrix PoseRTV::RRTMnb(const Rot3& att) { | 
					
						
							| 
									
										
										
										
											2012-10-02 22:40:07 +08:00
										 |  |  |   return PoseRTV::RRTMnb(att.rpy()); | 
					
						
							| 
									
										
										
										
											2012-06-06 21:04:47 +08:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ************************************************************************* */ | 
					
						
							| 
									
										
										
										
											2012-05-04 01:03:16 +08:00
										 |  |  | } // \namespace gtsam
 |