robot_interaction.h
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 /* Author: Ioan Sucan, Adam Leeper */
00031 
00032 
00033 #ifndef MOVEIT_ROBOT_INTERACTION_ROBOT_INTERACTION_
00034 #define MOVEIT_ROBOT_INTERACTION_ROBOT_INTERACTION_
00035 
00036 #include <visualization_msgs/InteractiveMarkerFeedback.h>
00037 #include <visualization_msgs/InteractiveMarker.h>
00038 #include <interactive_markers/menu_handler.h>
00039 #include <moveit/robot_state/robot_state.h>
00040 #include <moveit/macros/class_forward.h>
00041 #include <boost/function.hpp>
00042 #include <boost/thread.hpp>
00043 #include <tf/tf.h>
00044 
00045 namespace interactive_markers
00046 {
00047 class InteractiveMarkerServer;
00048 }
00049 
00050 namespace robot_interaction
00051 {
00052 
00053 // Manage interactive markers for controlling a robot state.
00054 //
00055 // The RobotInteraction class manages one or more InteractionHandler objects
00056 // each of which maintains a set of interactive markers for manipulating one
00057 // group of one RobotState.
00058 //
00059 // The group being manipulated is common to all InteractionHandler objects
00060 // contained in a RobotInteraction instance.
00061 class RobotInteraction
00062 {
00063 public:
00064 
00066   static const std::string INTERACTIVE_MARKER_TOPIC;
00067 
00069   // This is a bitmask so OR together the parts you want.
00070   enum EndEffectorInteractionStyle
00071   {
00072     EEF_POSITION_ARROWS = 1,      // arrow handles to change position
00073     EEF_ORIENTATION_CIRCLES = 2,  // circle handles to change orientation
00074     EEF_POSITION_SPHERE = 4,      // a sphere which can be dragged to change position
00075     EEF_ORIENTATION_SPHERE = 8,   // a sphere which can be dragged to change orientation
00076     EEF_POSITION_EEF = 16,        // drag end effector to change position
00077     EEF_ORIENTATION_EEF = 32,     // drag end effector to change orientation
00078     EEF_FIXED = 64,               // keep arrow and circle axis fixed
00079 
00080     EEF_POSITION = EEF_POSITION_ARROWS |
00081                    EEF_POSITION_SPHERE |
00082                    EEF_POSITION_EEF,
00083     EEF_ORIENTATION = EEF_ORIENTATION_CIRCLES |
00084                       EEF_ORIENTATION_SPHERE |
00085                       EEF_ORIENTATION_EEF,
00086     EEF_6DOF = EEF_POSITION |
00087                EEF_ORIENTATION,
00088     EEF_6DOF_SPHERE = EEF_POSITION_SPHERE |
00089                       EEF_ORIENTATION_SPHERE,
00090     EEF_POSITION_NOSPHERE = EEF_POSITION_ARROWS |
00091                             EEF_POSITION_EEF,
00092     EEF_ORIENTATION_NOSPHERE = EEF_ORIENTATION_CIRCLES |
00093                                EEF_ORIENTATION_EEF,
00094     EEF_6DOF_NOSPHERE = EEF_POSITION_NOSPHERE |
00095                         EEF_ORIENTATION_NOSPHERE
00096   };
00097 
00099   struct EndEffector
00100   {
00102     std::string parent_group;
00103 
00105     std::string parent_link;
00106 
00108     std::string eef_group;
00109 
00111     EndEffectorInteractionStyle interaction;
00112 
00114     double size;
00115 
00116   };
00117 
00119   struct Joint
00120   {
00122     std::string connecting_link;
00123 
00125     std::string parent_frame;
00126 
00128     std::string joint_name;
00129 
00131     unsigned int dof;
00132 
00134     double size;
00135   };
00136 
00141   typedef boost::function<bool(const robot_state::RobotState&, visualization_msgs::InteractiveMarker&)> InteractiveMarkerConstructorFn;
00142 
00146   typedef boost::function<bool(robot_state::RobotState&, const visualization_msgs::InteractiveMarkerFeedbackConstPtr &)> ProcessFeedbackFn;
00147 
00151   typedef boost::function<bool(const robot_state::RobotState&, geometry_msgs::Pose&)> InteractiveMarkerUpdateFn;
00152 
00154   struct Generic
00155   {
00156     InteractiveMarkerConstructorFn construct_marker; // see comment on typedef above
00157     ProcessFeedbackFn process_feedback;              // see comment on typedef above
00158     InteractiveMarkerUpdateFn update_pose;           // see comment on typedef above
00159     std::string marker_name_suffix; // automatically generated suffix added to name of markers
00160   };
00161 
00162   class InteractionHandler;
00163 
00167   typedef boost::function<void(InteractionHandler*, bool)> InteractionHandlerCallbackFn;
00168 
00174   class InteractionHandler
00175   {
00176   public:
00177 
00178     InteractionHandler(const std::string &name,
00179                        const robot_state::RobotState &kstate,
00180                        const boost::shared_ptr<tf::Transformer> &tf = boost::shared_ptr<tf::Transformer>());
00181     InteractionHandler(const std::string &name,
00182                        const robot_model::RobotModelConstPtr &kmodel,
00183                        const boost::shared_ptr<tf::Transformer> &tf = boost::shared_ptr<tf::Transformer>());
00184 
00185     virtual ~InteractionHandler()
00186     {
00187     }
00188 
00189     const std::string& getName() const
00190     {
00191       return name_;
00192     }
00193 
00194     robot_state::RobotStateConstPtr getState() const;
00195     void setState(const robot_state::RobotState& kstate);
00196 
00197     void setUpdateCallback(const InteractionHandlerCallbackFn &callback)
00198     {
00199       update_callback_ = callback;
00200     }
00201 
00202     const InteractionHandlerCallbackFn& getUpdateCallback() const
00203     {
00204       return update_callback_;
00205     }
00206 
00207     void setStateValidityCallback(const robot_state::StateValidityCallbackFn &callback)
00208     {
00209       state_validity_callback_fn_ = callback;
00210     }
00211 
00212     const robot_state::StateValidityCallbackFn& getStateValidityCallback() const
00213     {
00214       return state_validity_callback_fn_;
00215     }
00216 
00217     void setIKTimeout(double timeout)
00218     {
00219       ik_timeout_ = timeout;
00220     }
00221 
00222     double getIKTimeout() const
00223     {
00224       return ik_timeout_;
00225     }
00226 
00227     void setIKAttempts(unsigned int attempts)
00228     {
00229       ik_attempts_ = attempts;
00230     }
00231 
00232     unsigned int getIKAttempts() const
00233     {
00234       return ik_attempts_;
00235     }
00236     
00237     const kinematics::KinematicsQueryOptions& getKinematicsQueryOptions() const
00238     {
00239       return kinematics_query_options_;
00240     }
00241 
00242     void setKinematicsQueryOptions(const kinematics::KinematicsQueryOptions &opt)
00243     {
00244       kinematics_query_options_ = opt;
00245     }    
00246     
00247     void setMeshesVisible(bool visible)
00248     {
00249       display_meshes_ = visible;
00250     }
00251 
00252     bool getMeshesVisible() const
00253     {
00254       return display_meshes_;
00255     }
00256 
00257     void setControlsVisible(bool visible)
00258     {
00259       display_controls_ = visible;
00260     }
00261 
00262     bool getControlsVisible() const
00263     {
00264       return display_controls_;
00265     }
00266 
00271     void setPoseOffset(const RobotInteraction::EndEffector& eef, const geometry_msgs::Pose& m);
00272 
00277     void setPoseOffset(const RobotInteraction::Joint& eef, const geometry_msgs::Pose& m);
00278 
00284     bool getPoseOffset(const RobotInteraction::EndEffector& eef, geometry_msgs::Pose& m);
00285 
00291     bool getPoseOffset(const RobotInteraction::Joint& vj, geometry_msgs::Pose& m);
00292 
00295     void clearPoseOffset(const RobotInteraction::EndEffector& eef);
00296 
00299     void clearPoseOffset(const RobotInteraction::Joint& vj);
00300 
00302     void clearPoseOffsets();
00303 
00307     void setMenuHandler(const boost::shared_ptr<interactive_markers::MenuHandler>& mh);
00308 
00309 
00313     const boost::shared_ptr<interactive_markers::MenuHandler>& getMenuHandler();
00314 
00316     void clearMenuHandler();
00317 
00322     bool getLastEndEffectorMarkerPose(const RobotInteraction::EndEffector& eef, geometry_msgs::PoseStamped& pose);
00323 
00328     bool getLastJointMarkerPose(const RobotInteraction::Joint& vj, geometry_msgs::PoseStamped& pose);
00329 
00332     void clearLastEndEffectorMarkerPose(const RobotInteraction::EndEffector& eef);
00333 
00336     void clearLastJointMarkerPose(const RobotInteraction::Joint& vj);
00337 
00339     void clearLastMarkerPoses();
00340 
00343     virtual void handleEndEffector(const RobotInteraction::EndEffector &eef,
00344                                    const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback);
00345 
00348     virtual void handleJoint(const RobotInteraction::Joint &vj,
00349                              const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback);
00350 
00353     virtual void handleGeneric(const RobotInteraction::Generic &g,
00354                                const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback);
00355 
00357     virtual bool inError(const RobotInteraction::EndEffector& eef) const;
00358 
00360     virtual bool inError(const RobotInteraction::Joint& vj) const;
00361 
00363     virtual bool inError(const RobotInteraction::Generic& g) const;
00364 
00366     void clearError(void);
00367 
00368   protected:
00369 
00370     bool transformFeedbackPose(const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback,
00371                                const geometry_msgs::Pose &offset,
00372                                geometry_msgs::PoseStamped &tpose);
00373 
00374     robot_state::RobotStatePtr getUniqueStateAccess();
00375     void setStateToAccess(robot_state::RobotStatePtr &state);
00376 
00377     std::string name_;
00378     std::string planning_frame_;
00379     robot_state::RobotStatePtr kstate_;
00380     boost::shared_ptr<tf::Transformer> tf_;
00381     std::set<std::string> error_state_;
00382 
00383     // Contains the (user-programmable) pose offset between the end-effector
00384     // parent link (or a virtual joint) and the desired control frame for the
00385     // interactive marker. The offset is expressed in the frame of the parent
00386     // link or virtual joint. For example, on a PR2 an offset of +0.20 along
00387     // the x-axis will move the center of the 6-DOF interactive marker from
00388     // the wrist to the finger tips.
00389     std::map<std::string, geometry_msgs::Pose> offset_map_;
00390 
00391     // Contains the most recent poses received from interactive marker feedback,
00392     // with the offset removed (e.g. in theory, coinciding with the end-effector
00393     // parent or virtual joint). This allows a user application to query for the
00394     // interactive marker pose (which could be useful for robot control using
00395     // gradient-based methods) even when the IK solver failed to find a valid
00396     // robot state that satisfies the feedback pose.
00397     std::map<std::string, geometry_msgs::PoseStamped> pose_map_;
00398 
00399     // For adding menus (and associated callbacks) to all the
00400     // end-effector and virtual-joint interactive markers
00401     boost::shared_ptr<interactive_markers::MenuHandler> menu_handler_;
00402 
00403     // Called when the RobotState maintained by the handler changes.  The caller may, for example, redraw the robot at the new state.
00404     // handler is the handler that changed.
00405     // error_state_changed is true if an end effector's error state may have changed.
00406     boost::function<void(InteractionHandler* handler, bool error_state_changed)> update_callback_;
00407 
00408     robot_state::StateValidityCallbackFn state_validity_callback_fn_;
00409     double ik_timeout_;
00410     unsigned int ik_attempts_;
00411 
00412     // additional options for kinematics queries
00413     kinematics::KinematicsQueryOptions kinematics_query_options_;
00414     
00415     bool display_meshes_;
00416     bool display_controls_;
00417 
00418   private:
00419 
00420     mutable boost::mutex state_lock_;
00421     mutable boost::condition_variable state_available_condition_;
00422     boost::mutex pose_map_lock_;
00423     boost::mutex offset_map_lock_;
00424 
00425     void setup();
00426   };
00427 
00428   typedef boost::shared_ptr<InteractionHandler> InteractionHandlerPtr;
00429   typedef boost::shared_ptr<const InteractionHandler> InteractionHandlerConstPtr;
00430 
00431   RobotInteraction(const robot_model::RobotModelConstPtr &kmodel, const std::string &ns = "");
00432   virtual ~RobotInteraction();
00433 
00434   const std::string& getServerTopic(void) const
00435   {
00436     return topic_;
00437   }
00438 
00439   // add an interactive marker.
00440   // construct - a callback to construct the marker.  See comment on InteractiveMarkerConstructorFn above.
00441   // update - Called when the robot state changes.  Updates the marker pose.  Optional.  See comment on InteractiveMarkerUpdateFn above.
00442   // process - called when the marker moves.  Updates the robot state.  See comment on ProcessFeedbackFn above.
00443   void addActiveComponent(const InteractiveMarkerConstructorFn &construct,
00444                           const ProcessFeedbackFn &process,
00445                           const InteractiveMarkerUpdateFn &update = InteractiveMarkerUpdateFn(),
00446                           const std::string &name = "");
00447 
00448   // Adds an interactive marker for:
00449   //  - each end effector in the group that can be controller by IK
00450   //  - each floating joint
00451   //  - each planar joint
00452   // If no end effector exists in the robot then adds an interactive marker for the last link in the chain.
00453   void decideActiveComponents(const std::string &group, EndEffectorInteractionStyle style = EEF_6DOF);
00454 
00456   void decideActiveEndEffectors(const std::string &group, EndEffectorInteractionStyle style = EEF_6DOF);
00457 
00459   void decideActiveJoints(const std::string &group);
00460 
00461   // remove all interactive markers.
00462   void clear();
00463 
00464   void addInteractiveMarkers(const InteractionHandlerPtr &handler, const double marker_scale = 0.0);
00465   void updateInteractiveMarkers(const InteractionHandlerPtr &handler);
00466   bool showingMarkers(const InteractionHandlerPtr &handler);
00467 
00468   void publishInteractiveMarkers();
00469   void clearInteractiveMarkers();
00470 
00471   const std::vector<EndEffector>& getActiveEndEffectors() const
00472   {
00473     return active_eef_;
00474   }
00475 
00476   const std::vector<Joint>& getActiveJoints() const
00477   {
00478     return active_vj_;
00479   }
00480 
00481   static bool updateState(robot_state::RobotState &state, const EndEffector &eef, const geometry_msgs::Pose &pose,
00482                           unsigned int attempts, double ik_timeout,
00483                           const robot_state::StateValidityCallbackFn &validity_callback = robot_state::StateValidityCallbackFn(),
00484                           const kinematics::KinematicsQueryOptions &kinematics_query_options = kinematics::KinematicsQueryOptions());
00485   static bool updateState(robot_state::RobotState &state, const Joint &vj, const geometry_msgs::Pose &pose);
00486 
00487 private:
00488 
00489   // return the diameter of the sphere that certainly can enclose the AABB of the links in this group
00490   double computeGroupMarkerSize(const std::string &group);
00491   void computeMarkerPose(const InteractionHandlerPtr &handler, const EndEffector &eef, const robot_state::RobotState &robot_state,
00492                          geometry_msgs::Pose &pose, geometry_msgs::Pose &control_to_eef_tf) const;
00493 
00494   void addEndEffectorMarkers(const InteractionHandlerPtr &handler, const EndEffector& eef, visualization_msgs::InteractiveMarker& im, bool position = true, bool orientation = true);
00495   void addEndEffectorMarkers(const InteractionHandlerPtr &handler, const EndEffector& eef, const geometry_msgs::Pose& offset, visualization_msgs::InteractiveMarker& im, bool position = true, bool orientation = true);
00496   void processInteractiveMarkerFeedback(const visualization_msgs::InteractiveMarkerFeedbackConstPtr& feedback);
00497   void processingThread();
00498   void clearInteractiveMarkersUnsafe();
00499 
00500   boost::scoped_ptr<boost::thread> processing_thread_;
00501   bool run_processing_thread_;
00502 
00503   boost::condition_variable new_feedback_condition_;
00504   std::map<std::string, visualization_msgs::InteractiveMarkerFeedbackConstPtr> feedback_map_;
00505 
00506   robot_model::RobotModelConstPtr robot_model_;
00507 
00508   std::vector<EndEffector> active_eef_;
00509   std::vector<Joint> active_vj_;
00510   std::vector<Generic> active_generic_;
00511 
00512   std::map<std::string, InteractionHandlerPtr> handlers_;
00513   std::map<std::string, std::size_t> shown_markers_;
00514 
00515   // This mutex is locked every time markers are read or updated;
00516   // This includes the active_* arrays and shown_markers_
00517   // Please note that this mutex *MUST NOT* be locked while operations
00518   // on the interative marker server are called because the server
00519   // also locks internally and we could othewrise end up with a problem
00520   // of Thread 1: Lock A,         Lock B, Unlock B, Unloack A
00521   //    Thread 2:         Lock B, Lock A
00522   // => deadlock
00523   boost::mutex marker_access_lock_;
00524 
00525   interactive_markers::InteractiveMarkerServer *int_marker_server_;
00526   std::string topic_;
00527 };
00528 
00529 MOVEIT_CLASS_FORWARD(RobotInteraction);
00530 
00531 }
00532 
00533 #endif


robot_interaction
Author(s): Ioan Sucan
autogenerated on Mon Oct 6 2014 02:33:46