New in Electric

Note: This tutorial assumes that you have completed the previous tutorials: ROS Tutorials.

Interactive Markers: Basic Controls

Description: This tutorial explains how the basic_controls tutorial code works.

Tutorial Level: BEGINNER

The basic_controls tutorial explained

The basic_controls tutorial showing in RViz

This tutorial shows you most of the common options you have for designing interactive markers. The node providing will print all feedback it gets from RViz on the command line.

All interactive markers contain a grey box, which in most cases will do nothing more than move together with the rest of the controls. It will show you how the coordinate frame of the Interactive Marker moves.

Simple 6-DOF control

The structure of an <<MsgLink(visualization_msgs/InteractiveMarker)>> message

This shows how to control all 6 degrees of freedom using 6 separate controls. Use the rings to rotate and the arrows to move the structure.

Simple 6-DOF control (fixed orientation)

The structure of an <<MsgLink(visualization_msgs/InteractiveMarker)>> message

Identical to the 6-DOF control, with the exception that the orientation of the controls will stay fixed, independent of the orientation of the frame being controlled.

https://code.ros.org/svn/ros-pkg/stacks/visualization_tutorials/trunk/interactive_marker_tutorials/src/basic_controls.cpp

  49 Marker makeBox( InteractiveMarker &msg )
  50 {
  51   Marker marker;
  52 
  53   marker.type = Marker::CUBE;
  54   marker.scale.x = msg.scale * 0.45;
  55   marker.scale.y = msg.scale * 0.45;
  56   marker.scale.z = msg.scale * 0.45;
  57   marker.color.r = 0.5;
  58   marker.color.g = 0.5;
  59   marker.color.b = 0.5;
  60   marker.color.a = 1.0;
  61 
  62   return marker;
  63 }
  64 
  65 InteractiveMarkerControl& makeBoxControl( InteractiveMarker &msg )
  66 {
  67   InteractiveMarkerControl control;
  68   control.always_visible = true;
  69   control.markers.push_back( makeBox(msg) );
  70   msg.controls.push_back( control );
  71 
  72   return msg.controls.back();
  73 }

https://code.ros.org/svn/ros-pkg/stacks/visualization_tutorials/trunk/interactive_marker_tutorials/src/basic_controls.cpp

 259 void make6DofMarker( bool fixed )
 260 {
 261   InteractiveMarker int_marker;
 262   int_marker.header.frame_id = "/base_link";
 263   int_marker.pose.position.y = -3.0 * marker_pos++;;
 264   int_marker.scale = 1;
 265 
 266   int_marker.name = "simple_6dof";
 267   int_marker.description = "Simple 6-DOF Control";
 268 
 269   // insert a box
 270   makeBoxControl(int_marker);
 271 
 272   InteractiveMarkerControl control;
 273 
 274   if ( fixed )
 275   {
 276     int_marker.name += "_fixed";
 277     int_marker.description += "\n(fixed orientation)";
 278     control.orientation_mode = InteractiveMarkerControl::FIXED;
 279   }
 280 
 281   control.orientation.w = 1;
 282   control.orientation.x = 1;
 283   control.orientation.y = 0;
 284   control.orientation.z = 0;
 285   control.name = "rotate_x";
 286   control.interaction_mode = InteractiveMarkerControl::ROTATE_AXIS;
 287   int_marker.controls.push_back(control);
 288   control.name = "move_x";
 289   control.interaction_mode = InteractiveMarkerControl::MOVE_AXIS;
 290   int_marker.controls.push_back(control);
 291 
 292   control.orientation.w = 1;
 293   control.orientation.x = 0;
 294   control.orientation.y = 1;
 295   control.orientation.z = 0;
 296   control.name = "rotate_z";
 297   control.interaction_mode = InteractiveMarkerControl::ROTATE_AXIS;
 298   int_marker.controls.push_back(control);
 299   control.name = "move_z";
 300   control.interaction_mode = InteractiveMarkerControl::MOVE_AXIS;
 301   int_marker.controls.push_back(control);
 302 
 303   control.orientation.w = 1;
 304   control.orientation.x = 0;
 305   control.orientation.y = 0;
 306   control.orientation.z = 1;
 307   control.name = "rotate_y";
 308   control.interaction_mode = InteractiveMarkerControl::ROTATE_AXIS;
 309   int_marker.controls.push_back(control);
 310   control.name = "move_y";
 311   control.interaction_mode = InteractiveMarkerControl::MOVE_AXIS;
 312   int_marker.controls.push_back(control);
 313 
 314   server->insert(int_marker);
 315   server->setCallback(int_marker.name, &processFeedback);
 316 }

