transforms.cpp
Go to the documentation of this file.
00001 /*
00002  * Copyright (c) 2008, Willow Garage, Inc.
00003  * All rights reserved.
00004  *
00005  * Redistribution and use in source and binary forms, with or without
00006  * modification, are permitted provided that the following conditions are met:
00007  *
00008  *     * Redistributions of source code must retain the above copyright
00009  *       notice, this list of conditions and the following disclaimer.
00010  *     * Redistributions in binary form must reproduce the above copyright
00011  *       notice, this list of conditions and the following disclaimer in the
00012  *       documentation and/or other materials provided with the distribution.
00013  *     * Neither the name of the Willow Garage, Inc. nor the names of its
00014  *       contributors may be used to endorse or promote products derived from
00015  *       this software without specific prior written permission.
00016  *
00017  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
00018  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
00019  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
00020  * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
00021  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
00022  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
00023  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
00024  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
00025  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
00026  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00027  * POSSIBILITY OF SUCH DAMAGE.
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 // Turn a ROS Pose into an Eigen Transform (the one that maps from the pose frame to the world frame)
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 // Transform from pose1's frame to pose2's frame
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 // Transform that sends pose1 to pose2
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 // Apply an Eigen Transform to a ROS Pose
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 // Apply an Eigen transform to a ROS point
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 // Apply an Eigen transform to a ROS point
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 } // namespace pose_graph


pose_graph
Author(s): Bhaskara Marthi
autogenerated on Tue Jan 7 2014 11:17:15