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 #include <ros/ros.h>
00035 #include <math.h>
00036
00037 #include <interactive_markers/interactive_marker_server.h>
00038 #include <interactive_markers/menu_handler.h>
00039
00040 #include <object_manipulator/tools/mechanism_interface.h>
00041 #include <object_manipulator/tools/msg_helpers.h>
00042
00043 #include <boost/thread.hpp>
00044 #include <tf/transform_listener.h>
00045 #include <boost/thread/recursive_mutex.hpp>
00046
00047 #include <actionlib/client/simple_action_client.h>
00048 #include <actionlib/server/simple_action_server.h>
00049
00050 #include <pr2_object_manipulation_msgs/GetNavPoseAction.h>
00051 #include <pr2_object_manipulation_msgs/CameraFocus.h>
00052
00053 #include <sensor_msgs/point_cloud_conversion.h>
00054
00055 #include "eigen_conversions/eigen_msg.h"
00056
00057 #include "eigen3/Eigen/Geometry"
00058 #include "pcl/io/pcd_io.h"
00059 #include "pcl/point_types.h"
00060 #include "pcl_ros/transforms.h"
00061
00062 #include <interactive_marker_helpers/interactive_marker_helpers.h>
00063
00064 #include <geometry_msgs/PointStamped.h>
00065 #include <geometry_msgs/PoseStamped.h>
00066
00067
00068 using namespace object_manipulator;
00069 using namespace visualization_msgs;
00070 using namespace interactive_markers;
00071 using namespace pr2_object_manipulation_msgs;
00072 using namespace im_helpers;
00073
00075
00076
00079 class BasePoseAction
00080 {
00081 protected:
00082
00083
00084
00085 geometry_msgs::PoseStamped base_pose_;
00086 geometry_msgs::PoseStamped control_offset_;
00087
00088 bool active_;
00089
00090 int interface_number_;
00091 int task_number_;
00092
00093 bool testing_planned_grasp_;
00094 int tested_grasp_index_;
00095 bool testing_current_grasp_;
00096 double max_direct_move_radius_;
00097
00098 ros::NodeHandle nh_;
00099 ros::NodeHandle pnh_;
00100 ros::Subscriber sub_seed_pose_;
00101 ros::Subscriber sub_seed_point_;
00102
00103 ros::Timer fast_update_timer_;
00104 ros::Timer slow_update_timer_;
00105 InteractiveMarkerServer server_;
00106
00107 ros::Publisher pub_focus_;
00108
00109 MenuHandler menu_controls_;
00110 MenuHandler::EntryHandle accept_handle_;
00111 MenuHandler::EntryHandle cancel_handle_;
00112 MenuHandler::EntryHandle focus_handle_;
00113
00114 tf::TransformListener tfl_;
00115
00116 object_manipulator::MechanismInterface mechanism_;
00117
00118 std::string get_pose_name_;
00119 actionlib::SimpleActionServer<pr2_object_manipulation_msgs::GetNavPoseAction> get_pose_server_;
00120
00121 public:
00122
00123 BasePoseAction() :
00124 active_(false),
00125 max_direct_move_radius_(10.0),
00126 nh_("/"),
00127 pnh_("~"),
00128 server_(ros::names::resolve("pr2_nav_marker_control"), "nav_action", false),
00129 tfl_(nh_),
00130 get_pose_name_(ros::this_node::getName()),
00131 get_pose_server_(nh_, get_pose_name_, false)
00132 {
00133 ROS_INFO( "pr2_interactive_base_pose_action is starting up." );
00134
00135 ros::Duration(1.0).sleep();
00136
00137 nh_.param<int>("interactive_grasping/interface_number", interface_number_, 0);
00138 if (!interface_number_) ROS_WARN("No interface number specified for grasping study; using default configuration");
00139 else ROS_INFO("Using interface number %d for grasping study", interface_number_);
00140 nh_.param<int>("interactive_grasping/task_number", task_number_, 0);
00141 if (!task_number_) ROS_WARN("No task number specified for grasping study; using default configuration");
00142 else ROS_INFO("Using task number %d for grasping study", task_number_);
00143
00144
00145
00146
00147 geometry_msgs::PoseStamped ps;
00148 ps.header.frame_id = "base_link";
00149 server_.insert(makeButtonBox( "test_box", ps, 0.01, false, false));
00150
00151 pub_focus_ = nh_.advertise<pr2_object_manipulation_msgs::CameraFocus>("camera_focus", 1);
00152
00153 fast_update_timer_ = nh_.createTimer(ros::Duration(0.05), boost::bind( &BasePoseAction::fast_update, this ) );
00154
00155 sub_seed_pose_ = nh_.subscribe<geometry_msgs::PoseStamped>("/cloud_click_point", 1, boost::bind(&BasePoseAction::setSeedPoseCallback, this, _1));
00156 sub_seed_point_ = nh_.subscribe<geometry_msgs::PointStamped>("/rviz/navigate_to", 1, boost::bind(&BasePoseAction::setSeedPointCallback, this, _1));
00157
00158
00159 initMenus();
00160
00161
00162 get_pose_server_.registerGoalCallback( boost::bind(&BasePoseAction::goalCB, this));
00163 get_pose_server_.registerPreemptCallback( boost::bind(&BasePoseAction::preemptCB, this));
00164
00165 get_pose_server_.start();
00166 }
00167
00168 ~BasePoseAction()
00169 {
00170 }
00171
00172 void setSeedPoseCallback(const geometry_msgs::PoseStampedConstPtr &seedPose)
00173 {
00174 if(!active_) return;
00175 ROS_DEBUG("Setting seed.");
00176 base_pose_ = *seedPose;
00177 base_pose_.pose.orientation = geometry_msgs::Quaternion();
00178
00179 updateSeed();
00180 }
00181
00182 void setSeedPointCallback(const geometry_msgs::PointStampedConstPtr &seedPoint)
00183 {
00184 if(!active_) return;
00185 ROS_DEBUG("Setting seed point.");
00186 base_pose_.pose.position= seedPoint->point;
00187 base_pose_.pose.orientation = geometry_msgs::Quaternion();
00188
00189 updateSeed();
00190 }
00191
00192 void updateSeed()
00193 {
00194 initMarkers();
00195 }
00196
00197
00198
00200 void setIdle(){
00201 active_ = false;
00202 server_.clear();
00203 }
00204
00205
00207 void goalCB()
00208 {
00209 active_ = true;
00210 ROS_INFO("pr2_interactive_nav_action_called!");
00211 pr2_object_manipulation_msgs::GetNavPoseGoal goal = *get_pose_server_.acceptNewGoal();
00212
00213 if (goal.starting_pose.pose.orientation.x == 0 &&
00214 goal.starting_pose.pose.orientation.y == 0 &&
00215 goal.starting_pose.pose.orientation.z == 0 &&
00216 goal.starting_pose.pose.orientation.w == 0 )
00217 {
00218 ROS_DEBUG("Empty pose passed in; using default");
00219 base_pose_ = getDefaultPose();
00220 }
00221 else
00222 {
00223 base_pose_ = goal.starting_pose;
00224 }
00225
00226 if (get_pose_server_.isPreemptRequested())
00227 {
00228 preemptCB();
00229 return;
00230 }
00231 if(goal.max_distance > 0)
00232 max_direct_move_radius_ = goal.max_distance;
00233 else
00234 max_direct_move_radius_ = 1E6;
00235
00236 initMarkers();
00237 }
00238
00239
00241 void preemptCB()
00242 {
00243 ROS_INFO("%s: Preempted", get_pose_name_.c_str());
00244
00245 get_pose_server_.setPreempted();
00246 setIdle();
00247 }
00248
00251 void updatePoses()
00252 {
00253 server_.setPose("meshes", base_pose_.pose, base_pose_.header);
00254 }
00255
00256 geometry_msgs::PoseStamped getDefaultPose()
00257 {
00258 geometry_msgs::PoseStamped ps;
00259 ps.header.stamp = ros::Time(0);
00260 ps.header.frame_id = "base_link";
00261 ps.pose.orientation.w = 1;
00262 return ps;
00263 }
00264
00265
00266
00267
00270 void initMarkers()
00271 {
00272 initMeshMarkers();
00273 initControlMarkers();
00274 }
00275
00276 void initMeshMarkers()
00277 {
00278 }
00279
00280 void initControlMarkers()
00281 {
00282 geometry_msgs::PoseStamped ps = base_pose_;
00283 ps.header.stamp = ros::Time(0);
00284
00285
00286
00287
00288 std::vector< std::string > mesh_paths, mesh_frames;
00289 mesh_paths.push_back("package://pr2_description/meshes/base_v0/base.dae");
00290 mesh_frames.push_back("base_link");
00291 mesh_paths.push_back("package://pr2_description/meshes/torso_v0/torso_lift.dae");
00292 mesh_frames.push_back("torso_lift_link");
00293 mesh_paths.push_back("package://pr2_description/meshes/shoulder_v0/shoulder_pan.dae");
00294 mesh_frames.push_back("r_shoulder_pan_link");
00295 mesh_paths.push_back("package://pr2_description/meshes/shoulder_v0/shoulder_pan.dae");
00296 mesh_frames.push_back("l_shoulder_pan_link");
00297 mesh_paths.push_back("package://pr2_description/meshes/shoulder_v0/shoulder_lift.dae");
00298 mesh_frames.push_back("r_shoulder_lift_link");
00299 mesh_paths.push_back("package://pr2_description/meshes/shoulder_v0/shoulder_lift.dae");
00300 mesh_frames.push_back("l_shoulder_lift_link");
00301 mesh_paths.push_back("package://pr2_description/meshes/upper_arm_v0/upper_arm.dae");
00302 mesh_frames.push_back("r_upper_arm_link");
00303 mesh_paths.push_back("package://pr2_description/meshes/upper_arm_v0/upper_arm.dae");
00304 mesh_frames.push_back("l_upper_arm_link");
00305 mesh_paths.push_back("package://pr2_description/meshes/forearm_v0/forearm.dae");
00306 mesh_frames.push_back("r_forearm_link");
00307 mesh_paths.push_back("package://pr2_description/meshes/forearm_v0/forearm.dae");
00308 mesh_frames.push_back("l_forearm_link");
00309
00310
00311 mesh_paths.push_back("package://pr2_description/meshes/gripper_v0/gripper_palm.dae");
00312 mesh_frames.push_back("r_gripper_palm_link");
00313 mesh_paths.push_back("package://pr2_description/meshes/gripper_v0/upper_finger_r.stl");
00314 mesh_frames.push_back("r_gripper_r_finger_link");
00315 mesh_paths.push_back("package://pr2_description/meshes/gripper_v0/upper_finger_l.stl");
00316 mesh_frames.push_back("r_gripper_l_finger_link");
00317 mesh_paths.push_back("package://pr2_description/meshes/gripper_v0/finger_tip_r.stl");
00318 mesh_frames.push_back("r_gripper_r_finger_tip_link");
00319 mesh_paths.push_back("package://pr2_description/meshes/gripper_v0/finger_tip_l.stl");
00320 mesh_frames.push_back("r_gripper_l_finger_tip_link");
00321
00322
00323
00324 mesh_paths.push_back("package://pr2_description/meshes/gripper_v0/gripper_palm.dae");
00325 mesh_frames.push_back("l_gripper_palm_link");
00326 mesh_paths.push_back("package://pr2_description/meshes/gripper_v0/upper_finger_r.stl");
00327 mesh_frames.push_back("l_gripper_r_finger_link");
00328 mesh_paths.push_back("package://pr2_description/meshes/gripper_v0/upper_finger_l.stl");
00329 mesh_frames.push_back("l_gripper_l_finger_link");
00330 mesh_paths.push_back("package://pr2_description/meshes/gripper_v0/finger_tip_r.stl");
00331 mesh_frames.push_back("l_gripper_r_finger_tip_link");
00332 mesh_paths.push_back("package://pr2_description/meshes/gripper_v0/finger_tip_l.stl");
00333 mesh_frames.push_back("l_gripper_l_finger_tip_link");
00334
00335
00336 mesh_paths.push_back("package://pr2_description/meshes/head_v0/head_pan.dae");
00337 mesh_frames.push_back("head_pan_link");
00338 mesh_paths.push_back("package://pr2_description/meshes/head_v0/head_tilt.dae");
00339 mesh_frames.push_back("head_tilt_link");
00340
00341
00342 if(mesh_paths.size() != mesh_frames.size()) ROS_ERROR("The number of mesh paths and mesh frame_ids is not equal!");
00343
00344 std::vector< geometry_msgs::PoseStamped > mesh_poses;
00345 for(size_t i = 0; i < mesh_paths.size(); i++)
00346 {
00347 geometry_msgs::PoseStamped ps;
00348 ps.header.stamp = ros::Time(0);
00349 ps.header.frame_id = mesh_frames[i];
00350 ps.pose.orientation.w = 1;
00351 tfl_.waitForTransform("base_link", ps.header.frame_id, ps.header.stamp,ros::Duration(3.0));
00352 try
00353 {
00354 tfl_.transformPose("base_link", ps, ps);
00355 }
00356 catch (tf::TransformException ex)
00357 {
00358 ROS_ERROR("pr2_interactive_nav_action: failed to transform from %s to base_link! Skipping mesh part", ps.header.frame_id.c_str());
00359 continue;
00360 }
00361 mesh_poses.push_back(ps);
00362 }
00363
00364 server_.insert(makePosedMultiMeshMarker( "pose_controls", ps, mesh_poses, mesh_paths, 1.03, false),
00365 boost::bind( &BasePoseAction::poseControlCB, this, _1));
00366 menu_controls_.apply(server_, "pose_controls");
00367 }
00368
00369
00370 protected:
00371
00372
00374 void fast_update()
00375 {
00376
00377 server_.applyChanges();
00378 }
00379
00380 void slow_update()
00381 {
00382 }
00383
00384
00386 void acceptCB()
00387 {
00388 setIdle();
00389 pr2_object_manipulation_msgs::GetNavPoseResult result;
00390 base_pose_.header.stamp = ros::Time::now();
00391 result.pose = base_pose_;
00392 get_pose_server_.setSucceeded(result);
00393 }
00394
00396 void cancelCB()
00397 {
00398 get_pose_server_.setAborted();
00399 setIdle();
00400 }
00401
00403 void focusCB()
00404 {
00405 pr2_object_manipulation_msgs::CameraFocus msg;
00406 msg.focal_point.point = base_pose_.pose.position;
00407 msg.focal_point.header = base_pose_.header;
00408 pub_focus_.publish(msg);
00409 }
00410
00412 void poseMeshCB( const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback )
00413 {
00414 }
00415
00416 geometry_msgs::PoseStamped clipToRadius(const geometry_msgs::PoseStamped &input, const float &radius)
00417 {
00418 geometry_msgs::PoseStamped ps;
00419 try
00420 {
00421 tfl_.waitForTransform(input.header.frame_id, "base_link", input.header.stamp, ros::Duration(5.0));
00422 tfl_.transformPose("base_link", input, ps);
00423 tf::Vector3 pose_center;
00424 tf::pointMsgToTF(ps.pose.position, pose_center);
00425 float stored_z = pose_center.z();
00426 pose_center.setZ(0);
00427 float length = pose_center.length();
00428 if(length > radius)
00429 {
00430 pose_center = radius / length * pose_center;
00431 pose_center.setZ(stored_z);
00432 tf::pointTFToMsg(pose_center, ps.pose.position);
00433 }
00434 ps.header.stamp = ros::Time(0);
00435 if( tfl_.canTransform("map", ps.header.frame_id, ros::Time(0)))
00436 {
00437 tfl_.transformPose("map", ps, ps);
00438 }
00439 else if( tfl_.canTransform("odom_combined", ps.header.frame_id, ros::Time(0)))
00440 {
00441 tfl_.transformPose("odom_combined", ps, ps);
00442 }
00443 else if( tfl_.canTransform(input.header.frame_id, ps.header.frame_id, ros::Time(0)))
00444 {
00445 tfl_.transformPose(input.header.frame_id, ps, ps);
00446 }
00447 else
00448 {
00449 ROS_ERROR("TF could not transform from map, odom_combined, or %s to %s!! clipToRadius failed\n", input.header.frame_id.c_str(), ps.header.frame_id.c_str());
00450 }
00451 }
00452 catch (tf::TransformException ex)
00453 {
00454 ROS_ERROR("pr2_interactive_nav_action: failed to transform from %s to base_link!", input.header.frame_id.c_str());
00455 }
00456 return ps;
00457 }
00458
00460 void poseControlCB( const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback )
00461 {
00462 ros::Time now = ros::Time(0);
00463
00464 switch ( feedback->event_type )
00465 {
00466 case visualization_msgs::InteractiveMarkerFeedback::MOUSE_DOWN:
00467 break;
00468 case visualization_msgs::InteractiveMarkerFeedback::MOUSE_UP:
00469 base_pose_.pose = feedback->pose;
00470 base_pose_.header = feedback->header;
00471 ROS_DEBUG_STREAM("MOUSE_UP base_pose before clipping is\n" << base_pose_);
00472 base_pose_ = clipToRadius(base_pose_, max_direct_move_radius_);
00473 ROS_DEBUG_STREAM("MOUSE_UP base_pose after clipping is\n" << base_pose_);
00474 initMarkers();
00475 break;
00476 case visualization_msgs::InteractiveMarkerFeedback::POSE_UPDATE:
00477 ROS_DEBUG_STREAM("POSE_UPDATE in frame " << feedback->header.frame_id << std::endl << feedback->pose);
00478 base_pose_.pose = feedback->pose;
00479 base_pose_.header = feedback->header;
00480 updatePoses();
00481 break;
00482 }
00483 }
00484
00486 void initMenus()
00487 {
00488 accept_handle_ = menu_controls_.insert("Accept", boost::bind( &BasePoseAction::acceptCB, this ) );
00489 cancel_handle_ = menu_controls_.insert("Cancel", boost::bind( &BasePoseAction::cancelCB, this ) );
00490 focus_handle_ = menu_controls_.insert("Focus camera", boost::bind( &BasePoseAction::focusCB, this ) );
00491 }
00492 };
00493
00494 int main(int argc, char** argv)
00495 {
00496 ros::init(argc, argv, "pr2_interactive_pose_select_action");
00497 BasePoseAction base_pose_action;
00498
00499 ros::Duration(1.0).sleep();
00500
00501 ros::spin();
00502 }