00001 #include <cmath>
00002 #include <ros/ros.h>
00003 #include <tf/transform_listener.h>
00004 #include <actionlib/client/simple_action_client.h>
00005 #include <pr2_controllers_msgs/PointHeadAction.h>
00006 #include <std_srvs/Empty.h>
00007
00008
00009 typedef actionlib::SimpleActionClient<pr2_controllers_msgs::PointHeadAction> PointHeadClient;
00010
00011 class RobotHead
00012 {
00013 private:
00014 PointHeadClient point_head_client_;
00015 std::string frame_to_point;
00016 std::string frame_to_track;
00017 tf::TransformListener listener;
00018 bool active_;
00019 bool found_;
00020 ros::Subscriber pose_sub_;
00021 ros::ServiceServer service_on_, service_off_;
00022
00023 public:
00025 RobotHead() : point_head_client_("/head_traj_controller/point_head_action", true),
00026 frame_to_point("/head_mount_kinect_rgb_link"),
00027 frame_to_track("/checkerboard_0"),
00028 active_(false),
00029 found_(false)
00030 {
00031 ros::NodeHandle n;
00032 pose_sub_ = n.subscribe("pose0", 2, &RobotHead::track, this);
00033 service_on_ = n.advertiseService("search_and_track_checkerboard_on", &RobotHead::switchActive, this);
00034 service_off_ = n.advertiseService("search_and_track_checkerboard_off", &RobotHead::switchInactive, this);
00035
00036 ros::NodeHandle nh("~");
00037 nh.param<bool>("start_active", active_, active_);
00038
00039
00040 while(!point_head_client_.waitForServer(ros::Duration(1.0))){
00041 ROS_INFO_THROTTLE(10, "Waiting for the point_head_action server to come up");
00042 }
00043
00044 ROS_INFO_COND(active_, "Searching for checkerboard. Deactivate by service call");
00045 ROS_INFO_COND(!active_, "Search for checkerboard available. Activate by service call");
00046 }
00047
00048 void lookAt(geometry_msgs::PoseStamped pose_stamped)
00049 {
00050 if(!active_)return;
00051 found_ = true;
00052
00053 pr2_controllers_msgs::PointHeadGoal goal;
00054 geometry_msgs::PointStamped point_stamped;
00055 point_stamped.header = pose_stamped.header;
00056 point_stamped.point = pose_stamped.pose.position;
00057 goal.target = point_stamped;
00058 goal.pointing_frame = this->frame_to_point;
00059
00060
00061 goal.min_duration = ros::Duration(1.5);
00062
00063
00064 goal.max_velocity = 0.25;
00065
00066
00067 point_head_client_.sendGoal(goal);
00068 point_head_client_.waitForResult(ros::Duration(5));
00069 }
00070
00072 void lookAt(std::string frame_id, double x, double y, double z, double max_wait_seconds = 10.0)
00073 {
00074 if(!active_)return;
00075
00076 pr2_controllers_msgs::PointHeadGoal goal;
00077
00078
00079 geometry_msgs::PointStamped point;
00080 point.header.frame_id = frame_id;
00081 point.point.x = x; point.point.y = y; point.point.z = z;
00082 goal.target = point;
00083
00084
00085
00086 goal.pointing_frame = this->frame_to_point;
00087
00088
00089 goal.min_duration = ros::Duration(0.5);
00090
00091
00092 goal.max_velocity = 0.25;
00093
00094
00095 point_head_client_.sendGoal(goal);
00096 ros::Time start = ros::Time::now();
00097 while(ros::ok() && !point_head_client_.waitForResult(ros::Duration(0.5))){
00098 if(start < (ros::Time::now() - ros::Duration(max_wait_seconds))){
00099 break;
00100 }
00101 ros::spinOnce();
00102 }
00103 }
00104
00105 void track(geometry_msgs::PoseStamped ps = geometry_msgs::PoseStamped() ){
00106
00107 if(active_) this->lookAt(ps);
00108 }
00109
00111 void searchAndSpin(float step)
00112 {
00113 srand(10);
00114 float radius = 2.0;
00115 float height = -0.40;
00116 while (ros::ok())
00117 {
00118 ros::spinOnce();
00119 ros::Duration(1.0).sleep();
00120 if(!active_)
00121 continue;
00122
00123 if(listener.waitForTransform(frame_to_track, frame_to_point, ros::Time::now()-ros::Duration(0.1), ros::Duration(4.0))){
00124 if(!found_){
00125 ROS_INFO("Transformable frame %s", frame_to_track.c_str());
00126 found_=true;
00127 }
00128 continue;
00129 }
00130 else {
00131 found_ = false;
00132 }
00133 lookAt("/head_pan_link", radius, 0.0, height);
00134 if(listener.waitForTransform(frame_to_track, frame_to_point, ros::Time::now()-ros::Duration(0.1), ros::Duration(4.0))){
00135 if(!found_){
00136 ROS_INFO("Transformable frame %s", frame_to_track.c_str());
00137 found_=true;
00138 }
00139 continue;
00140 }
00141 else {
00142 found_ = false;
00143 }
00144
00145 lookAt("/torso_lift_link", radius*cos(step/180.0*M_PI),radius*sin(step/180.0*M_PI), height);
00146 if(listener.waitForTransform(frame_to_track, frame_to_point, ros::Time::now()-ros::Duration(0.1), ros::Duration(4.0))){
00147 if(!found_){
00148 ROS_INFO("Transformable frame %s", frame_to_track.c_str());
00149 found_=true;
00150 }
00151 continue;
00152 }
00153 else {
00154 found_ = false;
00155 }
00156
00157 step *= -1.0;
00158 height = (rand() % 100)/100.0 - 0.5;
00159 height *= height;
00160 radius = (rand() % 100)/100.0 + 1.0;
00161 ROS_INFO("Searching frame %s", frame_to_track.c_str());
00162 }
00163 }
00164
00165 bool switchActive(std_srvs::Empty::Request &req,
00166 std_srvs::Empty::Response &res )
00167 {
00168 active_ = true;
00169 lookAt("/torso_lift_link", 0.8, 0.3, 0.2);
00170
00171 return true;
00172 }
00173 bool switchInactive(std_srvs::Empty::Request &req,
00174 std_srvs::Empty::Response &res )
00175 {
00176 active_ = false;
00177 return true;
00178 }
00179 };
00180
00181
00182 int main(int argc, char** argv)
00183 {
00184
00185 ros::init(argc, argv, "look_around");
00186
00187 RobotHead head;
00188 head.searchAndSpin(30);
00189
00190 }
00191