Go to the documentation of this file.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 #include <door_handle_detector/DoorsDetectorCloud.h>
00038 #include <door_handle_detector/geometric_helper.h>
00039 #include <pr2_doors_common/door_functions.h>
00040 #include <pr2_laser_snapshotter/BuildCloudAngle.h>
00041
00042 #include "pr2_doors_actions/action_detect_door.h"
00043 #include <pr2_laser_snapshotter/TiltLaserSnapshotAction.h>
00044 #include <actionlib/client/simple_action_client.h>
00045
00046
00047 using namespace ros;
00048 using namespace std;
00049 using namespace door_handle_detector;
00050 using namespace pr2_doors_common;
00051 using namespace actionlib;
00052
00053 static const string fixed_frame = "odom_combined";
00054
00055
00056
00057
00058 DetectDoorAction::DetectDoorAction(tf::TransformListener& tf):
00059 tf_(tf),
00060 action_server_(ros::NodeHandle(),
00061 "detect_door",
00062 boost::bind(&DetectDoorAction::execute, this, _1)),
00063 laserSnapshotActionClient_("point_cloud_action/single_sweep_cloud")
00064 {};
00065
00066
00067 DetectDoorAction::~DetectDoorAction(){};
00068
00069
00070 void DetectDoorAction::execute(const door_msgs::DoorGoalConstPtr& goal)
00071 {
00072 ROS_INFO("DetectDoorAction: execute");
00073
00074
00075 door_msgs::Door goal_tr;
00076 if (!transformTo(tf_, fixed_frame, goal->door, goal_tr, fixed_frame)){
00077 ROS_ERROR("DetectDoorAction: Could not tranform door message from '%s' to '%s' at time %f",
00078 goal->door.header.frame_id.c_str(), fixed_frame.c_str(), goal->door.header.stamp.toSec());
00079 action_server_.setPreempted();
00080 return;
00081 }
00082 ROS_INFO("DetectDoorAction: goal message transformed to frame %s", fixed_frame.c_str());
00083 door_msgs::Door result_laser;
00084 if (!laserDetection(goal_tr, result_laser)){
00085 ROS_ERROR("DetectDoorAction: Aborted");
00086 action_server_.setPreempted();
00087 return;
00088 }
00089
00090 if (getDoorDir(result_laser) < 0){
00091 ROS_INFO("Detected door that opens towards robot");
00092 action_server_.setPreempted();
00093 return;
00094 }
00095
00096 ROS_INFO("DetectDoorAction: Succeeded");
00097 action_result_.door = result_laser;
00098 action_server_.setSucceeded(action_result_);
00099 }
00100
00101 bool DetectDoorAction::laserDetection(const door_msgs::Door& door_in, door_msgs::Door& door_out)
00102 {
00103
00104 if (action_server_.isPreemptRequested()) return false;
00105
00106 if (!tf_.waitForTransform("base_footprint", "laser_tilt_link", ros::Time(), ros::Duration().fromSec(5.0))){
00107 ROS_ERROR("DetectDoorAction: error getting transform from 'base_footprint' to 'laser_tilt_link'");
00108 return false;
00109 }
00110 tf::StampedTransform tilt_stage;
00111 tf_.lookupTransform("base_footprint", "laser_tilt_link", ros::Time(), tilt_stage);
00112 double laser_height = tilt_stage.getOrigin()[2];
00113 tf::Stamped<tf::Vector3> doorpoint(tf::Vector3((door_in.frame_p1.x+door_in.frame_p2.x)/2.0,
00114 (door_in.frame_p1.y+door_in.frame_p2.y)/2.0,
00115 (door_in.frame_p1.z+door_in.frame_p2.z)/2.0),
00116 ros::Time(), door_in.header.frame_id);
00117
00118 if (action_server_.isPreemptRequested()) return false;
00119
00120 if (!tf_.waitForTransform("base_footprint", doorpoint.frame_id_, ros::Time(), ros::Duration().fromSec(5.0))){
00121 ROS_ERROR("DetectDoorAction: error getting transform from '%s' to 'base_footprint'", doorpoint.frame_id_.c_str());
00122 return false;
00123 }
00124
00125 tf_.transformPoint("base_footprint", doorpoint, doorpoint);
00126 doorpoint[2] = 0;
00127 double dist = doorpoint.length();
00128 double door_bottom = -0.5;
00129 double door_top = 2.5;
00130 ROS_INFO("DetectDoorAction: tilt laser is at height %f, and door at distance %f", laser_height, dist);
00131
00132
00133 NodeHandle node;
00134 bool use_sim_time;
00135 node.param("use_sim_time", use_sim_time, false);
00136 if (!use_sim_time){
00137 ROS_WARN("dynamic_reconfigure of tilt_hokuyo_node is commented out, awaiting #3894 from simulation");
00138 system("rosrun dynamic_reconfigure dynparam set /tilt_hokuyo_node '{ intensity: false }'");
00139 system("rosrun dynamic_reconfigure dynparam set /tilt_hokuyo_node '{ skip: 0 }'");
00140 }
00141
00142
00143 if (action_server_.isPreemptRequested()) return false;
00144
00145 ROS_INFO("DetectDoorAction: get a point cloud from the door");
00146 pr2_laser_snapshotter::TiltLaserSnapshotGoal goalMsg;
00147
00148 goalMsg.angle_begin = -atan2(door_top - laser_height, dist);
00149 goalMsg.angle_end = atan2(laser_height - door_bottom, dist);
00150 goalMsg.duration = 10.0;
00151
00152
00153 laserSnapshotActionClient_.waitForServer();
00154 laserSnapshotActionClient_.sendGoal(goalMsg);
00155 laserSnapshotActionClient_.waitForResult();
00156
00157 if (laserSnapshotActionClient_.getState() != actionlib::SimpleClientGoalState::SUCCEEDED)
00158 {
00159 ROS_ERROR("DetectDoorAction: failed to get point cloud for door detection");
00160 return false;
00161 }
00162 pr2_laser_snapshotter::TiltLaserSnapshotResultConstPtr res_pointcloud = laserSnapshotActionClient_.getResult();
00163
00164
00165 if (action_server_.isPreemptRequested()) return false;
00166
00167 ROS_INFO("DetectDoorAction: detect the door in a pointcloud of size %u", (unsigned int)res_pointcloud->cloud.points.size());
00168 door_handle_detector::DoorsDetectorCloud::Request req_doordetect;
00169 door_handle_detector::DoorsDetectorCloud::Response res_doordetect;
00170 req_doordetect.door = door_in;
00171 req_doordetect.cloud = res_pointcloud->cloud;
00172
00173 if (!ros::service::call("doors_detector_cloud", req_doordetect, res_doordetect)){
00174 ROS_ERROR("DetectDoorAction: failed to detect a door");
00175 return false;
00176 }
00177
00178 door_out = res_doordetect.doors[0];
00179 return true;
00180 }
00181