The code section above shows how to construct the first two interactive markers. After adding the grey box, 6 controls for each degree of freedom are added. No markers are added to these controls, which will result in RViz creating a set of colored rings and arrows as a default visualization.

The only difference between the two is that in the second case, the orientation mode is set to InteractiveMarkerControl::FIXED, while in the first it is left at its default value, which is InteractiveMarkerControl::INHERIT.

NOTE: The orientations in the above code snippet can be confusing. If you compute the rotation matrices corresponding to each of the quaternions, you can verify that the specified orientation is correct.

6-DOF (Arbitrary Axes)

The structure of an <<MsgLink(visualization_msgs/InteractiveMarker)>> message

Shows that controls are not limited to the unit axes but can work on any arbitrary orientation.

https://code.ros.org/svn/ros-pkg/stacks/visualization_tutorials/trunk/interactive_marker_tutorials/src/basic_controls.cpp

 318 void makeRandomDofMarker( )
 319 {
 320   InteractiveMarker int_marker;
 321   int_marker.header.frame_id = "/base_link";
 322   int_marker.pose.position.y = -3.0 * marker_pos++;;
 323   int_marker.scale = 1;
 324 
 325   int_marker.name = "6dof_random_axes";
 326   int_marker.description = "6-DOF\n(Arbitrary Axes)";
 327 
 328   makeBoxControl(int_marker);
 329 
 330   InteractiveMarkerControl control;
 331 
 332   for ( int i=0; i<3; i++ )
 333   {
 334     control.orientation.w = rand(-1,1);
 335     control.orientation.x = rand(-1,1);
 336     control.orientation.y = rand(-1,1);
 337     control.orientation.z = rand(-1,1);
 338     control.interaction_mode = InteractiveMarkerControl::ROTATE_AXIS;
 339     int_marker.controls.push_back(control);
 340     control.interaction_mode = InteractiveMarkerControl::MOVE_AXIS;
 341     int_marker.controls.push_back(control);
 342   }
 343 
 344   server->insert(int_marker);
 345   server->setCallback(int_marker.name, &processFeedback);
 346 }

The controls in this example are created by assigning random values to the quaternions which determine the orientation of each control. RViz will normalize these quaternions, so you don't have to worry about it when creating an interactive marker.

View-Facing 6-DOF

The structure of an <<MsgLink(visualization_msgs/InteractiveMarker)>> message

This interactive marker can move and rotate in all directions. In contrast to the previous examples, it does that using only two controls. The outer ring rotates along the view axis of the camera in RViz. The box moves in the camera plane, although it is not visually aligned with the camera coordinate frame.

