vs_action.cpp
Go to the documentation of this file.
00001 /*********************************************************************
00002  *
00003  *  Copyright (c) 2012, Georgia Institute of Technology
00004  *  All rights reserved.
00005  *
00006  *  Redistribution and use in source and binary forms, with or without
00007  *  modification, are permitted provided that the following conditions
00008  *  are met:
00009  *
00010  *   * Redistributions of source code must retain the above copyright
00011  *     notice, this list of conditions and the following disclaimer.
00012  *   * Redistributions in binary form must reproduce the above
00013  *     copyright notice, this list of conditions and the following
00014  *     disclaimer in the documentation and/or other materials provided
00015  *     with the distribution.
00016  *   * Neither the name of the Georgia Institute of Technology nor the names of
00017  *     its contributors may be used to endorse or promote products derived
00018  *     from this software without specific prior written permission.
00019  *
00020  *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
00021  *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
00022  *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
00023  *  FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
00024  *  COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
00025  *  INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
00026  *  BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
00027  *  LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
00028  *  CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
00029  *  LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
00030  *  ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
00031  *  POSSIBILITY OF SUCH DAMAGE.
00032  *********************************************************************/
00033 
00034 // ROS
00035 #include <ros/ros.h>
00036 #include <ros/package.h>
00037 
00038 #include <std_msgs/Header.h>
00039 #include <std_msgs/String.h>
00040 #include <geometry_msgs/PointStamped.h>
00041 #include <geometry_msgs/QuaternionStamped.h>
00042 #include <geometry_msgs/TwistStamped.h>
00043 #include <geometry_msgs/Pose2D.h>
00044 #include <geometry_msgs/Point.h>
00045 #include <sensor_msgs/Image.h>
00046 #include <sensor_msgs/PointCloud2.h>
00047 #include <sensor_msgs/CameraInfo.h>
00048 #include <sensor_msgs/image_encodings.h>
00049 
00050 #include <message_filters/subscriber.h>
00051 #include <message_filters/time_synchronizer.h>
00052 #include <message_filters/synchronizer.h>
00053 #include <message_filters/sync_policies/approximate_time.h>
00054 #include <image_transport/image_transport.h>
00055 #include <cv_bridge/cv_bridge.h>
00056 
00057 // TF
00058 #include <tf/transform_listener.h>
00059 #include <tf/transform_datatypes.h>
00060 
00061 // PCL
00062 #include <pcl/point_cloud.h>
00063 #include <pcl/point_types.h>
00064 #include <pcl_ros/transforms.h>
00065 
00066 // Boost
00067 #include <boost/shared_ptr.hpp>
00068 
00069 // OpenCV
00070 #include <opencv2/core/core.hpp>
00071 #include <opencv2/imgproc/imgproc.hpp>
00072 #include <opencv2/highgui/highgui.hpp>
00073 
00074 // STL
00075 #include <vector>
00076 #include <deque>
00077 #include <queue>
00078 #include <string>
00079 #include <sstream>
00080 #include <iostream>
00081 #include <fstream>
00082 #include <utility>
00083 #include <stdexcept>
00084 #include <float.h>
00085 #include <math.h>
00086 #include <time.h> // for srand(time(NULL))
00087 #include <cstdlib> // for MAX_RAND
00088 #include <sstream>
00089 
00090 // Others
00091 #include <actionlib/server/simple_action_server.h>
00092 #include <visual_servo/VisualServoAction.h>
00093 #include <visual_servo/VisualServoTwist.h>
00094 #include <visual_servo/VisualServoPose.h>
00095 #include "visual_servo.cpp"
00096 
00097 // floating point mod
00098 #define fmod(a,b) a - (float)((int)(a/b)*b)
00099 
00100 typedef message_filters::sync_policies::ApproximateTime<sensor_msgs::Image, sensor_msgs::Image,sensor_msgs::PointCloud2> MySyncPolicy;
00101 typedef pcl::PointCloud<pcl::PointXYZ> XYZPointCloud;
00102 
00103 using boost::shared_ptr;
00104 using geometry_msgs::TwistStamped;
00105 using geometry_msgs::PoseStamped;
00106 using geometry_msgs::QuaternionStamped;
00107 using geometry_msgs::Point;
00108 using visual_servo::VisualServoTwist;
00109 using visual_servo::VisualServoPose;
00110 
00111 class GripperTape
00112 {
00119   public:
00120     GripperTape()
00121     {
00122     }
00123 
00124     void setTapeRelLoc(pcl::PointXYZ tape0, pcl::PointXYZ tape1, pcl::PointXYZ tape2)
00125     {
00126       tape1_loc_.x = tape1.x - tape0.x;
00127       tape1_loc_.y = tape1.y - tape0.y;
00128       tape1_loc_.z = tape1.z - tape0.z;
00129       tape2_loc_.x = tape2.x - tape0.x;
00130       tape2_loc_.y = tape2.y - tape0.y;
00131       tape2_loc_.z = tape2.z - tape0.z;
00132     }
00133 
00134     // this is the offset from tip center to tape0
00135     void setOffset(pcl::PointXYZ offset)
00136     {
00137       tape0_loc_ = offset;
00138     }
00139 
00140     std::vector<pcl::PointXYZ> getTapePoseFromXYZ(pcl::PointXYZ orig)
00141     {
00142       std::vector<pcl::PointXYZ> pts; pts.clear();
00143       pcl::PointXYZ zero = addPointXYZ(orig, tape0_loc_);
00144       pcl::PointXYZ one = addPointXYZ(zero, tape1_loc_);
00145       pcl::PointXYZ two = addPointXYZ(zero, tape2_loc_);
00146 
00147       pts.push_back(zero);
00148       pts.push_back(one);
00149       pts.push_back(two);
00150 
00151       return pts;
00152     }
00153 
00154   private:
00155     pcl::PointXYZ tape0_loc_;
00156     pcl::PointXYZ tape1_loc_;
00157     pcl::PointXYZ tape2_loc_;
00158 
00159     pcl::PointXYZ addPointXYZ(pcl::PointXYZ a, pcl::PointXYZ b)
00160     {
00161       pcl::PointXYZ r;
00162       r.x = a.x + b.x;
00163       r.y = a.y + b.y;
00164       r.z = a.z + b.z;
00165       return r;
00166     }
00167 };
00168 
00169 class VisualServoAction
00170 {
00171   public:
00172     VisualServoAction(ros::NodeHandle &n, std::string which_arm) :
00173       n_(n),
00174       as_(n_, "vsaction", false),
00175       action_name_("vsaction"),
00176       n_private_("~"),
00177       image_sub_(n_, "color_image_topic", 1),
00178       depth_sub_(n_, "depth_image_topic", 1),
00179       cloud_sub_(n_, "point_cloud_topic", 1),
00180       sync_(MySyncPolicy(15), image_sub_, depth_sub_, cloud_sub_),
00181       it_(n_), tf_(), camera_initialized_(false)
00182   {
00183     vs_ = shared_ptr<VisualServo>(new VisualServo(JACOBIAN_TYPE_PSEUDO));
00184     tf_ = shared_ptr<tf::TransformListener>(new tf::TransformListener());
00185     which_arm_ = which_arm;
00186 
00187     n_private_.param("display_wait_ms", display_wait_ms_, 3);
00188 
00189     std::string default_optical_frame = "/head_mount_kinect_rgb_optical_frame";
00190     n_private_.param("optical_frame", optical_frame_, default_optical_frame);
00191     std::string default_workspace_frame = "/torso_lift_link";
00192     n_private_.param("workspace_frame", workspace_frame_, default_workspace_frame);
00193     std::string cam_info_topic_def = "/kinect_head/rgb/camera_info";
00194     n_private_.param("cam_info_topic", cam_info_topic_, cam_info_topic_def);
00195 
00196     // color segmentation parameters
00197     n_private_.param("target_hue_value", target_hue_value_, 10);
00198     n_private_.param("target_hue_threshold", target_hue_threshold_, 20);
00199     n_private_.param("gripper_tape_hue_value", gripper_tape_hue_value_, 180);
00200     n_private_.param("gripper_tape_hue_threshold", gripper_tape_hue_threshold_, 50);
00201     n_private_.param("default_sat_bot_value", default_sat_bot_value_, 40);
00202     n_private_.param("default_sat_top_value", default_sat_top_value_, 40);
00203     n_private_.param("default_val_value", default_val_value_, 200);
00204     n_private_.param("min_contour_size", min_contour_size_, 10.0);
00205 
00206     // others
00207     n_private_.param("jacobian_type", jacobian_type_, JACOBIAN_TYPE_INV);
00208     n_private_.param("vs_err_term_thres", vs_err_term_threshold_, 0.001);
00209     n_private_.param("pose_servo_z_offset", pose_servo_z_offset_, 0.045);
00210     n_private_.param("place_z_velocity", place_z_velocity_, -0.025);
00211     n_private_.param("gripper_tape1_offset_x", tape1_offset_x_, 0.02);
00212     n_private_.param("gripper_tape1_offset_y", tape1_offset_y_, -0.025);
00213     n_private_.param("gripper_tape1_offset_z", tape1_offset_z_, 0.07);
00214 
00215     n_private_.param("max_exec_time", max_exec_time_, 20.0);
00216 
00217     // Setup ros node connections
00218     sync_.registerCallback(&VisualServoAction::sensorCallback, this);
00219     v_client_ = n_.serviceClient<visual_servo::VisualServoTwist>("vs_twist");
00220 
00221     gripper_tape_ = GripperTape();
00222     gripper_tape_.setOffset(pcl::PointXYZ(tape1_offset_x_, tape1_offset_y_, tape1_offset_z_));
00223 
00224     as_.registerGoalCallback(boost::bind(&VisualServoAction::goalCB, this));
00225     ROS_DEBUG("[vsaction] Initialization 0: Node init & Register Callback Done");
00226     as_.start();
00227     ROS_INFO("[vsaction] \e[0;34minit done. Action for \e[1;34m[%s]\e[0;34m-arm started", which_arm_.c_str());
00228   }
00229 
00230     // destructor
00231     ~VisualServoAction()
00232     {
00233     }
00234 
00235     void goalCB()
00236     {
00237       goal_p_ = as_.acceptNewGoal()->pose;
00238       ROS_INFO("[vsaction] \e[1;34mGoal Accepted: [%.3f %.3f %.3f]", goal_p_.pose.position.x,
00239       goal_p_.pose.position.y, goal_p_.pose.position.z);
00240       setTimer(max_exec_time_);
00241       return;
00242     }
00243 
00244 
00248     void sensorCallback(const sensor_msgs::ImageConstPtr& img_msg, 
00249         const sensor_msgs::ImageConstPtr& depth_msg, const sensor_msgs::PointCloud2ConstPtr& cloud_msg)
00250     {
00251       if (!as_.isActive())
00252         return;
00253 
00254       // Store camera information only once
00255       if (!camera_initialized_)
00256       {
00257         cam_info_ = *ros::topic::waitForMessage<sensor_msgs::CameraInfo>(cam_info_topic_, n_, ros::Duration(3.0));
00258         camera_initialized_ = true;
00259         vs_->setCamInfo(cam_info_);
00260         ROS_INFO("[vsaction]Initialization: Camera Info Done");
00261       }
00262 
00263       cv::Mat color_frame, depth_frame;
00264       cv_bridge::CvImagePtr color_cv_ptr = cv_bridge::toCvCopy(img_msg);
00265       cv_bridge::CvImagePtr depth_cv_ptr = cv_bridge::toCvCopy(depth_msg);
00266 
00267       color_frame = color_cv_ptr->image;
00268       depth_frame = depth_cv_ptr->image;
00269 
00270       XYZPointCloud cloud; 
00271       pcl::fromROSMsg(*cloud_msg, cloud);
00272       tf_->waitForTransform(workspace_frame_, cloud.header.frame_id,
00273           cloud.header.stamp, ros::Duration(0.9));
00274       pcl_ros::transformPointCloud(workspace_frame_, cloud, cloud, *tf_);
00275       cur_camera_header_ = img_msg->header;
00276       cur_color_frame_ = color_frame;
00277       cur_orig_color_frame_ = color_frame.clone();
00278       cur_depth_frame_ = depth_frame.clone();
00279       cur_point_cloud_ = cloud;
00280 
00281       // tape features are updated (can be interpolated too)
00282       gripper_pose_estimated_ = updateGripperFeatures();
00283 
00284       std::vector<PoseStamped> goals, feats;
00285       goals.push_back(goal_p_);
00286       feats.push_back(tape_features_p_);
00287 
00288       // setting arm_controller values
00289       visual_servo::VisualServoTwist v_srv = vs_->getTwist(goals,feats);
00290       v_srv.request.arm = which_arm_;
00291       float err = getError(goal_p_, tape_features_p_);
00292       v_srv.request.error = err;
00293 
00294       // setting action values
00295       feedback_.error = err;
00296       feedback_.ee = tape_features_p_;
00297       result_.error = err;
00298 
00299       if (v_client_.call(v_srv)){}
00300       as_.publishFeedback(feedback_);
00301       // termination condition
00302       if (v_srv.request.error < vs_err_term_threshold_)
00303       {
00304         ROS_INFO("\e[1;31mSuccess!");
00305         as_.setSucceeded(result_);
00306       }
00307       else if (isExpired())
00308       {
00309         ROS_WARN("Failed to go to the goal in time given. Aborting");
00310         as_.setAborted(result_, "timeout");
00311       }
00312     }
00313 
00314     void setTimer(float time)
00315     {
00316       ros::Time timer = ros::Time::now() + ros::Duration(time);
00317       timer_ = timer;
00318     }
00319     bool isExpired()
00320     {
00321       ros::Duration d = ros::Time::now() - timer_;
00322       if (d.toSec() > 0)
00323       {
00324         // set alarm to zero to be safe
00325         setTimer(0);
00326         return true;
00327       }
00328       return false; 
00329     }
00330 
00331     // Detect Tapes on Gripepr and update its position
00332     bool updateGripperFeatures()
00333     {
00334       bool estimated = false;
00335       int default_tape_num = 3;
00336 
00337       PoseStamped p;
00338       if (which_arm_.compare("l" == 0))
00339           p.header.frame_id = "/l_gripper_tool_frame";
00340       else
00341         p.header.frame_id = "/r_gripper_tool_frame";
00342       p.pose.orientation.w = 1;
00343       tf_->transformPose(workspace_frame_, p, p);
00344       Point fkpp = p.pose.position;
00345 
00346 
00348       // Hand 
00349       // get all the blues 
00350       cv::Mat tape_mask = colorSegment(cur_color_frame_.clone(), gripper_tape_hue_value_, gripper_tape_hue_threshold_);
00351 
00352       // make it clearer with morphology
00353       cv::Mat element_b = cv::getStructuringElement(cv::MORPH_RECT, cv::Size(3,3));
00354       cv::morphologyEx(tape_mask, tape_mask, cv::MORPH_OPEN, element_b);
00355 
00356       // find the three largest blues
00357       std::vector<cv::Moments> ms = findMoments(tape_mask, cur_color_frame_); 
00358 
00359       // order the blue tapes
00360       std::vector<cv::Point> pts = getMomentCoordinates(ms);
00361 
00362       // convert the features into proper form 
00363       tape_features_ = vs_->CVPointToVSXYZ(cur_point_cloud_, cur_depth_frame_, pts);
00364       if ((int)tape_features_.size() != default_tape_num)
00365       {
00366         if ((int)v_fk_diff_.size() != default_tape_num)
00367         {
00368           ROS_WARN("[vsaction]Cannot find tape in image and do not have enough historical data to interpolate");
00369           tape_features_p_ = PoseStamped();
00370           return false;
00371         }
00372         estimated = true;
00373         std::vector<pcl::PointXYZ> estimated_pose;
00374         estimated_pose.resize(default_tape_num);
00375         tape_features_.resize(default_tape_num);
00376         for (unsigned int i = 0; i < v_fk_diff_.size(); i++)
00377         {
00378           estimated_pose.at(i).x = v_fk_diff_.at(i).x + fkpp.x;
00379           estimated_pose.at(i).y = v_fk_diff_.at(i).y + fkpp.y;
00380           estimated_pose.at(i).z = v_fk_diff_.at(i).z + fkpp.z;
00381         }
00382         tape_features_ = vs_->Point3DToVSXYZ(estimated_pose, tf_);
00383       }
00384       tape_features_p_ = vs_->VSXYZToPoseStamped(tape_features_.front());
00385 
00386       // ORIENT
00387       QuaternionStamped q;
00388       q.quaternion.w = 1;
00389 
00390       if (which_arm_.compare("l" == 0))
00391         q.header.frame_id = "/l_gripper_tool_frame";
00392       else
00393         q.header.frame_id = "/r_gripper_tool_frame";
00394       tf_->transformQuaternion(workspace_frame_, q, q);
00395       tape_features_p_.pose.orientation = q.quaternion;
00396 
00397       // we aren't going to let controllers rotate at all when occluded;
00398       // vision vs. forward kinematics
00399       if (!estimated)
00400       {
00401         if (v_fk_diff_.size() == 0)
00402           v_fk_diff_.resize(default_tape_num); // initialize in case it isn't
00403         for (unsigned int i = 0 ; i < tape_features_.size() && i < v_fk_diff_.size(); i++)
00404         {
00405           v_fk_diff_.at(i).x = tape_features_.at(i).workspace.x - fkpp.x;
00406           v_fk_diff_.at(i).y = tape_features_.at(i).workspace.y - fkpp.y;
00407           v_fk_diff_.at(i).z = tape_features_.at(i).workspace.z - fkpp.z;
00408         }
00409       }
00410       return estimated;
00411     }
00412 
00413     float getError(PoseStamped a, PoseStamped b)
00414     {
00415       float e(0.0);
00416       e += pow(a.pose.position.x - b.pose.position.x, 2);
00417       e += pow(a.pose.position.y - b.pose.position.y, 2);
00418       e += pow(a.pose.position.z - b.pose.position.z, 2);
00419       return e;
00420     }
00421 
00422     /************************************
00423      * PERCEPTION
00424      ************************************/
00425 
00434     std::vector<cv::Point> getMomentCoordinates(std::vector<cv::Moments> ms)
00435     {
00436       std::vector<cv::Point> ret;
00437       ret.clear();
00438       if (ms.size() == 3) { 
00439         double centroids[3][2];
00440         for (int i = 0; i < 3; i++) {
00441           cv::Moments m0 = ms.at(i);
00442           double x0, y0;
00443           x0 = m0.m10/m0.m00;
00444           y0 = m0.m01/m0.m00;
00445           centroids[i][0] = x0;
00446           centroids[i][1] = y0;
00447         }
00448 
00449         // find the top left corner using distance scheme
00450         cv::Mat vect = cv::Mat::zeros(3,2, CV_32F);
00451         vect.at<float>(0,0) = centroids[0][0] - centroids[1][0];
00452         vect.at<float>(0,1) = centroids[0][1] - centroids[1][1];
00453         vect.at<float>(1,0) = centroids[0][0] - centroids[2][0];
00454         vect.at<float>(1,1) = centroids[0][1] - centroids[2][1];
00455         vect.at<float>(2,0) = centroids[1][0] - centroids[2][0];
00456         vect.at<float>(2,1) = centroids[1][1] - centroids[2][1];
00457 
00458         double angle[3];
00459         angle[0] = abs(vect.row(0).dot(vect.row(1)));
00460         angle[1] = abs(vect.row(0).dot(vect.row(2)));
00461         angle[2] = abs(vect.row(1).dot(vect.row(2)));
00462 
00463         // printMatrix(vect); 
00464         double min = angle[0]; 
00465         int one = 0;
00466         for (int i = 0; i < 3; i++)
00467         {
00468           // printf("[%d, %f]\n", i, angle[i]);
00469           if (angle[i] < min)
00470           {
00471             min = angle[i];
00472             one = i;
00473           }
00474         }
00475 
00476         // index of others depending on the index of the origin
00477         int a = one == 0 ? 1 : 0;
00478         int b = one == 2 ? 1 : 2; 
00479         // vectors of origin to a point
00480         double vX0, vY0, vX1, vY1, result;
00481         vX0 = centroids[a][0] - centroids[one][0];
00482         vY0 = centroids[a][1] - centroids[one][1];
00483         vX1 = centroids[b][0] - centroids[one][0];
00484         vY1 = centroids[b][1] - centroids[one][1];
00485         cv::Point pto(centroids[one][0], centroids[one][1]);
00486         cv::Point pta(centroids[a][0], centroids[a][1]);
00487         cv::Point ptb(centroids[b][0], centroids[b][1]);
00488 
00489         // cross-product: simplified assuming that z = 0 for both
00490         result = vX1*vY0 - vX0*vY1;
00491         ret.push_back(pto);
00492         if (result >= 0) {
00493           ret.push_back(ptb);
00494           ret.push_back(pta);
00495         }
00496         else {
00497           ret.push_back(pta);
00498           ret.push_back(ptb);
00499         }
00500       }
00501       return ret;
00502     } 
00503 
00511     std::vector<cv::Moments> findMoments(cv::Mat in, cv::Mat &color_frame, unsigned int max_num = 3) 
00512     {
00513       cv::Mat temp = in.clone();
00514       std::vector<std::vector<cv::Point> > contours; contours.clear();
00515       cv::findContours(temp, contours, cv::RETR_CCOMP,CV_CHAIN_APPROX_NONE);
00516       std::vector<cv::Moments> moments; moments.clear();
00517 
00518       for (unsigned int i = 0; i < contours.size(); i++) {
00519         cv::Moments m = cv::moments(contours[i]);
00520         if (m.m00 > min_contour_size_) {
00521           // first add the forth element
00522           moments.push_back(m);
00523           // find the smallest element of 4 and remove that
00524           if (moments.size() > max_num) {
00525             double small(moments.at(0).m00);
00526             unsigned int smallInd(0);
00527             for (unsigned int j = 1; j < moments.size(); j++){
00528               if (moments.at(j).m00 < small) {
00529                 small = moments.at(j).m00;
00530                 smallInd = j;
00531               }
00532             }
00533             moments.erase(moments.begin() + smallInd);
00534           }
00535         }
00536       }
00537       return moments;
00538     }
00539 
00540     cv::Mat colorSegment(cv::Mat color_frame, int hue, int threshold)
00541     {
00542       /*
00543        * Often value = 0 or 255 are very useless. 
00544        * The distance at those end points get very close and it is not useful
00545        * Same with saturation 0. Low saturation makes everything more gray scaled
00546        * So the default setting are below 
00547        */
00548       return colorSegment(color_frame, hue - threshold, hue + threshold,  
00549           default_sat_bot_value_, default_sat_top_value_, 40, default_val_value_);
00550     }
00551 
00560     cv::Mat colorSegment(cv::Mat color_frame, int _hue_n, int _hue_p, int _sat_n, int _sat_p, int _value_n,  int _value_p)
00561     {
00562       cv::Mat temp (color_frame.clone());
00563       cv::cvtColor(temp, temp, CV_BGR2HSV);
00564       std::vector<cv::Mat> hsv;
00565       cv::split(temp, hsv);
00566 
00567       // so it can support hue near 0 & 360
00568       _hue_n = (_hue_n + 360);
00569       _hue_p = (_hue_p + 360);
00570 
00571       // masking out values that do not fall between the condition 
00572       cv::Mat wm(color_frame.rows, color_frame.cols, CV_8UC1, cv::Scalar(0));
00573       for (int r = 0; r < temp.rows; r++)
00574       {
00575         uchar* workspace_row = wm.ptr<uchar>(r);
00576         for (int c = 0; c < temp.cols; c++)
00577         {
00578           int hue     = 2*(int)hsv[0].at<uchar>(r, c) + 360;
00579           float sat   = 0.392*(int)hsv[1].at<uchar>(r, c); // 0.392 = 100/255
00580           float value = 0.392*(int)hsv[2].at<uchar>(r, c);
00581 
00582           if (_hue_n < hue && hue < _hue_p)
00583             if (_sat_n < sat && sat < _sat_p)
00584               if (_value_n < value && value < _value_p)
00585                 workspace_row[c] = 255;
00586         }
00587       }
00588 
00589       return wm;
00590     }
00591 
00592     /**********************
00593      * HELPER METHODS
00594      **********************/
00595 
00596     bool sendZeroVelocity()
00597     {
00598       // assume everything is init to zero
00599       visual_servo::VisualServoTwist v_srv;
00600 
00601       // need this to mvoe the arm
00602       v_srv.request.error = 1;
00603       v_srv.request.arm = which_arm_;
00604       return v_client_.call(v_srv);
00605     }
00606 
00607     visual_servo::VisualServoPose formPoseService(float px, float py, float pz)
00608     {
00609 
00610       visual_servo::VisualServoPose p = VisualServoMsg::createPoseMsg(px, py, pz, -0.4582, 0, 0.8889, 0);
00611       p.request.arm = which_arm_;
00612       return p;
00613     }
00614 
00615     void printMatrix(cv::Mat_<double> in)
00616     {
00617       for (int i = 0; i < in.rows; i++) {
00618         for (int j = 0; j < in.cols; j++) {
00619           printf("%+.5f\t", in(i,j)); 
00620         }
00621         printf("\n");
00622       }
00623     }
00624 
00625   protected:
00626     ros::NodeHandle n_;
00627     actionlib::SimpleActionServer<visual_servo::VisualServoAction> as_;
00628     std::string action_name_;
00629     shared_ptr<VisualServo> vs_;
00630 
00631     std::string which_arm_;
00632     ros::Time timer_;
00633     double max_exec_time_;
00634 
00635     visual_servo::VisualServoFeedback feedback_;
00636     visual_servo::VisualServoResult result_;
00637 
00638     ros::NodeHandle n_private_;
00639     message_filters::Subscriber<sensor_msgs::Image> image_sub_;
00640     message_filters::Subscriber<sensor_msgs::Image> depth_sub_;
00641     message_filters::Subscriber<sensor_msgs::PointCloud2> cloud_sub_;
00642     message_filters::Synchronizer<MySyncPolicy> sync_;
00643     image_transport::ImageTransport it_;
00644     sensor_msgs::CameraInfo cam_info_;
00645     shared_ptr<tf::TransformListener> tf_;
00646 
00647     // frames
00648     cv::Mat cur_color_frame_;
00649     cv::Mat cur_orig_color_frame_;
00650     cv::Mat cur_depth_frame_;
00651     cv::Mat cur_workspace_mask_;
00652     std_msgs::Header cur_camera_header_;
00653     XYZPointCloud cur_point_cloud_;
00654     int display_wait_ms_;
00655     int num_downsamples_;
00656     std::string workspace_frame_;
00657     std::string optical_frame_;
00658     bool camera_initialized_;
00659     bool desire_points_initialized_;
00660     std::string cam_info_topic_;
00661 
00662     // segmenting
00663     int target_hue_value_;
00664     int target_hue_threshold_;
00665     int gripper_tape_hue_value_;
00666     int gripper_tape_hue_threshold_;
00667     int default_sat_bot_value_;
00668     int default_sat_top_value_;
00669     int default_val_value_;
00670     double min_contour_size_;
00671 
00672     // Other params
00673     int jacobian_type_;
00674     double vs_err_term_threshold_;
00675     double pose_servo_z_offset_;
00676     double place_z_velocity_;
00677     double tape1_offset_x_;
00678     double tape1_offset_y_;
00679     double tape1_offset_z_;
00680     ros::ServiceClient v_client_;
00681 
00682     // desired location/current gripper location
00683     cv::Mat desired_jacobian_;
00684     std::vector<VSXYZ> cur_goal_;
00685     std::vector<VSXYZ> goal_;
00686     PoseStamped goal_p_;
00687     std::vector<VSXYZ> tape_features_;
00688     PoseStamped tape_features_p_;
00689     VSXYZ desired_;
00690     cv::Mat K;
00691     std::vector<pcl::PointXYZ> v_fk_diff_;
00692     bool is_gripper_initialized_;
00693     bool gripper_pose_estimated_;
00694     GripperTape gripper_tape_;
00695 };
00696 
00697 int main(int argc, char** argv)
00698 {
00699   ros::init(argc, argv, "vsaction");
00700 
00701   log4cxx::LoggerPtr my_logger = log4cxx::Logger::getLogger(ROSCONSOLE_DEFAULT_NAME);
00702   my_logger->setLevel(ros::console::g_level_lookup[ros::console::levels::Info]);
00703 
00704   ros::NodeHandle n;
00705   std::string which_arm = argv[1];
00706   VisualServoAction vsa(n, which_arm);
00707   ros::spin();
00708   return 0;
00709 }


visual_servo
Author(s): Stephan Lee
autogenerated on Wed Nov 27 2013 11:44:03