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
00052
00053 #include <exception>
00054 #include <string>
00055
00056
00057 #include <boost/shared_ptr.hpp>
00058
00059
00060 #include <ros/ros.h>
00061 #include <image_transport/image_transport.h>
00062 #include <actionlib/client/simple_action_client.h>
00063 #include <sensor_msgs/CameraInfo.h>
00064 #include <geometry_msgs/PointStamped.h>
00065 #include <control_msgs/PointHeadAction.h>
00066 #include <sensor_msgs/image_encodings.h>
00067 #include <ros/topic.h>
00068
00069
00070 #include <opencv2/highgui/highgui.hpp>
00071 #include <cv_bridge/cv_bridge.h>
00072
00074
00075 static const std::string windowName = "Inside of TIAGo's head";
00076 static const std::string cameraFrame = "/xtion_rgb_optical_frame";
00077 static const std::string imageTopic = "/xtion/rgb/image_raw";
00078 static const std::string cameraInfoTopic = "/xtion/rgb/camera_info";
00079
00080
00081 cv::Mat cameraIntrinsics;
00082
00083
00084 typedef actionlib::SimpleActionClient<control_msgs::PointHeadAction> PointHeadClient;
00085 typedef boost::shared_ptr<PointHeadClient> PointHeadClientPtr;
00086
00087 PointHeadClientPtr pointHeadClient;
00088
00089 ros::Time latestImageStamp;
00090
00092
00093
00094 void imageCallback(const sensor_msgs::ImageConstPtr& imgMsg)
00095 {
00096 latestImageStamp = imgMsg->header.stamp;
00097
00098 cv_bridge::CvImagePtr cvImgPtr;
00099
00100 cvImgPtr = cv_bridge::toCvCopy(imgMsg, sensor_msgs::image_encodings::BGR8);
00101 cv::imshow(windowName, cvImgPtr->image);
00102 cv::waitKey(15);
00103 }
00104
00105
00106 void onMouse( int event, int u, int v, int, void* )
00107 {
00108 if ( event != cv::EVENT_LBUTTONDOWN )
00109 return;
00110
00111 ROS_INFO_STREAM("Pixel selected (" << u << ", " << v << ") Making TIAGo look to that direction");
00112
00113 geometry_msgs::PointStamped pointStamped;
00114
00115 pointStamped.header.frame_id = cameraFrame;
00116 pointStamped.header.stamp = latestImageStamp;
00117
00118
00119 double x = ( u - cameraIntrinsics.at<double>(0,2) )/ cameraIntrinsics.at<double>(0,0);
00120 double y = ( v - cameraIntrinsics.at<double>(1,2) )/ cameraIntrinsics.at<double>(1,1);
00121 double Z = 1.0;
00122 pointStamped.point.x = x * Z;
00123 pointStamped.point.y = y * Z;
00124 pointStamped.point.z = Z;
00125
00126
00127 control_msgs::PointHeadGoal goal;
00128
00129 goal.pointing_frame = cameraFrame;
00130 goal.pointing_axis.x = 0.0;
00131 goal.pointing_axis.y = 0.0;
00132 goal.pointing_axis.z = 1.0;
00133 goal.min_duration = ros::Duration(1.0);
00134 goal.max_velocity = 0.25;
00135 goal.target = pointStamped;
00136
00137 pointHeadClient->sendGoal(goal);
00138 ros::Duration(0.5).sleep();
00139 }
00140
00141
00142 void createPointHeadClient(PointHeadClientPtr& actionClient)
00143 {
00144 ROS_INFO("Creating action client to head controller ...");
00145
00146 actionClient.reset( new PointHeadClient("/head_controller/point_head_action") );
00147
00148 int iterations = 0, max_iterations = 3;
00149
00150 while( !actionClient->waitForServer(ros::Duration(2.0)) && ros::ok() && iterations < max_iterations )
00151 {
00152 ROS_DEBUG("Waiting for the point_head_action server to come up");
00153 ++iterations;
00154 }
00155
00156 if ( iterations == max_iterations )
00157 throw std::runtime_error("Error in createPointHeadClient: head controller action server not available");
00158 }
00159
00161
00162
00163 int main(int argc, char** argv)
00164 {
00165
00166 ros::init(argc, argv, "look_to_point");
00167
00168 ROS_INFO("Starting look_to_point application ...");
00169
00170
00171 ros::NodeHandle nh;
00172 if (!ros::Time::waitForValid(ros::WallDuration(10.0)))
00173 {
00174 ROS_FATAL("Timed-out waiting for valid time.");
00175 return EXIT_FAILURE;
00176 }
00177
00178
00179 ROS_INFO("Waiting for camera intrinsics ... ");
00180 sensor_msgs::CameraInfoConstPtr msg = ros::topic::waitForMessage
00181 <sensor_msgs::CameraInfo>(cameraInfoTopic, ros::Duration(10.0));
00182 if(msg.use_count() > 0)
00183 {
00184 cameraIntrinsics = cv::Mat::zeros(3,3,CV_64F);
00185 cameraIntrinsics.at<double>(0, 0) = msg->K[0];
00186 cameraIntrinsics.at<double>(1, 1) = msg->K[4];
00187 cameraIntrinsics.at<double>(0, 2) = msg->K[2];
00188 cameraIntrinsics.at<double>(1, 2) = msg->K[5];
00189 cameraIntrinsics.at<double>(2, 2) = 1;
00190 }
00191
00192
00193 createPointHeadClient( pointHeadClient );
00194
00195
00196 cv::namedWindow(windowName, cv::WINDOW_AUTOSIZE);
00197
00198
00199 cv::setMouseCallback(windowName, onMouse);
00200
00201
00202 image_transport::ImageTransport it(nh);
00203
00204 image_transport::TransportHints transportHint("compressed");
00205
00206 ROS_INFO_STREAM("Subscribing to " << imageTopic << " ...");
00207 image_transport::Subscriber sub = it.subscribe(imageTopic, 1,
00208 imageCallback, transportHint);
00209
00210
00211 ros::spin();
00212
00213 cv::destroyWindow(windowName);
00214
00215 return EXIT_SUCCESS;
00216 }