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 #include "interactive_markers/tools.h"
00031
00032 #include <tf/LinearMath/Quaternion.h>
00033 #include <tf/LinearMath/Matrix3x3.h>
00034
00035 #include <math.h>
00036 #include <assert.h>
00037
00038 #include <set>
00039 #include <sstream>
00040
00041 namespace interactive_markers
00042 {
00043
00044 void autoComplete( visualization_msgs::InteractiveMarker &msg )
00045 {
00046
00047 if ( msg.controls.empty() )
00048 {
00049 return;
00050 }
00051
00052
00053 if ( msg.scale == 0 )
00054 {
00055 msg.scale = 1;
00056 }
00057
00058
00059 if ( msg.pose.orientation.w == 0 && msg.pose.orientation.x == 0 &&
00060 msg.pose.orientation.y == 0 && msg.pose.orientation.z == 0 )
00061 {
00062 msg.pose.orientation.w = 1;
00063 }
00064
00065
00066 tf::Quaternion int_marker_orientation( msg.pose.orientation.x, msg.pose.orientation.y,
00067 msg.pose.orientation.z, msg.pose.orientation.w );
00068 int_marker_orientation.normalize();
00069 msg.pose.orientation.x = int_marker_orientation.x();
00070 msg.pose.orientation.y = int_marker_orientation.y();
00071 msg.pose.orientation.z = int_marker_orientation.z();
00072 msg.pose.orientation.w = int_marker_orientation.w();
00073
00074
00075 for ( unsigned c=0; c<msg.controls.size(); c++ )
00076 {
00077 autoComplete( msg, msg.controls[c] );
00078 }
00079
00080 uniqueifyControlNames( msg );
00081 }
00082
00083 void uniqueifyControlNames( visualization_msgs::InteractiveMarker& msg )
00084 {
00085 int uniqueification_number = 0;
00086 std::set<std::string> names;
00087 for( unsigned c = 0; c < msg.controls.size(); c++ )
00088 {
00089 std::string name = msg.controls[c].name;
00090 while( names.find( name ) != names.end() )
00091 {
00092 std::stringstream ss;
00093 ss << name << "_u" << uniqueification_number++;
00094 name = ss.str();
00095 }
00096 msg.controls[c].name = name;
00097 names.insert( name );
00098 }
00099 }
00100
00101 void autoComplete( const visualization_msgs::InteractiveMarker &msg,
00102 visualization_msgs::InteractiveMarkerControl &control )
00103 {
00104
00105 if ( control.orientation.w == 0 && control.orientation.x == 0 &&
00106 control.orientation.y == 0 && control.orientation.z == 0 )
00107 {
00108 control.orientation.w = 1;
00109 }
00110
00111
00112 if ( control.description.empty() )
00113 {
00114 switch ( control.interaction_mode )
00115 {
00116 case visualization_msgs::InteractiveMarkerControl::NONE:
00117 break;
00118
00119 case visualization_msgs::InteractiveMarkerControl::MOVE_AXIS:
00120 control.description = "Drag to move along the axis.";
00121 break;
00122
00123 case visualization_msgs::InteractiveMarkerControl::MOVE_PLANE:
00124 control.description = "Drag to move in the plane.";
00125 break;
00126
00127 case visualization_msgs::InteractiveMarkerControl::ROTATE_AXIS:
00128 control.description = "Drag to rotate.";
00129 break;
00130
00131 case visualization_msgs::InteractiveMarkerControl::MOVE_ROTATE:
00132 control.description = "Drag to rotate and move.";
00133 break;
00134
00135 case visualization_msgs::InteractiveMarkerControl::BUTTON:
00136 control.description = "Click to activate.";
00137 break;
00138
00139 case visualization_msgs::InteractiveMarkerControl::MENU:
00140 control.description = "Menu";
00141 break;
00142
00143 default:
00144 break;
00145 }
00146 }
00147
00148
00149 if ( control.markers.empty() )
00150 {
00151 switch ( control.interaction_mode )
00152 {
00153 case visualization_msgs::InteractiveMarkerControl::NONE:
00154 break;
00155
00156 case visualization_msgs::InteractiveMarkerControl::MOVE_AXIS:
00157 control.markers.reserve(2);
00158 makeArrow( msg, control, 1.0 );
00159 makeArrow( msg, control, -1.0 );
00160 break;
00161
00162 case visualization_msgs::InteractiveMarkerControl::MOVE_PLANE:
00163 case visualization_msgs::InteractiveMarkerControl::ROTATE_AXIS:
00164 case visualization_msgs::InteractiveMarkerControl::MOVE_ROTATE:
00165 makeDisc( msg, control );
00166 break;
00167
00168 case visualization_msgs::InteractiveMarkerControl::BUTTON:
00169 break;
00170
00171 case visualization_msgs::InteractiveMarkerControl::MENU:
00172 makeViewFacingButton( msg, control, control.description );
00173 break;
00174
00175 default:
00176 break;
00177 }
00178 }
00179
00180
00181 tf::Quaternion int_marker_orientation( msg.pose.orientation.x, msg.pose.orientation.y,
00182 msg.pose.orientation.z, msg.pose.orientation.w );
00183 tf::Vector3 int_marker_position( msg.pose.position.x, msg.pose.position.y, msg.pose.position.z );
00184
00185
00186 for ( unsigned m=0; m<control.markers.size(); m++ )
00187 {
00188 visualization_msgs::Marker &marker = control.markers[m];
00189
00190 if ( marker.scale.x == 0 )
00191 {
00192 marker.scale.x = 1;
00193 }
00194 if ( marker.scale.y == 0 )
00195 {
00196 marker.scale.y = 1;
00197 }
00198 if ( marker.scale.z == 0 )
00199 {
00200 marker.scale.z = 1;
00201 }
00202
00203 marker.ns = msg.name;
00204
00205
00206 if ( marker.pose.orientation.w == 0 && marker.pose.orientation.x == 0 &&
00207 marker.pose.orientation.y == 0 && marker.pose.orientation.z == 0 )
00208 {
00209 marker.pose.orientation.w = 1;
00210 }
00211
00212
00213 tf::Quaternion marker_orientation( marker.pose.orientation.x, marker.pose.orientation.y,
00214 marker.pose.orientation.z, marker.pose.orientation.w );
00215 tf::Vector3 marker_position( marker.pose.position.x, marker.pose.position.y, marker.pose.position.z );
00216
00217 marker_orientation.normalize();
00218
00219
00220 if ( marker.header.frame_id.empty() )
00221 {
00222 marker.header = msg.header;
00223
00224
00225 if ( control.orientation_mode == visualization_msgs::InteractiveMarkerControl::INHERIT )
00226 {
00227 marker_orientation = int_marker_orientation * marker_orientation;
00228 }
00229 marker_position = int_marker_position + ( tf::Matrix3x3(int_marker_orientation) * marker_position);
00230 }
00231
00232
00233 marker.pose.position.x = marker_position.x();
00234 marker.pose.position.y = marker_position.y();
00235 marker.pose.position.z = marker_position.z();
00236
00237 marker.pose.orientation.x = marker_orientation.x();
00238 marker.pose.orientation.y = marker_orientation.y();
00239 marker.pose.orientation.z = marker_orientation.z();
00240 marker.pose.orientation.w = marker_orientation.w();
00241
00242 static volatile unsigned id = 0;
00243 marker.id = id++;
00244 marker.ns = msg.name;
00245 }
00246 }
00247
00248 void makeArrow( const visualization_msgs::InteractiveMarker &msg,
00249 visualization_msgs::InteractiveMarkerControl &control, float pos )
00250 {
00251 visualization_msgs::Marker marker;
00252
00253
00254 marker.pose.orientation = control.orientation;
00255
00256 marker.type = visualization_msgs::Marker::ARROW;
00257 marker.scale.x = msg.scale * 0.3;
00258 marker.scale.y = msg.scale * 0.5;
00259 marker.scale.z = msg.scale * 0.2;
00260
00261 assignDefaultColor(marker, control.orientation);
00262
00263 float dist = fabs(pos);
00264 float dir = pos > 0 ? 1 : -1;
00265
00266 float inner = 0.5 * dist;
00267 float outer = inner + 0.4;
00268
00269 marker.points.resize(2);
00270 marker.points[0].x = dir * msg.scale * inner;
00271 marker.points[1].x = dir * msg.scale * outer;
00272
00273 control.markers.push_back( marker );
00274 }
00275
00276 void makeDisc( const visualization_msgs::InteractiveMarker &msg,
00277 visualization_msgs::InteractiveMarkerControl &control, float width )
00278 {
00279 visualization_msgs::Marker marker;
00280
00281
00282 marker.pose.orientation = control.orientation;
00283
00284 marker.type = visualization_msgs::Marker::TRIANGLE_LIST;
00285 marker.scale.x = msg.scale;
00286 marker.scale.y = msg.scale;
00287 marker.scale.z = msg.scale;
00288
00289 assignDefaultColor(marker, control.orientation);
00290
00291
00292 int steps = 36;
00293 std::vector<geometry_msgs::Point> circle1, circle2;
00294 circle1.reserve(steps);
00295 circle2.reserve(steps);
00296
00297 geometry_msgs::Point v1,v2;
00298
00299 for ( int i=0; i<steps; i++ )
00300 {
00301 float a = float(i)/float(steps) * M_PI * 2.0;
00302
00303 v1.y = 0.5 * cos(a);
00304 v1.z = 0.5 * sin(a);
00305
00306 v2.y = (1+width) * v1.y;
00307 v2.z = (1+width) * v1.z;
00308
00309 circle1.push_back( v1 );
00310 circle2.push_back( v2 );
00311 }
00312
00313
00314 control.markers.reserve( control.markers.size() + steps );
00315
00316 switch ( control.interaction_mode )
00317 {
00318 case visualization_msgs::InteractiveMarkerControl::ROTATE_AXIS:
00319 {
00320 marker.points.resize(6);
00321 std_msgs::ColorRGBA base_color = marker.color;
00322 for ( int i=0; i<steps; i++ )
00323 {
00324 int i1 = i;
00325 int i2 = (i+1) % steps;
00326 int i3 = (i+2) % steps;
00327
00328 marker.points[0] = circle1[i1];
00329 marker.points[1] = circle2[i2];
00330 marker.points[2] = circle1[i2];
00331
00332 marker.points[3] = circle1[i2];
00333 marker.points[4] = circle2[i2];
00334 marker.points[5] = circle2[i3];
00335
00336 float t = 0.6 + 0.4 * (i%2);
00337 marker.color.r = base_color.r * t;
00338 marker.color.g = base_color.g * t;
00339 marker.color.b = base_color.b * t;
00340 control.markers.push_back(marker);
00341 }
00342 break;
00343 }
00344
00345 case visualization_msgs::InteractiveMarkerControl::MOVE_ROTATE:
00346 {
00347 marker.points.resize(6);
00348 std_msgs::ColorRGBA base_color = marker.color;
00349 for ( int i=0; i<steps-1; i+=2 )
00350 {
00351 int i1 = i;
00352 int i2 = (i+1) % steps;
00353 int i3 = (i+2) % steps;
00354
00355 marker.points[0] = circle1[i1];
00356 marker.points[1] = circle2[i2];
00357 marker.points[2] = circle1[i2];
00358
00359 marker.points[3] = circle1[i2];
00360 marker.points[4] = circle2[i2];
00361 marker.points[5] = circle1[i3];
00362
00363 marker.color.r = base_color.r * 0.6;
00364 marker.color.g = base_color.g * 0.6;
00365 marker.color.b = base_color.b * 0.6;
00366 control.markers.push_back(marker);
00367
00368 marker.points[0] = circle2[i1];
00369 marker.points[1] = circle2[i2];
00370 marker.points[2] = circle1[i1];
00371
00372 marker.points[3] = circle2[i2];
00373 marker.points[4] = circle2[i3];
00374 marker.points[5] = circle1[i3];
00375
00376 marker.color = base_color;
00377 control.markers.push_back(marker);
00378 }
00379 break;
00380 }
00381
00382 default:
00383 marker.points.resize(6);
00384
00385 for ( int i=0; i<steps; i++ )
00386 {
00387 int i1 = i;
00388 int i2 = (i+1) % steps;
00389
00390 marker.points[0] = circle1[i1];
00391 marker.points[1] = circle2[i1];
00392 marker.points[2] = circle1[i2];
00393
00394 marker.points[3] = circle2[i1];
00395 marker.points[4] = circle2[i2];
00396 marker.points[5] = circle1[i2];
00397
00398 control.markers.push_back(marker);
00399 }
00400 }
00401 }
00402
00403 void makeViewFacingButton( const visualization_msgs::InteractiveMarker &msg,
00404 visualization_msgs::InteractiveMarkerControl &control, std::string text )
00405 {
00406 control.orientation_mode = visualization_msgs::InteractiveMarkerControl::VIEW_FACING;
00407 control.independent_marker_orientation = false;
00408
00409 visualization_msgs::Marker marker;
00410
00411 float base_scale = 0.25 * msg.scale;
00412 float base_z = 1.2 * msg.scale;
00413
00414 marker.type = visualization_msgs::Marker::TEXT_VIEW_FACING;
00415 marker.scale.x = base_scale;
00416 marker.scale.y = base_scale;
00417 marker.scale.z = base_scale;
00418 marker.color.r = 1.0;
00419 marker.color.g = 1.0;
00420 marker.color.b = 1.0;
00421 marker.color.a = 1.0;
00422 marker.pose.position.x = base_scale * -0.1;
00423 marker.pose.position.z = base_z + base_scale * -0.1;
00424 marker.text = text;
00425
00426 control.markers.push_back( marker );
00427 }
00428
00429
00430 void assignDefaultColor(visualization_msgs::Marker &marker, const geometry_msgs::Quaternion &quat )
00431 {
00432 geometry_msgs::Vector3 v;
00433
00434 tf::Quaternion bt_quat( quat.x, quat.y, quat.z, quat.w );
00435 tf::Vector3 bt_x_axis = tf::Matrix3x3(bt_quat) * tf::Vector3(1,0,0);
00436
00437 float x,y,z;
00438 x = fabs(bt_x_axis.x());
00439 y = fabs(bt_x_axis.y());
00440 z = fabs(bt_x_axis.z());
00441
00442 float max_xy = x>y ? x : y;
00443 float max_yz = y>z ? y : z;
00444 float max_xyz = max_xy > max_yz ? max_xy : max_yz;
00445
00446 marker.color.r = x / max_xyz;
00447 marker.color.g = y / max_xyz;
00448 marker.color.b = z / max_xyz;
00449 marker.color.a = 0.5;
00450 }
00451
00452
00453 visualization_msgs::InteractiveMarkerControl makeTitle( visualization_msgs::InteractiveMarker &msg )
00454 {
00455 visualization_msgs::Marker marker;
00456
00457 marker.type = visualization_msgs::Marker::TEXT_VIEW_FACING;
00458 marker.scale.x = msg.scale * 0.15;
00459 marker.scale.y = msg.scale * 0.15;
00460 marker.scale.z = msg.scale * 0.15;
00461 marker.color.r = 1.0;
00462 marker.color.g = 1.0;
00463 marker.color.b = 1.0;
00464 marker.color.a = 1.0;
00465 marker.pose.position.z = msg.scale * 1.4;
00466 marker.text = msg.description;
00467
00468 visualization_msgs::InteractiveMarkerControl control;
00469 control.interaction_mode = visualization_msgs::InteractiveMarkerControl::NONE;
00470 control.orientation_mode = visualization_msgs::InteractiveMarkerControl::VIEW_FACING;
00471 control.always_visible = true;
00472 control.markers.push_back( marker );
00473
00474 autoComplete( msg, control );
00475
00476 return control;
00477 }
00478
00479 }