https://code.ros.org/svn/ros-pkg/stacks/visualization_tutorials/trunk/interactive_marker_tutorials/src/basic_controls.cpp

 349 void makeViewFacingMarker( )
 350 {
 351   InteractiveMarker int_marker;
 352   int_marker.header.frame_id = "/base_link";
 353   int_marker.pose.position.y = -3.0 * marker_pos++;;
 354   int_marker.scale = 1;
 355 
 356   int_marker.name = "view_facing";
 357   int_marker.description = "View Facing 6-DOF";
 358 
 359   InteractiveMarkerControl control;
 360 
 361   // make a control that rotates around the view axis
 362   control.orientation_mode = InteractiveMarkerControl::VIEW_FACING;
 363   control.interaction_mode = InteractiveMarkerControl::ROTATE_AXIS;
 364   control.orientation.w = 1;
 365   control.name = "rotate";
 366 
 367   int_marker.controls.push_back(control);
 368 
 369   // create a box in the center which should not be view facing,
 370   // but move in the camera plane.
 371   control.orientation_mode = InteractiveMarkerControl::VIEW_FACING;
 372   control.interaction_mode = InteractiveMarkerControl::MOVE_PLANE;
 373   control.independent_marker_orientation = true;
 374   control.name = "move";
 375 
 376   control.markers.push_back( makeBox(int_marker) );
 377   control.always_visible = true;
 378 
 379   int_marker.controls.push_back(control);
 380 
 381   server->insert(int_marker);
 382   server->setCallback(int_marker.name, &processFeedback);
 383 }

Quadrocopter

The structure of an <<MsgLink(visualization_msgs/InteractiveMarker)>> message

This interactive marker has a constrained set of 4 degrees of freedom. It can rotate around the z axis and move in all 3 dimensions. It it realized using two controls: the green ring moves in the y-z plane and rotates around the z-axis, while the two additional arrows move along z.

Click and drag the green ring to see how the combined movement and rotation works: If the mouse cursor stays close to the ring, it will only rotate. Once you move it further away, it will start following the mouse.

https://code.ros.org/svn/ros-pkg/stacks/visualization_tutorials/trunk/interactive_marker_tutorials/src/basic_controls.cpp

 386 void makeQuadrocopterMarker( )
 387 {
 388   InteractiveMarker int_marker;
 389   int_marker.header.frame_id = "/base_link";
 390   int_marker.pose.position.y = -3.0 * marker_pos++;;
 391   int_marker.scale = 1;
 392 
 393   int_marker.name = "quadrocopter";
 394   int_marker.description = "Quadrocopter";
 395 
 396   makeBoxControl(int_marker);
 397 
 398   InteractiveMarkerControl control;
 399 
 400   control.orientation.w = 1;
 401   control.orientation.x = 0;
 402   control.orientation.y = 1;
 403   control.orientation.z = 0;
 404   control.interaction_mode = InteractiveMarkerControl::MOVE_ROTATE;
 405   int_marker.controls.push_back(control);
 406   control.interaction_mode = InteractiveMarkerControl::MOVE_AXIS;
 407   int_marker.controls.push_back(control);
 408 
 409   server->insert(int_marker);
 410   server->setCallback(int_marker.name, &processFeedback);
 411 }

The creation of the interactive marker is analogous to the previous examples, just that the interaction mode for one of the controls is set to MOVE_ROTATE.

Chess Piece

The structure of an <<MsgLink(visualization_msgs/InteractiveMarker)>> message

Click and drag the box or the surrounding Ring to move it in the x-y plane. Once you let go of the mouse button, it will snap to one of the grid fields. The way this works is that the basic_controls server running outside of RViz will set the pose of the Interactive Marker to a new value when it receives the pose from RViz. RViz will apply the update once you stop dragging it.

