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 #include <srs_assisted_arm_navigation_ui/bb_estimation_controls.h>
00029 #include <rviz/window_manager_interface.h>
00030
00031 using namespace std;
00032 using namespace srs_assisted_arm_navigation_ui;
00033 using namespace srs_assisted_arm_navigation;
00034 using namespace srs_assisted_arm_navigation_msgs;
00035
00036 static const string cv_win = "Assisted object detection";
00037
00038 const int ID_BUTTON_OK(101);
00039
00040 CButBBEstimationControls * class_ptr;
00041
00045 CButBBEstimationControls::CButBBEstimationControls(wxWindow *parent, const wxString& title, rviz::WindowManagerInterface * wmi )
00046 : wxPanel( parent, wxID_ANY, wxDefaultPosition, wxSize(280, 180), wxTAB_TRAVERSAL, title)
00047 , m_wmi( wmi ),
00048 as_(nh_,ACT_BB_SELECT,false),
00049 it_(nh_)
00050 {
00051
00052 ros::NodeHandle nh;
00053
00054 ros::param::param<bool>("~is_video_flipped", is_video_flipped_ , true);
00055
00056
00057 class_ptr = this;
00058
00059 parent_ = parent;
00060
00061 m_button_ok_ = new wxButton(this, ID_BUTTON_OK, wxT("Positioning completed"),wxDefaultPosition,wxDefaultSize,wxBU_EXACTFIT);
00062
00063 m_button_ok_->Enable(false);
00064
00065
00066
00067 as_.registerGoalCallback( boost::bind(&CButBBEstimationControls::actionGoalCallback, this));
00068 as_.registerPreemptCallback( boost::bind(&CButBBEstimationControls::actionPreemptCallback, this));
00069
00070 image_ = NULL;
00071 image_tmp_ = NULL;
00072
00073 image_width_ = 0;
00074 image_height_ = 0;
00075
00076 butt_down_x_ = -1;
00077 butt_down_y_ = -1;
00078
00079 disable_video_ = false;
00080
00081 data_ready_ = false;
00082 some_data_ready_ = false;
00083 action_in_progress_ = false;
00084
00085
00086 timer_ = nh.createTimer(ros::Duration(0.04),&CButBBEstimationControls::timerCallback,this);
00087
00088
00089 as_.start();
00090
00091
00092 }
00093
00094
00095
00096
00097 CButBBEstimationControls::~CButBBEstimationControls() {
00098
00099 delete m_button_ok_;
00100 class_ptr = NULL;
00101
00102 }
00103
00104 void CButBBEstimationControls::timerCallback(const ros::TimerEvent& ev) {
00105
00106 ROS_INFO_ONCE("Timer triggered.");
00107
00108 if (action_in_progress_ && !disable_video_) {
00109
00110
00111 image_mutex_.lock();
00112
00113 if (image_ == NULL) {
00114
00115 image_mutex_.unlock();
00116 return;
00117
00118 }
00119
00120 if (image_tmp_ != NULL) {
00121
00122 image_tmp_->release();
00123 delete image_tmp_;
00124
00125 }
00126
00127
00128
00129 image_tmp_ = new cv::Mat();
00130
00131 image_->copyTo(*image_tmp_);
00132
00133 image_mutex_.unlock();
00134
00135 std::string text_line1 = "Please select object.";
00136 std::string text_line2 = "Press left button, drag and then release.";
00137
00138 int fontFace = cv::FONT_HERSHEY_COMPLEX_SMALL;
00139 double fontScale = 0.8;
00140 int thickness = 1;
00141
00142 int baseline=0;
00143
00144 cv::Size size_line1 = cv::getTextSize(text_line1, fontFace, fontScale, thickness, &baseline);
00145 cv::Size size_line2 = cv::getTextSize(text_line2, fontFace, fontScale, thickness, &baseline);
00146
00147 int bigger_w = 0;
00148
00149 if (size_line1.width > size_line2.width) bigger_w = size_line1.width;
00150 else bigger_w = size_line2.width;
00151
00152 cv::rectangle(*image_tmp_,
00153 cv::Point(0,0),
00154 cv::Point(bigger_w + 20,size_line1.height + size_line2.height + 40),
00155 cv::Scalar(250, 250, 250, 125),
00156 CV_FILLED,
00157 CV_AA,
00158 0);
00159
00160 cv::putText(*image_tmp_, "Please select object.", cvPoint(10,20), fontFace, fontScale, cvScalar(0,0,0), thickness, CV_AA);
00161 cv::putText(*image_tmp_, "Press left button, drag and then release.", cvPoint(10,50), fontFace, fontScale, cvScalar(0,0,0), thickness, CV_AA);
00162
00163
00164
00165 if (data_ready_ || some_data_ready_) {
00166
00167 cv::Point tl,br;
00168
00169 data_mutex_.lock();
00170
00171 if (p1_[0] < p2_[0]) {
00172
00173 tl.x = p1_[0];
00174 tl.y = p1_[1];
00175
00176 br.x = p2_[0];
00177 br.y = p2_[1];
00178
00179 } else {
00180
00181 tl.x = p2_[0];
00182 tl.y = p2_[1];
00183
00184 br.x = p1_[0];
00185 br.y = p1_[1];
00186
00187 }
00188
00189 data_mutex_.unlock();
00190
00191 cv::Scalar color;
00192
00193 if (some_data_ready_) color = cv::Scalar(255, 0, 0, 0);
00194 else color = cv::Scalar(0, 0, 255, 0);
00195
00196 cv::rectangle(*image_tmp_,
00197 tl,
00198 br,
00199 color,
00200 1, 8, 0);
00201
00202
00203 }
00204
00205 cv::imshow(cv_win.c_str(), *image_tmp_);
00206
00207
00208
00209 }
00210
00211
00212 }
00213
00214 void CButBBEstimationControls::imageCallback(const sensor_msgs::ImageConstPtr& msg) {
00215
00216 ROS_INFO_ONCE("Received image");
00217
00218 if (disable_video_) return;
00219
00220
00221
00222
00223 try {
00224
00225
00226
00227
00228
00229
00230
00231
00232
00233 cv_bridge::CvImagePtr cv_ptr;
00234 cv_ptr = cv_bridge::toCvCopy(msg,msg->encoding);
00235
00236 image_mutex_.lock();
00237
00238 if (image_ != NULL) {
00239
00240 image_->release();
00241 delete image_;
00242
00243 }
00244
00245 image_ = new cv::Mat(cv_ptr->image);
00246
00247 image_mutex_.unlock();
00248
00249 } catch (cv_bridge::Exception& e) {
00250
00251 ROS_ERROR("cv_bridge exception: %s", e.what());
00252 return;
00253
00254 }
00255
00256 if (image_width_ == 0) {
00257
00258
00259 image_width_ = msg->width;
00260 image_height_ = msg->height;
00261
00262 }
00263
00264 }
00265
00266 void CButBBEstimationControls::newData(int event, int x, int y) {
00267
00268 if (!as_.isActive()) return;
00269
00270 switch(event) {
00271
00272 case CV_EVENT_LBUTTONDOWN: {
00273
00274 butt_down_x_ = x;
00275 butt_down_y_ = y;
00276
00277 } break;
00278
00279
00280 case CV_EVENT_MOUSEMOVE: {
00281
00282 if (butt_down_x_ != -1) {
00283
00284 some_data_ready_ = true;
00285
00286 data_mutex_.lock();
00287 p1_[0] = butt_down_x_;
00288 p1_[1] = butt_down_y_;
00289
00290 p2_[0] = x;
00291 p2_[1] = y;
00292 data_mutex_.unlock();
00293
00294 }
00295
00296
00297 } break;
00298
00299
00300 case CV_EVENT_LBUTTONUP: {
00301
00302 data_mutex_.lock();
00303
00304 p1_[0] = butt_down_x_;
00305 p1_[1] = butt_down_y_;
00306
00307 butt_down_x_ = -1;
00308 butt_down_y_ = -1;
00309
00310 p2_[0] = x;
00311 p2_[1] = y;
00312
00313 data_mutex_.unlock();
00314
00315 some_data_ready_ = false;
00316 data_ready_ = true;
00317
00318 if (!is_video_flipped_) {
00319
00320 fb_.p1[0] = p1_[0];
00321 fb_.p1[1] = p1_[1];
00322 fb_.p2[0] = p2_[0];
00323 fb_.p2[1] = p2_[1];
00324
00325 } else {
00326
00327 fb_.p1[0] = image_width_ - p1_[0];
00328 fb_.p1[1] = image_height_ - p1_[1];
00329 fb_.p2[0] = image_width_ - p2_[0];
00330 fb_.p2[1] = image_height_ - p2_[1];
00331
00332 }
00333
00334 fb_.timestamp = ros::Time::now();
00335
00336 as_.publishFeedback(fb_);
00337
00338 ROS_INFO("New ROI at [%d,%d], [%d,%d]",p1_[0],p1_[1],p2_[0],p2_[1]);
00339
00340 m_button_ok_->Enable(true);
00341
00342 } break;
00343
00344
00345 }
00346
00347
00348
00349 }
00350
00351 void onMouse(int event, int x, int y, int flags, void* param) {
00352
00353 if (class_ptr!=NULL)
00354 class_ptr->newData(event,x,y);
00355
00356 }
00357
00358 void CButBBEstimationControls::actionGoalCallback() {
00359
00360 ROS_INFO("Asking user to select ROI in image.");
00361
00362 goal_ = as_.acceptNewGoal();
00363
00364 disable_video_ = goal_->disable_video;
00365
00366 if (!disable_video_) {
00367
00368 sub_image_ = it_.subscribe("bb_video_in", 1, &CButBBEstimationControls::imageCallback,this);
00369
00370 wxMessageBox(wxString::FromAscii("Please select unknown object in image. You can select object in image several times. After selecting, it will appear as interactive marker in RVIZ and you can tune it. When it will fit real object, please click on \"Positioning finished\" button."), wxString::FromAscii("Assisted object detection"), wxOK, parent_,-1,-1);
00371
00372 cv::namedWindow(cv_win.c_str());
00373 cv::setMouseCallback(cv_win,onMouse,NULL);
00374
00375 } else {
00376
00377 wxMessageBox(wxString::FromAscii("Please tune position and orientation of interactive marker to fit the object. When finished, please click on \"Positioning finished\" button."), wxString::FromAscii("Assisted object detection"), wxOK, parent_,-1,-1);
00378 m_button_ok_->Enable(true);
00379
00380 }
00381
00382
00383
00384
00385
00386
00387
00388 action_in_progress_ = true;
00389
00390 }
00391
00392
00393
00394 void CButBBEstimationControls::actionPreemptCallback() {
00395
00396 ROS_INFO("%s: Preempted",ACT_BB_SELECT.c_str());
00397 as_.setPreempted();
00398
00399 action_in_progress_ = false;
00400 disable_video_ = false;
00401
00402 if (!disable_video_) {
00403
00404 cv::destroyWindow(cv_win.c_str());
00405 sub_image_.shutdown();
00406 some_data_ready_ = false;
00407 data_ready_ = false;
00408 image_width_ = 0;
00409 image_height_ = 0;
00410
00411 }
00412
00413 }
00414
00415 void CButBBEstimationControls::OnOk(wxCommandEvent& event) {
00416
00417
00418 if (!as_.isActive()) return;
00419
00420 ManualBBEstimationResult result;
00421
00422 if (!disable_video_) {
00423
00424 if (!is_video_flipped_) {
00425
00426 result.p1[0] = p1_[0];
00427 result.p1[1] = p1_[1];
00428 result.p2[0] = p2_[0];
00429 result.p2[1] = p2_[1];
00430
00431 } else {
00432
00433 result.p1[0] = image_width_ - p1_[0];
00434 result.p1[1] = image_height_ - p1_[1];
00435 result.p2[0] = image_width_ - p2_[0];
00436 result.p2[1] = image_height_ - p2_[1];
00437
00438 }
00439
00440 } else {
00441
00442 result.p1[0] = 0.0;
00443 result.p1[1] = 0.0;
00444 result.p2[0] = 0.0;
00445 result.p2[1] = 0.0;
00446
00447 }
00448
00449
00450
00451 as_.setSucceeded(result, "Go on...");
00452
00453 m_button_ok_->Enable(false);
00454
00455 if (disable_video_) {
00456
00457 cv::destroyWindow(cv_win.c_str());
00458 sub_image_.shutdown();
00459
00460 some_data_ready_ = false;
00461 data_ready_ = false;
00462 action_in_progress_ = false;
00463 image_width_ = 0;
00464 image_height_ = 0;
00465
00466 }
00467
00468 disable_video_ = false;
00469
00470 }
00471
00472
00473
00474
00475 BEGIN_EVENT_TABLE(CButBBEstimationControls, wxPanel)
00476 EVT_BUTTON(ID_BUTTON_OK, CButBBEstimationControls::OnOk)
00477 END_EVENT_TABLE()
00478