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 
00032 
00033 
00034 
00035 
00036 
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 
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         
00087         const Eigen::Affine3d &t2fixed_frame = tf->getTransform(mjs.header.frame_id);
00088         
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     
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         
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 
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   
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   
00415   if (include_header)
00416   {
00417     for (std::size_t i = 0; i < state.getVariableCount(); ++i)
00418     {
00419       out << state.getVariableNames()[i];
00420 
00421       
00422       if (i < state.getVariableCount() - 1)
00423         out << separator;
00424     }
00425     out << std::endl;
00426   }
00427 
00428   
00429   for (std::size_t i = 0; i < state.getVariableCount(); ++i)
00430   {
00431     out << state.getVariablePositions()[i];
00432 
00433     
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     
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     
00460     std::vector<double> group_variable_positions;
00461     state.copyJointGroupPositions(jmg, group_variable_positions);
00462 
00463     
00464     for (std::size_t i = 0; i < jmg->getVariableCount(); ++i)
00465     {
00466       joints << group_variable_positions[i] << separator;
00467     }
00468   }
00469 
00470   
00471   if (include_header)
00472     out << headers.str() << std::endl;
00473   out << joints.str() << std::endl;
00474 }