action_detect_door.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  * Software License Agreement (BSD License)
00003  *
00004  *  Copyright (c) 2008, Willow Garage, Inc.
00005  *  All rights reserved.
00006  *
00007  *  Redistribution and use in source and binary forms, with or without
00008  *  modification, are permitted provided that the following conditions
00009  *  are met:
00010  *
00011  *   * Redistributions of source code must retain the above copyright
00012  *     notice, this list of conditions and the following disclaimer.
00013  *   * Redistributions in binary form must reproduce the above
00014  *     copyright notice, this list of conditions and the following
00015  *     disclaimer in the documentation and/or other materials provided
00016  *     with the distribution.
00017  *   * Neither the name of Willow Garage nor the names of its
00018  *     contributors may be used to endorse or promote products derived
00019  *     from this software without specific prior written permission.
00020  *
00021  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00022  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00023  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00024  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00025  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00026  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00027  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00028  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00029  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00030  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00031  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00032  *  POSSIBILITY OF SUCH DAMAGE.
00033  *********************************************************************/
00034 
00035 /* Author: Wim Meeussen */
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 //#include <pr2_robot_actions/set_hokuyo_mode.h>
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   // transform door message to time fixed frame
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   // check where robot is relative to door
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   // set the laser scanner to NON-intensity mode
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   // gets a point cloud from the point_cloud_srv
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   // detect door
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 


pr2_doors_actions
Author(s): Wim Meeussen
autogenerated on Wed Dec 11 2013 14:17:44