Go to the documentation of this file.00001 
00002 
00003 
00004 
00005 
00006 
00007 
00008 
00009 
00010 
00011 
00012 
00013 
00014 
00015 
00016 
00017 
00018 
00019 
00020 
00021 
00022 
00023 
00024 
00025 
00026 
00027 
00028 
00029 
00030 
00031 
00040 #include <pose_graph/transforms.h>
00041 #include <tf/transform_datatypes.h>
00042 #include <boost/random/mersenne_twister.hpp>
00043 #include <boost/random/uniform_real.hpp>
00044 #include <boost/random/variate_generator.hpp>
00045 #include <boost/lexical_cast.hpp>
00046 
00047 
00048 
00049 #include <ros/ros.h>
00050 
00051 namespace pose_graph
00052 {
00053 
00054 namespace nm=nav_msgs;
00055 namespace gm=geometry_msgs;
00056 
00057 using Eigen3::Translation3d;
00058 using Eigen3::Quaterniond;
00059 using std::string;
00060 using nav_msgs::OccupancyGrid;
00061 
00062 
00063 Affine3d poseToWorldTransform (const Pose& p)
00064 {
00065   return
00066     Translation3d(p.position.x, p.position.y, p.position.z) *
00067     Quaterniond(p.orientation.w, p.orientation.x, p.orientation.y, p.orientation.z);
00068 }
00069 
00070 
00071 
00072 Affine3d relativeTransform (const Pose& pose1, const Pose& pose2)
00073 {
00074   const Affine3d inv2(poseToWorldTransform(pose2).inverse());
00075   const Affine3d result=inv2*poseToWorldTransform(pose1);
00076   return result;
00077 }
00078 
00079 
00080 Affine3d transformBetween (const Pose& pose1, const Pose& pose2)
00081 {
00082   const Affine3d inv1(poseToWorldTransform(pose1).inverse());
00083   return poseToWorldTransform(pose2) * inv1;
00084 }
00085 
00086 
00087 
00088 Pose applyTransform (const Affine3d& trans, const Pose& pose)
00089 {
00090   const Affine3d pose_to_world = poseToWorldTransform(pose);
00091   const Affine3d new_pose_to_world = trans*pose_to_world;
00092   Pose new_pose;
00093   new_pose.position.x = new_pose_to_world.translation().x();
00094   new_pose.position.y = new_pose_to_world.translation().y();
00095   new_pose.position.z = new_pose_to_world.translation().z();
00096   const Quaterniond rotation(new_pose_to_world.rotation());
00097   new_pose.orientation.x = rotation.x();
00098   new_pose.orientation.y = rotation.y();
00099   new_pose.orientation.z = rotation.z();
00100   new_pose.orientation.w = rotation.w();
00101 
00102   return new_pose;
00103 }
00104 
00105 
00106 Point32 transformPoint (const Affine3d& trans, const Point32& point)
00107 {
00108   Point32 ret;
00109   Vector3d result = trans*Vector3d(point.x, point.y, point.z);
00110   ret.x = result.x();
00111   ret.y = result.y();
00112   ret.z = result.z();
00113 
00114   return ret;
00115 }
00116 
00117 
00118 Point transformPoint (const Affine3d& trans, const Point& point)
00119 {
00120   Point ret;
00121   Vector3d result = trans*Vector3d(point.x, point.y, point.z);
00122   ret.x = result.x();
00123   ret.y = result.y();
00124   ret.z = result.z();
00125 
00126   return ret;
00127 }
00128 
00129 
00130 Pose perturbPose (const Pose& pose, double r)
00131 {
00132   boost::mt19937 rng(ros::Time::now().toNSec());
00133   boost::uniform_real<float> u(-r, r);
00134   boost::variate_generator<boost::mt19937&, boost::uniform_real<float> > gen(rng, u);
00135 
00136   Pose perturbed;
00137   perturbed.orientation = pose.orientation;
00138   perturbed.position.x = pose.position.x + gen();
00139   perturbed.position.y = pose.position.y + gen();
00140   perturbed.position.z = pose.position.z;
00141 
00142   return perturbed;
00143 }
00144 
00145 Point pointInReferenceFrame (const Point& p, const Pose& pose)
00146 {
00147   return transformPoint(poseToWorldTransform(pose), p);
00148 }
00149 
00150 
00151 
00152 Eigen3::Vector4d quaternionMsgToVector4d (const geometry_msgs::Quaternion& m)
00153 {
00154   return Eigen3::Vector4d(m.x, m.y, m.z, m.w);
00155 }
00156 
00157 Eigen3::Vector4d translationToVector4d(const geometry_msgs::Point& p)
00158 {
00159   return Eigen3::Vector4d(p.x, p.y, p.z, 1.0);
00160 }
00161 
00162 
00163 
00164 Pose2D projectToPose2D (const Pose& pose)
00165 {
00166   Pose2D pose2d;
00167   pose2d.x = pose.position.x;
00168   pose2d.y = pose.position.y;
00169   pose2d.theta = tf::getYaw(pose.orientation);
00170   return pose2d;
00171 }
00172 
00173 
00174 
00175 Affine3d relativeTransform (const Pose2D& pose1, const Pose2D& pose2)
00176 {
00177   return relativeTransform(convertToPose(pose1), convertToPose(pose2));
00178 }
00179 
00182 Pose relativePose (const Pose& pose1, const Pose& pose2)
00183 {
00184   const Affine3d toPose2Coords(poseToWorldTransform(pose2).inverse());
00185   return applyTransform(toPose2Coords, pose1);
00186 }
00187 
00188 
00189 Pose convertToPose (const Pose2D& pose2d)
00190 {
00191   Pose p;
00192   p.position.x = pose2d.x;
00193   p.position.y = pose2d.y;
00194   p.position.z = 0.0;
00195   p.orientation = tf::createQuaternionMsgFromYaw(pose2d.theta);
00196   return p;
00197 }
00198 
00199 Pose convertToPose (const Affine3d trans)
00200 {
00201   Pose id;
00202   id.orientation.w = 1.0;
00203   return applyTransform(trans, id);
00204 }
00205 
00206 OccupancyGrid transformGrid (const Affine3d& trans, const OccupancyGrid& g)
00207 {
00208   OccupancyGrid g2(g);
00209   g2.info.origin = applyTransform(trans, g.info.origin);
00210   return g2;
00211 }
00212 
00214 Pose2D makePose2D (double x, double y, double theta)
00215 {
00216   Pose2D p;
00217   p.x = x;
00218   p.y = y;
00219   p.theta = theta;
00220   return p;
00221 }
00222 
00223 
00225 nm::MapMetaData getMapInfo (const gm::Pose& pose, const double size, const double resolution)
00226 {
00227   const Eigen3::Affine3d node_ref_transform = poseToWorldTransform(pose);
00228 
00229   gm::Pose local_origin;
00230   local_origin.position.x = -size/2;
00231   local_origin.position.y = -size/2;
00232   local_origin.orientation.w = 1.0;
00233 
00234   nm::MapMetaData info;
00235   info.resolution = resolution;
00236   info.width = size/resolution;
00237   info.height = size/resolution;
00238   info.origin = applyTransform(node_ref_transform, local_origin);
00239 
00240   return info;
00241 }
00242 
00243 
00244 }