https://code.ros.org/svn/ros-pkg/stacks/visualization_tutorials/trunk/interactive_marker_tutorials/src/basic_controls.cpp

 413 void makeChessPieceMarker( )
 414 {
 415   InteractiveMarker int_marker;
 416   int_marker.header.frame_id = "/base_link";
 417   int_marker.pose.position.y = -3.0 * marker_pos++;;
 418   int_marker.scale = 1;
 419 
 420   int_marker.name = "chess_piece";
 421   int_marker.description = "Chess Piece\n(2D Move + Alignment)";
 422 
 423   InteractiveMarkerControl control;
 424 
 425   control.orientation.w = 1;
 426   control.orientation.x = 0;
 427   control.orientation.y = 1;
 428   control.orientation.z = 0;
 429   control.interaction_mode = InteractiveMarkerControl::MOVE_PLANE;
 430   int_marker.controls.push_back(control);
 431 
 432   // make a box which also moves in the plane
 433   control.markers.push_back( makeBox(int_marker) );
 434   control.always_visible = true;
 435   int_marker.controls.push_back(control);
 436 
 437   // we want to use our special callback function
 438   server->insert(int_marker);
 439   server->setCallback(int_marker.name, &processFeedback);
 440 
 441   // set different callback for POSE_UPDATE feedback
 442   server->setCallback(int_marker.name, &alignMarker, visualization_msgs::InteractiveMarkerFeedback::POSE_UPDATE );
 443 }

The major difference to the previous example is that an additional feedback function is specified, which will be called instead of processFeedback() when the pose of the marker gets updated. This function modifies the pose of the marker and sends it back to RViz:

https://code.ros.org/svn/ros-pkg/stacks/visualization_tutorials/trunk/interactive_marker_tutorials/src/basic_controls.cpp

 224 void alignMarker( const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback )
 225 {
 226   geometry_msgs::Pose pose = feedback->pose;
 227 
 228   pose.position.x = round(pose.position.x-0.5)+0.5;
 229   pose.position.y = round(pose.position.y-0.5)+0.5;
 230 
 231   ROS_INFO_STREAM( feedback->marker_name << ":"
 232       << " aligning position = "
 233       << feedback->pose.position.x
 234       << ", " << feedback->pose.position.y
 235       << ", " << feedback->pose.position.z
 236       << " to "
 237       << pose.position.x
 238       << ", " << pose.position.y
 239       << ", " << pose.position.z );
 240 
 241   server->setPose( feedback->marker_name, pose );
 242   server->applyChanges();
 243 }

Pan / Tilt

The structure of an <<MsgLink(visualization_msgs/InteractiveMarker)>> message

This example shows that you can combine frame aligned and fixed-orientation controls in one Interactive Marker. The Pan control will always stay in place, while the tilt control will rotate.

https://code.ros.org/svn/ros-pkg/stacks/visualization_tutorials/trunk/interactive_marker_tutorials/src/basic_controls.cpp

 445 void makePanTiltMarker( )
 446 {
 447   InteractiveMarker int_marker;
 448   int_marker.header.frame_id = "/base_link";
 449   int_marker.pose.position.y = -3.0 * marker_pos++;;
 450   int_marker.scale = 1;
 451 
 452   int_marker.name = "pan_tilt";
 453   int_marker.description = "Pan / Tilt";
 454 
 455   makeBoxControl(int_marker);
 456 
 457   InteractiveMarkerControl control;
 458 
 459   control.orientation.w = 1;
 460   control.orientation.x = 0;
 461   control.orientation.y = 1;
 462   control.orientation.z = 0;
 463   control.interaction_mode = InteractiveMarkerControl::ROTATE_AXIS;
 464   control.orientation_mode = InteractiveMarkerControl::FIXED;
 465   int_marker.controls.push_back(control);
 466 
 467   control.orientation.w = 1;
 468   control.orientation.x = 0;
 469   control.orientation.y = 0;
 470   control.orientation.z = 1;
 471   control.interaction_mode = InteractiveMarkerControl::ROTATE_AXIS;
 472   control.orientation_mode = InteractiveMarkerControl::INHERIT;
 473   int_marker.controls.push_back(control);
 474 
 475   server->insert(int_marker);
 476   server->setCallback(int_marker.name, &processFeedback);
 477 }

Context Menu

This example shows how to attach a simple-static menu to an interactive marker. If you do not specify a custom marker for visualization (as in the case of the grey box), RViz will create a text marker floating above the Interactive Marker, which will enables you to open the context menu.

