conversions.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002 * Software License Agreement (BSD License)
00003 *
00004 *  Copyright (c) 2013, Ioan A. Sucan
00005 *  Copyright (c) 2011-2013, Willow Garage, Inc.
00006 *  All rights reserved.
00007 *
00008 *  Redistribution and use in source and binary forms, with or without
00009 *  modification, are permitted provided that the following conditions
00010 *  are met:
00011 *
00012 *   * Redistributions of source code must retain the above copyright
00013 *     notice, this list of conditions and the following disclaimer.
00014 *   * Redistributions in binary form must reproduce the above
00015 *     copyright notice, this list of conditions and the following
00016 *     disclaimer in the documentation and/or other materials provided
00017 *     with the distribution.
00018 *   * Neither the name of the Willow Garage nor the names of its
00019 *     contributors may be used to endorse or promote products derived
00020 *     from this software without specific prior written permission.
00021 *
00022 *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00023 *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00024 *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00025 *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00026 *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00027 *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00028 *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00029 *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00030 *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00031 *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00032 *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00033 *  POSSIBILITY OF SUCH DAMAGE.
00034 *********************************************************************/
00035 
00036 /* Author: Ioan Sucan, Dave Coleman */
00037 
00038 #include <moveit/robot_state/conversions.h>
00039 #include <geometric_shapes/shape_operations.h>
00040 #include <eigen_conversions/eigen_msg.h>
00041 
00042 namespace moveit
00043 {
00044 namespace core
00045 {
00046 
00047 // ********************************************
00048 // * Internal (hidden) functions
00049 // ********************************************
00050 
00051 namespace
00052 {
00053 
00054 static bool _jointStateToRobotState(const sensor_msgs::JointState &joint_state, RobotState& state)
00055 {
00056   if (joint_state.name.size() != joint_state.position.size())
00057   {
00058     logError("Different number of names and positions in JointState message: %u, %u",
00059              (unsigned int)joint_state.name.size(), (unsigned int)joint_state.position.size());
00060     return false;
00061   }
00062   
00063   state.setVariableValues(joint_state);
00064   
00065   return true;
00066 }
00067 
00068 static bool _multiDOFJointsToRobotState(const sensor_msgs::MultiDOFJointState &mjs, RobotState& state, const Transforms *tf)
00069 {
00070   std::size_t nj = mjs.joint_names.size();
00071   if (nj != mjs.transforms.size())
00072   {
00073     logError("Different number of names, values or frames in MultiDOFJointState message.");
00074     return false;
00075   }
00076   
00077   bool error = false;
00078   Eigen::Affine3d inv_t;
00079   bool use_inv_t = false;
00080   
00081   if (nj > 0 && !Transforms::sameFrame(mjs.header.frame_id, state.getRobotModel()->getModelFrame()))
00082   {
00083     if (tf)
00084       try
00085       {
00086         // find the transform that takes the given frame_id to the desired fixed frame
00087         const Eigen::Affine3d &t2fixed_frame = tf->getTransform(mjs.header.frame_id);
00088         // we update the value of the transform so that it transforms from the known fixed frame to the desired child link
00089         inv_t = t2fixed_frame.inverse();
00090         use_inv_t = true;
00091       }
00092       catch (std::runtime_error&)
00093       {
00094         error = true;
00095       }
00096     else
00097       error = true;
00098 
00099     if (error)
00100       logWarn("The transform for multi-dof joints was specified in frame '%s' but it was not possible to transform that to frame '%s'",
00101               mjs.header.frame_id.c_str(), state.getRobotModel()->getModelFrame().c_str());
00102   }
00103 
00104   for (std::size_t i = 0 ; i < nj ; ++i)
00105   {
00106     const std::string &joint_name = mjs.joint_names[i];
00107     if (!state.getRobotModel()->hasJointModel(joint_name))
00108     {
00109       logWarn("No joint matching multi-dof joint '%s'", joint_name.c_str());
00110       error = true;
00111       continue;
00112     }
00113     Eigen::Affine3d transf;
00114     tf::transformMsgToEigen(mjs.transforms[i], transf);
00115     // if frames do not mach, attempt to transform
00116     if (use_inv_t)
00117       transf = transf * inv_t;
00118     
00119     state.setJointPositions(joint_name, transf);
00120   }
00121 
00122   return !error;
00123 }
00124 
00125 static inline void _robotStateToMultiDOFJointState(const RobotState& state, sensor_msgs::MultiDOFJointState &mjs)
00126 {
00127   const std::vector<const JointModel*> &js = state.getRobotModel()->getMultiDOFJointModels();
00128   mjs.joint_names.clear();
00129   mjs.transforms.clear();
00130   for (std::size_t i = 0 ; i < js.size() ; ++i)
00131   {
00132     geometry_msgs::Transform p;
00133     if (state.dirtyJointTransform(js[i]))
00134     {
00135       Eigen::Affine3d t;
00136       t.setIdentity();
00137       js[i]->computeTransform(state.getJointPositions(js[i]), t);
00138       tf::transformEigenToMsg(t, p);
00139     }
00140     else
00141       tf::transformEigenToMsg(state.getJointTransform(js[i]), p);
00142     mjs.joint_names.push_back(js[i]->getName());
00143     mjs.transforms.push_back(p);
00144   }
00145   mjs.header.frame_id = state.getRobotModel()->getModelFrame();
00146 }
00147 
00148 class ShapeVisitorAddToCollisionObject : public boost::static_visitor<void>
00149 {
00150 public:
00151 
00152   ShapeVisitorAddToCollisionObject(moveit_msgs::CollisionObject *obj) :
00153     boost::static_visitor<void>(), obj_(obj)
00154   {
00155   }
00156 
00157   void addToObject(const shapes::ShapeMsg &sm, const geometry_msgs::Pose &pose)
00158   {
00159     pose_ = &pose;
00160     boost::apply_visitor(*this, sm);
00161   }
00162 
00163   void operator()(const shape_msgs::Plane &shape_msg) const
00164   {
00165     obj_->planes.push_back(shape_msg);
00166     obj_->plane_poses.push_back(*pose_);
00167   }
00168 
00169   void operator()(const shape_msgs::Mesh &shape_msg) const
00170   {
00171     obj_->meshes.push_back(shape_msg);
00172     obj_->mesh_poses.push_back(*pose_);
00173   }
00174 
00175   void operator()(const shape_msgs::SolidPrimitive &shape_msg) const
00176   {
00177     obj_->primitives.push_back(shape_msg);
00178     obj_->primitive_poses.push_back(*pose_);
00179   }
00180 
00181 private:
00182 
00183   moveit_msgs::CollisionObject *obj_;
00184   const geometry_msgs::Pose *pose_;
00185 };
00186 
00187 static void _attachedBodyToMsg(const AttachedBody &attached_body, moveit_msgs::AttachedCollisionObject &aco)
00188 {
00189   aco.link_name = attached_body.getAttachedLinkName();
00190   aco.detach_posture = attached_body.getDetachPosture();
00191   const std::set<std::string> &touch_links = attached_body.getTouchLinks();
00192   aco.touch_links.clear();
00193   for (std::set<std::string>::const_iterator it = touch_links.begin() ; it != touch_links.end() ; ++it)
00194     aco.touch_links.push_back(*it);
00195   aco.object.header.frame_id = aco.link_name;
00196   aco.object.id = attached_body.getName();
00197 
00198   aco.object.operation = moveit_msgs::CollisionObject::ADD;
00199   const std::vector<shapes::ShapeConstPtr>& ab_shapes = attached_body.getShapes();
00200   const EigenSTL::vector_Affine3d& ab_tf = attached_body.getFixedTransforms();
00201   ShapeVisitorAddToCollisionObject sv(&aco.object);
00202   aco.object.primitives.clear();
00203   aco.object.meshes.clear();
00204   aco.object.planes.clear();
00205   aco.object.primitive_poses.clear();
00206   aco.object.mesh_poses.clear();
00207   aco.object.plane_poses.clear();
00208   for (std::size_t j = 0 ; j < ab_shapes.size() ; ++j)
00209   {
00210     shapes::ShapeMsg sm;
00211     if (shapes::constructMsgFromShape(ab_shapes[j].get(), sm))
00212     {
00213       geometry_msgs::Pose p;
00214       tf::poseEigenToMsg(ab_tf[j], p);
00215       sv.addToObject(sm, p);
00216     }
00217   }
00218 }
00219 
00220 static void _msgToAttachedBody(const Transforms *tf, const moveit_msgs::AttachedCollisionObject &aco, RobotState& state)
00221 {
00222   if (aco.object.operation == moveit_msgs::CollisionObject::ADD)
00223   {
00224     if (!aco.object.primitives.empty() || !aco.object.meshes.empty() || !aco.object.planes.empty())
00225     {
00226       if (aco.object.primitives.size() != aco.object.primitive_poses.size())
00227       {
00228         logError("Number of primitive shapes does not match number of poses in collision object message");
00229         return;
00230       }
00231 
00232       if (aco.object.meshes.size() != aco.object.mesh_poses.size())
00233       {
00234         logError("Number of meshes does not match number of poses in collision object message");
00235         return;
00236       }
00237 
00238       if (aco.object.planes.size() != aco.object.plane_poses.size())
00239       {
00240         logError("Number of planes does not match number of poses in collision object message");
00241         return;
00242       }
00243 
00244       const LinkModel *lm = state.getLinkModel(aco.link_name);
00245       if (lm)
00246       {
00247         std::vector<shapes::ShapeConstPtr> shapes;
00248         EigenSTL::vector_Affine3d poses;
00249 
00250         for (std::size_t i = 0 ; i < aco.object.primitives.size() ; ++i)
00251         {
00252           shapes::Shape *s = shapes::constructShapeFromMsg(aco.object.primitives[i]);
00253           if (s)
00254           {
00255             Eigen::Affine3d p;
00256             tf::poseMsgToEigen(aco.object.primitive_poses[i], p);
00257             shapes.push_back(shapes::ShapeConstPtr(s));
00258             poses.push_back(p);
00259           }
00260         }
00261         for (std::size_t i = 0 ; i < aco.object.meshes.size() ; ++i)
00262         {
00263           shapes::Shape *s = shapes::constructShapeFromMsg(aco.object.meshes[i]);
00264           if (s)
00265           {
00266             Eigen::Affine3d p;
00267             tf::poseMsgToEigen(aco.object.mesh_poses[i], p);
00268             shapes.push_back(shapes::ShapeConstPtr(s));
00269             poses.push_back(p);
00270           }
00271         }
00272         for (std::size_t i = 0 ; i < aco.object.planes.size() ; ++i)
00273         {
00274           shapes::Shape *s = shapes::constructShapeFromMsg(aco.object.planes[i]);
00275           if (s)
00276           {
00277             Eigen::Affine3d p;
00278             tf::poseMsgToEigen(aco.object.plane_poses[i], p);
00279 
00280             shapes.push_back(shapes::ShapeConstPtr(s));
00281             poses.push_back(p);
00282           }
00283         }
00284 
00285         // transform poses to link frame
00286         if (!Transforms::sameFrame(aco.object.header.frame_id, aco.link_name))
00287         {
00288           Eigen::Affine3d t0;
00289           if (state.knowsFrameTransform(aco.object.header.frame_id))
00290             t0 = state.getFrameTransform(aco.object.header.frame_id);
00291           else
00292             if (tf && tf->canTransform(aco.object.header.frame_id))
00293               t0 = tf->getTransform(aco.object.header.frame_id);
00294             else
00295             {
00296               t0.setIdentity();
00297               logError("Cannot properly transform from frame '%s'. The pose of the attached body may be incorrect", aco.object.header.frame_id.c_str());
00298             }
00299           Eigen::Affine3d t = state.getGlobalLinkTransform(lm).inverse() * t0;
00300           for (std::size_t i = 0 ; i < poses.size() ; ++i)
00301             poses[i] = t * poses[i];
00302         }
00303 
00304         if (shapes.empty())
00305           logError("There is no geometry to attach to link '%s' as part of attached body '%s'", aco.link_name.c_str(), aco.object.id.c_str());
00306         else
00307         {
00308           if (state.clearAttachedBody(aco.object.id))
00309             logDebug("The robot state already had an object named '%s' attached to link '%s'. The object was replaced.",
00310                       aco.object.id.c_str(), aco.link_name.c_str());
00311           state.attachBody(aco.object.id, shapes, poses, aco.touch_links, aco.link_name, aco.detach_posture);
00312           logDebug("Attached object '%s' to link '%s'", aco.object.id.c_str(), aco.link_name.c_str());
00313         }
00314       }
00315     }
00316     else
00317       logError("The attached body for link '%s' has no geometry", aco.link_name.c_str());
00318   }
00319   else
00320     if (aco.object.operation == moveit_msgs::CollisionObject::REMOVE)
00321     {
00322       state.clearAttachedBody(aco.object.id);
00323     }
00324     else
00325       logError("Unknown collision object operation: %d", aco.object.operation);
00326 }
00327 
00328 static bool _robotStateMsgToRobotStateHelper(const Transforms *tf, const moveit_msgs::RobotState &robot_state, RobotState& state, bool copy_attached_bodies)
00329 {
00330   bool result1 = _jointStateToRobotState(robot_state.joint_state, state);
00331   bool result2 = _multiDOFJointsToRobotState(robot_state.multi_dof_joint_state, state, tf);
00332 
00333   if (copy_attached_bodies)
00334   {
00335     if (!robot_state.is_diff)
00336       state.clearAttachedBodies();
00337     for (std::size_t i = 0 ; i < robot_state.attached_collision_objects.size() ; ++i)
00338       _msgToAttachedBody(tf, robot_state.attached_collision_objects[i], state);
00339   }
00340   
00341   return result1 && result2;
00342 }
00343 
00344 }
00345 }
00346 }
00347 
00348 
00349 // ********************************************
00350 
00351 
00352 
00353 // ********************************************
00354 // * Exposed functions
00355 // ********************************************
00356 
00357 bool moveit::core::jointStateToRobotState(const sensor_msgs::JointState &joint_state, RobotState& state)
00358 {
00359   bool result = _jointStateToRobotState(joint_state, state);
00360   state.update();
00361   return result;
00362 }
00363 
00364 bool moveit::core::robotStateMsgToRobotState(const moveit_msgs::RobotState &robot_state, RobotState& state, bool copy_attached_bodies)
00365 {
00366   bool result = _robotStateMsgToRobotStateHelper(NULL, robot_state, state, copy_attached_bodies);
00367   state.update();
00368   return result;
00369 }
00370 
00371 bool moveit::core::robotStateMsgToRobotState(const Transforms &tf, const moveit_msgs::RobotState &robot_state, RobotState& state, bool copy_attached_bodies)
00372 {
00373   bool result = _robotStateMsgToRobotStateHelper(&tf, robot_state, state, copy_attached_bodies);
00374   state.update();
00375   return result;
00376 }
00377 
00378 void moveit::core::robotStateToRobotStateMsg(const RobotState& state, moveit_msgs::RobotState &robot_state, bool copy_attached_bodies)
00379 {
00380   robotStateToJointStateMsg(state, robot_state.joint_state);
00381   _robotStateToMultiDOFJointState(state, robot_state.multi_dof_joint_state);
00382   if (copy_attached_bodies)
00383   {
00384     std::vector<const AttachedBody*> attached_bodies;
00385     state.getAttachedBodies(attached_bodies);
00386     robot_state.attached_collision_objects.resize(attached_bodies.size());
00387     for (std::size_t i = 0 ; i < attached_bodies.size() ; ++i)
00388       _attachedBodyToMsg(*attached_bodies[i], robot_state.attached_collision_objects[i]);
00389   }
00390 }
00391 
00392 void moveit::core::robotStateToJointStateMsg(const RobotState& state, sensor_msgs::JointState &joint_state)
00393 {
00394   const std::vector<const JointModel*> &js = state.getRobotModel()->getSingleDOFJointModels();
00395   joint_state = sensor_msgs::JointState();
00396   
00397   for (std::size_t i = 0 ; i < js.size() ; ++i)
00398   {
00399     joint_state.name.push_back(js[i]->getName());
00400     joint_state.position.push_back(state.getVariablePosition(js[i]->getFirstVariableIndex()));
00401     if (state.hasVelocities())
00402       joint_state.velocity.push_back(state.getVariableVelocity(js[i]->getFirstVariableIndex()));
00403   }
00404   
00405   // if inconsistent number of velocities are specified, discard them
00406   if (joint_state.velocity.size() != joint_state.position.size())
00407     joint_state.velocity.clear();
00408 
00409   joint_state.header.frame_id = state.getRobotModel()->getModelFrame();
00410 }
00411 
00412 void moveit::core::robotStateToStream(const RobotState& state, std::ostream &out, bool include_header, const std::string& separator)
00413 {
00414   // Output name of variables
00415   if (include_header)
00416   {
00417     for (std::size_t i = 0; i < state.getVariableCount(); ++i)
00418     {
00419       out << state.getVariableNames()[i];
00420 
00421       // Output comma except at end
00422       if (i < state.getVariableCount() - 1)
00423         out << separator;
00424     }
00425     out << std::endl;
00426   }
00427 
00428   // Output values of joints
00429   for (std::size_t i = 0; i < state.getVariableCount(); ++i)
00430   {
00431     out << state.getVariablePositions()[i];
00432 
00433     // Output comma except at end
00434     if (i < state.getVariableCount() - 1)
00435       out << separator;
00436   }
00437   out << std::endl;
00438 }
00439 
00440 void moveit::core::robotStateToStream(const RobotState& state, std::ostream &out, const std::vector<std::string> &joint_groups_ordering,
00441                                       bool include_header, const std::string& separator)
00442 {
00443   std::stringstream headers;
00444   std::stringstream joints;
00445 
00446   for (std::size_t j = 0; j < joint_groups_ordering.size(); ++j)
00447   {
00448     const JointModelGroup *jmg = state.getRobotModel()->getJointModelGroup(joint_groups_ordering[j]);
00449 
00450     // Output name of variables
00451     if (include_header)
00452     {
00453       for (std::size_t i = 0; i < jmg->getVariableCount(); ++i)
00454       {
00455         headers << jmg->getVariableNames()[i] << separator;
00456       }
00457     }
00458 
00459     // Copy the joint positions for each joint model group
00460     std::vector<double> group_variable_positions;
00461     state.copyJointGroupPositions(jmg, group_variable_positions);
00462 
00463     // Output values of joints
00464     for (std::size_t i = 0; i < jmg->getVariableCount(); ++i)
00465     {
00466       joints << group_variable_positions[i] << separator;
00467     }
00468   }
00469 
00470   // Push all headers and joints to our output stream
00471   if (include_header)
00472     out << headers.str() << std::endl;
00473   out << joints.str() << std::endl;
00474 }


moveit_core
Author(s): Ioan Sucan , Sachin Chitta , Acorn Pooley
autogenerated on Thu Aug 27 2015 13:58:52