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
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
00058 #include <tf/transform_listener.h>
00059 #include <tf/transform_datatypes.h>
00060
00061
00062 #include <pcl/point_cloud.h>
00063 #include <pcl/point_types.h>
00064 #include <pcl_ros/transforms.h>
00065
00066
00067 #include <boost/shared_ptr.hpp>
00068
00069
00070 #include <opencv2/core/core.hpp>
00071 #include <opencv2/imgproc/imgproc.hpp>
00072 #include <opencv2/highgui/highgui.hpp>
00073
00074
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>
00087 #include <cstdlib>
00088 #include <sstream>
00089
00090
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
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
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
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
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
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
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
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
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
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
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
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
00325 setTimer(0);
00326 return true;
00327 }
00328 return false;
00329 }
00330
00331
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
00349
00350 cv::Mat tape_mask = colorSegment(cur_color_frame_.clone(), gripper_tape_hue_value_, gripper_tape_hue_threshold_);
00351
00352
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
00357 std::vector<cv::Moments> ms = findMoments(tape_mask, cur_color_frame_);
00358
00359
00360 std::vector<cv::Point> pts = getMomentCoordinates(ms);
00361
00362
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
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
00398
00399 if (!estimated)
00400 {
00401 if (v_fk_diff_.size() == 0)
00402 v_fk_diff_.resize(default_tape_num);
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
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
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
00464 double min = angle[0];
00465 int one = 0;
00466 for (int i = 0; i < 3; i++)
00467 {
00468
00469 if (angle[i] < min)
00470 {
00471 min = angle[i];
00472 one = i;
00473 }
00474 }
00475
00476
00477 int a = one == 0 ? 1 : 0;
00478 int b = one == 2 ? 1 : 2;
00479
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
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
00522 moments.push_back(m);
00523
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
00544
00545
00546
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
00568 _hue_n = (_hue_n + 360);
00569 _hue_p = (_hue_p + 360);
00570
00571
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);
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
00594
00595
00596 bool sendZeroVelocity()
00597 {
00598
00599 visual_servo::VisualServoTwist v_srv;
00600
00601
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
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
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
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
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 }