https://code.ros.org/svn/ros-pkg/stacks/visualization_tutorials/trunk/interactive_marker_tutorials/src/basic_controls.cpp

 479 void makeMenuMarker()
 480 {
 481   InteractiveMarker int_marker;
 482   int_marker.header.frame_id = "/base_link";
 483   int_marker.pose.position.y = -3.0 * marker_pos++;;
 484   int_marker.scale = 1;
 485 
 486   int_marker.name = "context_menu";
 487   int_marker.description = "Context Menu\n(Right Click)";
 488 
 489   InteractiveMarkerControl control;
 490 
 491   control.interaction_mode = InteractiveMarkerControl::MENU;
 492   control.description="Options";
 493   control.name = "menu_only_control";
 494 
 495   Marker marker = makeBox( int_marker );
 496   control.markers.push_back( marker );
 497   control.always_visible = true;
 498   int_marker.controls.push_back(control);
 499 
 500   server->insert(int_marker);
 501   server->setCallback(int_marker.name, &processFeedback);
 502   menu_handler.apply( *server, int_marker.name );
 503 }

Marker attached to a moving frame

This example shows what happens if you click on a marker that is attached to a frame which moves relative to the fixed frame specified in RViz. Click on the box to move and on the ring to rotate. As the containing frame moves, the marker will continue moving relative to your mouse even if you are holding it.

https://code.ros.org/svn/ros-pkg/stacks/visualization_tutorials/trunk/interactive_marker_tutorials/src/basic_controls.cpp

 505 void makeMovingMarker()
 506 {
 507   InteractiveMarker int_marker;
 508   int_marker.header.frame_id = "/moving_frame";
 509   int_marker.pose.position.y = -3.0 * marker_pos++;;
 510   int_marker.scale = 1;
 511 
 512   int_marker.name = "moving";
 513   int_marker.description = "Marker Attached to a\nMoving Frame";
 514 
 515   InteractiveMarkerControl control;
 516 
 517   control.orientation.w = 1;
 518   control.orientation.x = 1;
 519   control.orientation.y = 0;
 520   control.orientation.z = 0;
 521   control.interaction_mode = InteractiveMarkerControl::ROTATE_AXIS;
 522   int_marker.controls.push_back(control);
 523 
 524   control.interaction_mode = InteractiveMarkerControl::MOVE_PLANE;
 525   control.always_visible = true;
 526   control.markers.push_back( makeBox(int_marker) );
 527   int_marker.controls.push_back(control);
 528 
 529   server->insert(int_marker);
 530   server->setCallback(int_marker.name, &processFeedback);
 531 }

The surrounding code

To setup the server node, all that is needed is to create an instance of InteractiveMarkerServer and pass all InteractiveMarker messages to that object.

Note that you have to call applyChanges() after you have added, updated or removed interactive markers, their pose, menus or feedback functions. This will cause the InteractiveMarkerServer to apply all scheduled changes to its internal state and send an update message to all connected clients. This is done to make it possible to maintain a coherent state and minimize data traffic between the server and its clients.

https://code.ros.org/svn/ros-pkg/stacks/visualization_tutorials/trunk/interactive_marker_tutorials/src/basic_controls.cpp

  44 boost::shared_ptr<interactive_markers::InteractiveMarkerServer> server;
  45 float marker_pos = 0;
  46 interactive_markers::MenuHandler menu_handler;

