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
00035 #include <ros/ros.h>
00036 #include <interactive_markers/interactive_marker_server.h>
00037
00038
00039 #include <interactive_markers/menu_handler.h>
00040 #include <tf/transform_broadcaster.h>
00041 #include <tf/tf.h>
00042 #include <math.h>
00043 #include <sensor_msgs/JointState.h>
00044
00045 using namespace visualization_msgs;
00046
00047
00048
00049 boost::shared_ptr<interactive_markers::InteractiveMarkerServer> server;
00050 float marker_pos = 0;
00051 interactive_markers::MenuHandler menu_handler;
00052 ros::Publisher pub;
00053
00054
00055
00056 void frameCallback(const ros::TimerEvent&)
00057 {
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072
00073
00074
00075 }
00076
00077
00078
00079 void processFeedback( const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback )
00080 {
00081 std::ostringstream s;
00082 s << "Feedback from marker '" << feedback->marker_name << "' "
00083 << " / control '" << feedback->control_name << "'";
00084
00085 std::ostringstream mouse_point_ss;
00086 if( feedback->mouse_point_valid )
00087 {
00088 mouse_point_ss << " at " << feedback->mouse_point.x
00089 << ", " << feedback->mouse_point.y
00090 << ", " << feedback->mouse_point.z
00091 << " in frame " << feedback->header.frame_id;
00092 }
00093
00094 switch ( feedback->event_type )
00095 {
00096
00097
00098
00099
00100
00101
00102
00103
00104 case visualization_msgs::InteractiveMarkerFeedback::POSE_UPDATE:
00105
00106 tf::Quaternion q;
00107 q[0] = feedback->pose.orientation.x;
00108 q[1] = feedback->pose.orientation.y;
00109 q[2] = feedback->pose.orientation.z;
00110 q[3] = feedback->pose.orientation.w;
00111 tf::Matrix3x3 M(q);
00112 double r,p,y;
00113 #if ROS_VERSION_MINIMUM(1, 8, 0) // if current ros version is >= 1.8.0
00114 M.getEulerYPR(y, p, r);
00115 #else // Code for earlier versions (Electric, diamondback, ...)
00116 M.getRPY(r,p,y);
00117 #endif
00118
00119 sensor_msgs::JointState joint_state;
00120 joint_state.header.stamp = ros::Time::now();
00121 joint_state.name.resize(2);
00122 joint_state.position.resize(2);
00123 joint_state.name[0] =ros::names::remap("pan");
00124 joint_state.position[0] = y;
00125 joint_state.name[1] =ros::names::remap("tilt");
00126 joint_state.position[1] = p;
00127 pub.publish(joint_state);
00128
00129
00130
00131 ROS_INFO_STREAM( s.str() << ": pose changed"
00132 << "\nposition = "
00133 << feedback->pose.position.x
00134 << ", " << feedback->pose.position.y
00135 << ", " << feedback->pose.position.z
00136 << "\norientation = "
00137 << feedback->pose.orientation.w
00138 << ", " << feedback->pose.orientation.x
00139 << ", " << feedback->pose.orientation.y
00140 << ", " << feedback->pose.orientation.z
00141 << "\nframe: " << feedback->header.frame_id
00142 << " time: " << feedback->header.stamp.sec << "sec, "
00143 << feedback->header.stamp.nsec << " nsec" );
00144 break;
00145
00146
00147
00148
00149
00150
00151
00152
00153 }
00154
00155 server->applyChanges();
00156 }
00157
00158
00159
00160 void alignMarker( const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback )
00161 {
00162 geometry_msgs::Pose pose = feedback->pose;
00163
00164 pose.position.x = round(pose.position.x-0.5)+0.5;
00165 pose.position.y = round(pose.position.y-0.5)+0.5;
00166
00167 ROS_INFO_STREAM( feedback->marker_name << ":"
00168 << " aligning position = "
00169 << feedback->pose.position.x
00170 << ", " << feedback->pose.position.y
00171 << ", " << feedback->pose.position.z
00172 << " to "
00173 << pose.position.x
00174 << ", " << pose.position.y
00175 << ", " << pose.position.z );
00176
00177 server->setPose( feedback->marker_name, pose );
00178 server->applyChanges();
00179 }
00180
00181
00182 double rand( double min, double max )
00183 {
00184 double t = (double)rand() / (double)RAND_MAX;
00185 return min + t*(max-min);
00186 }
00187
00188
00189 Marker makeBox( InteractiveMarker &msg )
00190 {
00191 Marker marker;
00192
00193 marker.type = Marker::SPHERE;
00194 marker.scale.x = msg.scale * 0.45;
00195 marker.scale.y = msg.scale * 0.45;
00196 marker.scale.z = msg.scale * 0.45;
00197 marker.color.r = 0;
00198 marker.color.g = 0.7;
00199 marker.color.b = 0;
00200 marker.color.a = 0.6;
00201
00202 return marker;
00203 }
00204
00205 InteractiveMarkerControl& makeBoxControl( InteractiveMarker &msg )
00206 {
00207 InteractiveMarkerControl control;
00208 control.always_visible = true;
00209 control.markers.push_back( makeBox(msg) );
00210 msg.controls.push_back( control );
00211
00212 return msg.controls.back();
00213 }
00214
00215
00216 void saveMarker( InteractiveMarker int_marker )
00217 {
00218 server->insert(int_marker);
00219 server->setCallback(int_marker.name, &processFeedback);
00220 }
00221
00223
00224
00225 void make6DofMarker( bool fixed )
00226 {
00227 InteractiveMarker int_marker;
00228 int_marker.header.frame_id = "/atc/vehicle/center_bumper";
00229 int_marker.pose.position.x = 2;
00230 int_marker.pose.position.y = 0;
00231 int_marker.pose.position.z = 0.5;
00232 int_marker.scale = 0.5;
00233
00234 int_marker.name = "Fovetation Control Target";
00235 int_marker.description = "Foveation_control will try \nto aim the PTU towards\n the marker";
00236
00237
00238 makeBoxControl(int_marker);
00239 InteractiveMarkerControl control;
00240
00241 if ( fixed )
00242 {
00243
00244
00245
00246 }
00247
00248 control.orientation.w = 1;
00249 control.orientation.x = 1;
00250 control.orientation.y = 0;
00251 control.orientation.z = 0;
00252
00253
00254
00255 control.name = "move_x";
00256 control.interaction_mode = InteractiveMarkerControl::MOVE_AXIS;
00257 int_marker.controls.push_back(control);
00258
00259 control.orientation.w = 1;
00260 control.orientation.x = 0;
00261 control.orientation.y = 1;
00262 control.orientation.z = 0;
00263
00264
00265
00266 control.name = "move_z";
00267 control.interaction_mode = InteractiveMarkerControl::MOVE_AXIS;
00268 int_marker.controls.push_back(control);
00269
00270 control.orientation.w = 1;
00271 control.orientation.x = 0;
00272 control.orientation.y = 0;
00273 control.orientation.z = 1;
00274
00275
00276
00277 control.name = "move_y";
00278 control.interaction_mode = InteractiveMarkerControl::MOVE_AXIS;
00279 int_marker.controls.push_back(control);
00280
00281 server->insert(int_marker);
00282 server->setCallback(int_marker.name, &processFeedback);
00283 }
00284
00285
00286
00287 void makeRandomDofMarker( )
00288 {
00289 InteractiveMarker int_marker;
00290 int_marker.header.frame_id = "/base_link";
00291 int_marker.pose.position.y = -3.0 * marker_pos++;;
00292 int_marker.scale = 1;
00293
00294 int_marker.name = "6dof_random_axes";
00295 int_marker.description = "6-DOF\n(Arbitrary Axes)";
00296
00297 makeBoxControl(int_marker);
00298
00299 InteractiveMarkerControl control;
00300
00301 for ( int i=0; i<3; i++ )
00302 {
00303 control.orientation.w = rand(-1,1);
00304 control.orientation.x = rand(-1,1);
00305 control.orientation.y = rand(-1,1);
00306 control.orientation.z = rand(-1,1);
00307 control.interaction_mode = InteractiveMarkerControl::ROTATE_AXIS;
00308 int_marker.controls.push_back(control);
00309 control.interaction_mode = InteractiveMarkerControl::MOVE_AXIS;
00310 int_marker.controls.push_back(control);
00311 }
00312
00313 server->insert(int_marker);
00314 server->setCallback(int_marker.name, &processFeedback);
00315 }
00316
00317
00318
00319
00320 void makeViewFacingMarker( )
00321 {
00322 InteractiveMarker int_marker;
00323 int_marker.header.frame_id = "/base_link";
00324 int_marker.pose.position.y = -3.0 * marker_pos++;;
00325 int_marker.scale = 1;
00326
00327 int_marker.name = "view_facing";
00328 int_marker.description = "View Facing 6-DOF";
00329
00330 InteractiveMarkerControl control;
00331
00332
00333 control.orientation_mode = InteractiveMarkerControl::VIEW_FACING;
00334 control.interaction_mode = InteractiveMarkerControl::ROTATE_AXIS;
00335 control.orientation.w = 1;
00336 control.name = "rotate";
00337
00338 int_marker.controls.push_back(control);
00339
00340
00341
00342 control.orientation_mode = InteractiveMarkerControl::VIEW_FACING;
00343 control.interaction_mode = InteractiveMarkerControl::MOVE_PLANE;
00344 control.independent_marker_orientation = true;
00345 control.name = "move";
00346
00347 control.markers.push_back( makeBox(int_marker) );
00348 control.always_visible = true;
00349
00350 int_marker.controls.push_back(control);
00351
00352 server->insert(int_marker);
00353 server->setCallback(int_marker.name, &processFeedback);
00354 }
00355
00356
00357
00358
00359 void makeQuadrocopterMarker( )
00360 {
00361 InteractiveMarker int_marker;
00362 int_marker.header.frame_id = "/base_link";
00363 int_marker.pose.position.y = -3.0 * marker_pos++;;
00364 int_marker.scale = 1;
00365
00366 int_marker.name = "quadrocopter";
00367 int_marker.description = "Quadrocopter";
00368
00369 makeBoxControl(int_marker);
00370
00371 InteractiveMarkerControl control;
00372
00373 control.orientation.w = 1;
00374 control.orientation.x = 0;
00375 control.orientation.y = 1;
00376 control.orientation.z = 0;
00377 control.interaction_mode = InteractiveMarkerControl::MOVE_ROTATE;
00378 int_marker.controls.push_back(control);
00379 control.interaction_mode = InteractiveMarkerControl::MOVE_AXIS;
00380 int_marker.controls.push_back(control);
00381
00382 server->insert(int_marker);
00383 server->setCallback(int_marker.name, &processFeedback);
00384 }
00385
00386
00387
00388 void makeChessPieceMarker( )
00389 {
00390 InteractiveMarker int_marker;
00391 int_marker.header.frame_id = "/base_link";
00392 int_marker.pose.position.y = -3.0 * marker_pos++;;
00393 int_marker.scale = 1;
00394
00395 int_marker.name = "chess_piece";
00396 int_marker.description = "Chess Piece\n(2D Move + Alignment)";
00397
00398 InteractiveMarkerControl control;
00399
00400 control.orientation.w = 1;
00401 control.orientation.x = 0;
00402 control.orientation.y = 1;
00403 control.orientation.z = 0;
00404 control.interaction_mode = InteractiveMarkerControl::MOVE_PLANE;
00405 int_marker.controls.push_back(control);
00406
00407
00408 control.markers.push_back( makeBox(int_marker) );
00409 control.always_visible = true;
00410 int_marker.controls.push_back(control);
00411
00412
00413 server->insert(int_marker);
00414 server->setCallback(int_marker.name, &processFeedback);
00415
00416
00417 server->setCallback(int_marker.name, &alignMarker, visualization_msgs::InteractiveMarkerFeedback::POSE_UPDATE );
00418 }
00419
00420
00421
00422 void makePanTiltMarker( )
00423 {
00424 InteractiveMarker int_marker;
00425 int_marker.header.frame_id = "/atc/ptu/base";
00426 int_marker.pose.position.x = 0;
00427 int_marker.pose.position.y = 0;
00428 int_marker.pose.position.z = 0;
00429 int_marker.scale = 0.1;
00430
00431 int_marker.name = "/marker";
00432 int_marker.description = " Pan/Tilt control";
00433
00434 makeBoxControl(int_marker);
00435
00436 InteractiveMarkerControl control;
00437
00438 control.orientation.w = 1;
00439 control.orientation.x = 0;
00440 control.orientation.y = 1;
00441 control.orientation.z = 0;
00442 control.interaction_mode = InteractiveMarkerControl::ROTATE_AXIS;
00443 control.orientation_mode = InteractiveMarkerControl::FIXED;
00444 int_marker.controls.push_back(control);
00445
00446 control.orientation.w = 1;
00447 control.orientation.x = 0;
00448 control.orientation.y = 0;
00449 control.orientation.z = 1;
00450 control.interaction_mode = InteractiveMarkerControl::ROTATE_AXIS;
00451 control.orientation_mode = InteractiveMarkerControl::INHERIT;
00452 int_marker.controls.push_back(control);
00453
00454 server->insert(int_marker);
00455 server->setCallback(int_marker.name, &processFeedback);
00456 }
00457
00458
00459
00460 void makeMenuMarker()
00461 {
00462 InteractiveMarker int_marker;
00463 int_marker.header.frame_id = "/atc/ptu/base";
00464 int_marker.pose.position.y = -3.0 * marker_pos++;;
00465 int_marker.scale = 1;
00466
00467 int_marker.name = "context_menu";
00468 int_marker.description = "Context Menu\n(Right Click)";
00469
00470 InteractiveMarkerControl control;
00471
00472
00473 control.interaction_mode = InteractiveMarkerControl::MENU;
00474 control.description="Options";
00475 control.name = "menu_only_control";
00476 int_marker.controls.push_back(control);
00477
00478
00479 Marker marker = makeBox( int_marker );
00480 control.markers.push_back( marker );
00481 control.always_visible = true;
00482 int_marker.controls.push_back(control);
00483
00484 server->insert(int_marker);
00485 server->setCallback(int_marker.name, &processFeedback);
00486 menu_handler.apply( *server, int_marker.name );
00487 }
00488
00489
00490
00491 void makeMovingMarker()
00492 {
00493 InteractiveMarker int_marker;
00494 int_marker.header.frame_id = "/moving_frame";
00495 int_marker.pose.position.y = -3.0 * marker_pos++;;
00496 int_marker.scale = 1;
00497
00498 int_marker.name = "moving";
00499 int_marker.description = "Marker Attached to a\nMoving Frame";
00500
00501 InteractiveMarkerControl control;
00502
00503 control.orientation.w = 1;
00504 control.orientation.x = 1;
00505 control.orientation.y = 0;
00506 control.orientation.z = 0;
00507 control.interaction_mode = InteractiveMarkerControl::ROTATE_AXIS;
00508 int_marker.controls.push_back(control);
00509
00510 control.interaction_mode = InteractiveMarkerControl::MOVE_PLANE;
00511 control.always_visible = true;
00512 control.markers.push_back( makeBox(int_marker) );
00513 int_marker.controls.push_back(control);
00514
00515 server->insert(int_marker);
00516 server->setCallback(int_marker.name, &processFeedback);
00517 }
00518
00519
00520
00521 int main(int argc, char** argv)
00522 {
00523 ros::init(argc, argv, "ptu_interactive_control_node");
00524 ros::NodeHandle n;
00525
00526
00527 pub = n.advertise<sensor_msgs::JointState>("/ptu_cmd", 1);
00528
00529
00530
00531
00532
00533 server.reset( new interactive_markers::InteractiveMarkerServer("direct/im","",false) );
00534
00535 ros::Duration(0.1).sleep();
00536
00537
00538 menu_handler.insert( "First Entry", &processFeedback );
00539 menu_handler.insert( "Second Entry", &processFeedback );
00540 interactive_markers::MenuHandler::EntryHandle sub_menu_handle = menu_handler.insert( "Submenu" );
00541 menu_handler.insert( sub_menu_handle, "First Entry", &processFeedback );
00542 menu_handler.insert( sub_menu_handle, "Second Entry", &processFeedback );
00543
00544
00545
00546
00547
00548
00549
00550 makePanTiltMarker( );
00551
00552
00553
00554 server->applyChanges();
00555
00556 ros::spin();
00557
00558 server.reset();
00559 }
00560
00561
00562
00563