Go to the documentation of this file.00001 #include <stdio.h>
00002 #include <math.h>
00003
00004 #include "geometry_msgs/PoseStamped.h"
00005 #include <geometry_msgs/Twist.h>
00006 #include "std_msgs/String.h"
00007
00008 #include <pcl_ros/point_cloud.h>
00009 #include <pcl/point_types.h>
00010 #include <opencv2/highgui/highgui.hpp>
00011 #include <cv_bridge/cv_bridge.h>
00012 #include <image_transport/image_transport.h>
00013 #include <sensor_msgs/image_encodings.h>
00014
00015 #include "ScavTaskHumanFollowing.h"
00016
00017 namespace scav_task_human_following {
00018
00019 sensor_msgs::ImageConstPtr wb_image;
00020 sensor_msgs::ImageConstPtr wb_image_candidate;
00021 std::string wb_path_to_image;
00022
00023
00024 ScavTaskHumanFollowing::ScavTaskHumanFollowing(ros::NodeHandle *nh, std::string dir) : ac("move_base", true)
00025 {
00026 this->nh = nh;
00027 directory = dir;
00028 task_description = "following a human for a distance";
00029 task_name = "Human following";
00030 certificate = "";
00031
00032 while (!ac.waitForServer(ros::Duration(5.0)))
00033 {
00034 ROS_INFO("Waiting for the move_base action server to come up");
00035 }
00036
00037 cmd_vel_pub = nh->advertise<geometry_msgs::Twist>("cmd_vel", 1);
00038
00039 sound_pub = nh->advertise<sound_play::SoundRequest>("robotsound", 1);
00040
00041 search_planner_simple = new SearchPlannerSimple(nh);
00042
00043 task_completed = false;
00044 human_detected = -1;
00045 }
00046
00047
00048 void ScavTaskHumanFollowing::callback_human_detected(const geometry_msgs::PoseStamped::ConstPtr& msg)
00049 {
00050 if (human_detected == -1)
00051 search_planner_simple->cancelCurrentGoal();
00052
00053 detected_time = ros::Time::now();
00054
00055 ROS_INFO("Person detected");
00056
00057
00058
00059 double human_pose_delta = sqrt(pow(msg->pose.position.x - human_pose.pose.position.x, 2) +
00060 pow(msg->pose.position.y - human_pose.pose.position.y, 2));
00061
00062 if (human_pose_delta > human_pose_delta_threshold) {
00063
00064
00065 boost::posix_time::ptime curr_time = boost::posix_time::second_clock::local_time();
00066 std::string time_str = boost::posix_time::to_iso_extended_string(curr_time);
00067
00068 wb_path_to_image = directory + "human_following_" + time_str + ".PNG";
00069 wb_image = wb_image_candidate;
00070
00071
00072
00073
00074
00075 human_pose.pose.position = msg->pose.position;
00076 human_pose.header.frame_id = "level_mux/map";
00077 human_pose.header.stamp = msg->header.stamp;
00078 human_pose.pose.orientation.x = 0;
00079 human_pose.pose.orientation.y = 0;
00080 human_pose.pose.orientation.z = 0;
00081 human_pose.pose.orientation.w = 1;
00082
00083
00084
00085
00086 human_following_pose = human_pose;
00087 double theta = atan2(human_pose.pose.position.y - current_pose.position.y,
00088 human_pose.pose.position.x - current_pose.position.x);
00089
00090 human_following_pose.pose.position.x -= human_following_pose_offset * cos(theta);
00091 human_following_pose.pose.position.y -= human_following_pose_offset * sin(theta);
00092 human_following_pose.pose.orientation.x = 0;
00093 human_following_pose.pose.orientation.y = 0;
00094 human_following_pose.pose.orientation.z = sin((theta)/2);
00095 human_following_pose.pose.orientation.w = cos((theta)/2);
00096 human_pose.pose.orientation.x = 0;
00097 human_pose.pose.orientation.y = 0;
00098 human_pose.pose.orientation.z = sin((theta)/2);
00099 human_pose.pose.orientation.w = cos((theta)/2);
00100
00101
00102 human_detected = 1;
00103 }
00104 }
00105
00106
00107 void ScavTaskHumanFollowing::callback_image(const sensor_msgs::ImageConstPtr& msg)
00108 {
00109 wb_image_candidate = msg;
00110 }
00111
00112
00113 void ScavTaskHumanFollowing::callback_ac_followed(const actionlib::SimpleClientGoalState& state,
00114 const move_base_msgs::MoveBaseResultConstPtr& result)
00115 {
00116 ROS_INFO("Reached human following way point");
00117
00118 ros::Duration last_detected_duration_threshold (0.2);
00119 ros::Duration detection_time_elapsed = ros::Time::now() - detected_time;
00120 if (detection_time_elapsed < last_detected_duration_threshold){
00121 ROS_INFO("Human still in view, not moving in; detection_elapsed: %f", detection_time_elapsed.toSec());
00122 } else {
00123 ROS_INFO("Move to human's last seen location");
00124 human_detected = 2;
00125 }
00126 }
00127
00128 void ScavTaskHumanFollowing::callback_ac_reached(const actionlib::SimpleClientGoalState& state,
00129 const move_base_msgs::MoveBaseResultConstPtr& result)
00130 {
00131 ROS_INFO("Reached human last seen location");
00132 human_detected = 4;
00133 }
00134
00135 void ScavTaskHumanFollowing::callback_ac_done(const actionlib::SimpleClientGoalState& state,
00136 const move_base_msgs::MoveBaseResultConstPtr& result)
00137 {
00138 human_detected = 4;
00139 }
00140
00141 void ScavTaskHumanFollowing::amclPoseCallback(
00142 const geometry_msgs::PoseWithCovarianceStamped::ConstPtr& msg) {
00143 current_pose = msg->pose.pose;
00144 }
00145
00146 void ScavTaskHumanFollowing::motionThread() {
00147
00148 ros::Rate r(2);
00149
00150
00151 ros::Subscriber amcl_pose_sub;
00152 amcl_pose_sub = nh->subscribe("amcl_pose", 100, &ScavTaskHumanFollowing::amclPoseCallback, this);
00153
00154 move_base_msgs::MoveBaseGoal goal;
00155 sound_play::SoundRequest sound_msg;
00156
00157
00158 while (ros::ok() and r.sleep() and task_completed == false) {
00159 ros::spinOnce();
00160 ROS_INFO_STREAM("human_detected: " << human_detected);
00161
00162
00163 if (human_detected == -1) {
00164 if (false == search_planner_simple->busy)
00165 search_planner_simple->moveToNextDoor();
00166 }
00167
00168
00169
00170
00171 if (human_detected == 1) {
00172
00173 human_detected = 0;
00174 goal.target_pose = human_following_pose;
00175 ac.sendGoal(goal, boost::bind(&ScavTaskHumanFollowing::callback_ac_followed, this, _1, _2));
00176
00177 sound_msg.command = sound_play::SoundRequest::PLAY_ONCE;
00178 sound_msg.arg = "following";
00179 sound_msg.arg2 = "voice_kal_diphone";
00180
00181 sound_pub.publish(sound_msg);
00182 }
00183
00184 if (human_detected == 2) {
00185 human_detected = 0;
00186 goal.target_pose = human_pose;
00187 ac.sendGoal(goal, boost::bind(&ScavTaskHumanFollowing::callback_ac_reached, this, _1, _2));
00188 }
00189
00190
00191
00192
00193
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204 if (human_detected == 4) {
00205 human_detected = 0;
00206 ROS_INFO("Human lost, following task complete");
00207
00208 cv_bridge::CvImageConstPtr cv_ptr = cv_bridge::toCvShare(wb_image, sensor_msgs::image_encodings::BGR8);
00209
00210 if (boost::filesystem::is_directory(directory) == false) {
00211 boost::filesystem::path tmp_path(directory);
00212 boost::filesystem::create_directory(tmp_path);
00213 }
00214 ROS_INFO("Saving image at %s", wb_path_to_image.c_str());
00215 cv::imwrite(wb_path_to_image, cv_ptr->image);
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00226
00227
00228 ROS_INFO_STREAM("Finished saving image: " << wb_path_to_image);
00229
00230 task_completed = true;
00231 }
00232 }
00233 }
00234
00235 void ScavTaskHumanFollowing::visionThread() {
00236
00237 ros::Subscriber sub_human = nh->subscribe("/segbot_pcl_person_detector/human_poses",
00238 100, &ScavTaskHumanFollowing::callback_human_detected, this);
00239
00240 image_transport::ImageTransport it(*nh);
00241 image_transport::Subscriber sub_image = it.subscribe("/nav_kinect/rgb/image_raw",
00242 1, &ScavTaskHumanFollowing::callback_image, this);
00243
00244 ros::Rate r(10);
00245 while (ros::ok() and r.sleep() and !task_completed) {
00246 ros::spinOnce();
00247 }
00248 }
00249
00250 void ScavTaskHumanFollowing::executeTask(int timeout, TaskResult &result, std::string &record) {
00251
00252 boost::thread motion( &ScavTaskHumanFollowing::motionThread, this);
00253 boost::thread vision( &ScavTaskHumanFollowing::visionThread, this);
00254
00255 motion.join();
00256 vision.join();
00257 record = wb_path_to_image;
00258 result = SUCCEEDED;
00259 }
00260
00261
00262 void ScavTaskHumanFollowing::stopEarly() {
00263 task_completed = true;
00264 }
00265 }