https://code.ros.org/svn/ros-pkg/stacks/visualization_tutorials/trunk/interactive_marker_tutorials/src/basic_controls.cpp

 533 int main(int argc, char** argv)
 534 {
 535   ros::init(argc, argv, "basic_controls");
 536   ros::NodeHandle n;
 537 
 538   // create a timer to update the published transforms
 539   ros::Timer frame_timer = n.createTimer(ros::Duration(0.01), frameCallback);
 540 
 541   server.reset( new interactive_markers::InteractiveMarkerServer("basic_controls","",false) );
 542 
 543   ros::Duration(0.1).sleep();
 544 
 545   menu_handler.insert( "First Entry", &processFeedback );
 546   menu_handler.insert( "Second Entry", &processFeedback );
 547   interactive_markers::MenuHandler::EntryHandle sub_menu_handle = menu_handler.insert( "Submenu" );
 548   menu_handler.insert( sub_menu_handle, "First Entry", &processFeedback );
 549   menu_handler.insert( sub_menu_handle, "Second Entry", &processFeedback );
 550 
 551   make6DofMarker( false );
 552   make6DofMarker( true );
 553   makeRandomDofMarker( );
 554   makeViewFacingMarker( );
 555   makeQuadrocopterMarker( );
 556   makeChessPieceMarker( );
 557   makePanTiltMarker( );
 558   makeMenuMarker( );
 559   makeMovingMarker( );
 560 
 561   server->applyChanges();
 562 
 563   ros::spin();
 564 
 565   server.reset();
 566 }

A timer is set up to update the tf transformation between base_link and moving_frame, which is done in frameCallback():

https://code.ros.org/svn/ros-pkg/stacks/visualization_tutorials/trunk/interactive_marker_tutorials/src/basic_controls.cpp

  75 void frameCallback(const ros::TimerEvent&)
  76 {
  77   static uint32_t counter = 0;
  78   static bool make = true;
  79 
  80   static tf::TransformBroadcaster br;
  81 
  82   tf::Transform t;
  83 
  84   ros::Time time = ros::Time::now();
  85 
  86   t.setOrigin(tf::Vector3(0.0, 0.0, sin(float(counter)/140.0) * 2.0));
  87   t.setRotation(tf::Quaternion(0.0, 0.0, 0.0, 1.0));
  88   br.sendTransform(tf::StampedTransform(t, time, "base_link", "moving_frame"));
  89 
  90   t.setOrigin(tf::Vector3(0.0, 0.0, 0.0));
  91   t.setRotation(tf::createQuaternionFromRPY(0.0, float(counter)/140.0, 0.0));
  92   br.sendTransform(tf::StampedTransform(t, time, "base_link", "rotating_frame"));
  93 
  94   ++counter;
  95   if( (counter % 400) == 0 )
  96   {
  97     if( make )
  98     {
  99       InteractiveMarker int_marker;
 100       int_marker.header.frame_id = "/base_link";
 101       int_marker.pose.position.x = 5;
 102       int_marker.scale = 1;
 103 
 104       int_marker.name = "blinky";
 105       int_marker.description = "blinking 6-DOF Control";
 106 
 107       {
 108         InteractiveMarkerControl control;
 109 
 110         control.interaction_mode = InteractiveMarkerControl::MENU;
 111         control.description="Blinky Options";
 112         control.name = "menu_only_control";
 113         control.always_visible = true;
 114 
 115         Marker marker = makeBox( int_marker );
 116         control.markers.push_back( marker );
 117 
 118         int_marker.controls.push_back(control);
 119       }
 120 
 121       InteractiveMarkerControl control;
 122 
 123       control.orientation.w = 1;
 124       control.orientation.x = 1;
 125       control.orientation.y = 0;
 126       control.orientation.z = 0;
 127       control.name = "rotate_x";
 128       control.interaction_mode = InteractiveMarkerControl::ROTATE_AXIS;
 129       int_marker.controls.push_back(control);
 130       control.name = "move_x";
 131       control.interaction_mode = InteractiveMarkerControl::MOVE_AXIS;
 132       int_marker.controls.push_back(control);
 133 
 134       control.orientation.w = 1;
 135       control.orientation.x = 0;
 136       control.orientation.y = 1;
 137       control.orientation.z = 0;
 138       control.name = "rotate_z";
 139       control.interaction_mode = InteractiveMarkerControl::ROTATE_AXIS;
 140       int_marker.controls.push_back(control);
 141       control.name = "move_z";
 142       control.interaction_mode = InteractiveMarkerControl::MOVE_AXIS;
 143       int_marker.controls.push_back(control);
 144 
 145       control.orientation.w = 1;
 146       control.orientation.x = 0;
 147       control.orientation.y = 0;
 148       control.orientation.z = 1;
 149       control.name = "rotate_y";
 150       control.interaction_mode = InteractiveMarkerControl::ROTATE_AXIS;
 151       int_marker.controls.push_back(control);
 152       control.name = "move_y";
 153       control.interaction_mode = InteractiveMarkerControl::MOVE_AXIS;
 154       int_marker.controls.push_back(control);
 155 
 156       server->insert(int_marker);
 157       menu_handler.apply( *server, int_marker.name );
 158 
 159       server->applyChanges();
 160       make = false;
 161     }
 162     else
 163     {
 164       server->erase( "blinky" );
 165       server->applyChanges();
 166       make = true;
 167     }
 168   }
 169 }

Finally, processFeedback() is used to print output to rosconsole when feedback arrives:

https://code.ros.org/svn/ros-pkg/stacks/visualization_tutorials/trunk/interactive_marker_tutorials/src/basic_controls.cpp

 171 void processFeedback( const visualization_msgs::InteractiveMarkerFeedbackConstPtr &feedback )
 172 {
 173   std::ostringstream s;
 174   s << "Feedback from marker '" << feedback->marker_name << "' "
 175       << " / control '" << feedback->control_name << "'";
 176 
 177   std::ostringstream mouse_point_ss;
 178   if( feedback->mouse_point_valid )
 179   {
 180     mouse_point_ss << " at " << feedback->mouse_point.x
 181                    << ", " << feedback->mouse_point.y
 182                    << ", " << feedback->mouse_point.z
 183                    << " in frame " << feedback->header.frame_id;
 184   }
 185 
 186   switch ( feedback->event_type )
 187   {
 188     case visualization_msgs::InteractiveMarkerFeedback::BUTTON_CLICK:
 189       ROS_INFO_STREAM( s.str() << ": button click" << mouse_point_ss.str() << "." );
 190       break;
 191 
 192     case visualization_msgs::InteractiveMarkerFeedback::MENU_SELECT:
 193       ROS_INFO_STREAM( s.str() << ": menu item " << feedback->menu_entry_id << " clicked" << mouse_point_ss.str() << "." );
 194       break;
 195 
 196     case visualization_msgs::InteractiveMarkerFeedback::POSE_UPDATE:
 197       ROS_INFO_STREAM( s.str() << ": pose changed"
 198           << "\nposition = "
 199           << feedback->pose.position.x
 200           << ", " << feedback->pose.position.y
 201           << ", " << feedback->pose.position.z
 202           << "\norientation = "
 203           << feedback->pose.orientation.w
 204           << ", " << feedback->pose.orientation.x
 205           << ", " << feedback->pose.orientation.y
 206           << ", " << feedback->pose.orientation.z
 207           << "\nframe: " << feedback->header.frame_id
 208           << " time: " << feedback->header.stamp.sec << "sec, "
 209           << feedback->header.stamp.nsec << " nsec" );
 210       break;
 211 
 212     case visualization_msgs::InteractiveMarkerFeedback::MOUSE_DOWN:
 213       ROS_INFO_STREAM( s.str() << ": mouse down" << mouse_point_ss.str() << "." );
 214       break;
 215 
 216     case visualization_msgs::InteractiveMarkerFeedback::MOUSE_UP:
 217       ROS_INFO_STREAM( s.str() << ": mouse up" << mouse_point_ss.str() << "." );
 218       break;
 219   }
 220 
 221   server->applyChanges();
 222 }

Wiki: rviz/Tutorials/Interactive Markers: Basic Controls (last edited 2012-01-09 18:53:14 by AdvaitJain)