# Understanding InteractiveMarkers

I have followed the interactive markers tutorial, and I successfully achieved want I wanted: to mix the quadrocopter and button markers. However, I do not understand how the code works. To define the marker, I have the following code:

def makeMarker():
marker = Marker()
marker.type = Marker.CYLINDER
marker.scale.x =  0.3
marker.scale.y =  0.3
marker.scale.z =  0.3
marker.color.g = 1.0
marker.color.a = 1.0
return marker

# create an interactive marker for our server
int_marker = InteractiveMarker()
int_marker.name = "goal_marker"
int_marker.description = "goal_marker"
int_marker.scale = 0.7

# create marker and a non-interactive control containing the marker
control = InteractiveMarkerControl()
control.always_visible = True
control.markers.append(makeMarker())

# add control to interactive marker
int_marker.controls.append(control)

# add control for position (as it has no marker, RViz decides which one to use).
control = InteractiveMarkerControl()
control.orientation.w = 1
control.orientation.x = 0
control.orientation.y = 1
control.orientation.z = 0
control.interaction_mode = InteractiveMarkerControl.MOVE_PLANE
int_marker.controls.append(copy.deepcopy(control))

# add control for the height (as it has no marker, RViz decides which one to use).
control.interaction_mode = InteractiveMarkerControl.MOVE_AXIS
int_marker.controls.append(copy.deepcopy(control))

# add control for pose publishing.
control.interaction_mode = InteractiveMarkerControl.BUTTON
control.markers.append(makeMarker())
int_marker.controls.append(control)


First, the interactive marker is created (int_marker), and then a Control is associated to maker created by makeMarker and this Control is inserted in int_marker. Then, two more controls are created to give the plannar movement and height, and inserted to int_marker. So far so good.

However, when adding the button functionality, I have to include the extra line control.markers.append(makeMarker()), that is, to create a new visual marker and append it to the Control. Why do I need this? I will not work otherwise.

FINAL SOLUTION: Removing extra appends and thus other extra code:

# create an interactive marker for our server
int_marker = InteractiveMarker()
int_marker.name = "int_marker"
int_marker.description = "int_marker"
int_marker.scale = 0.7

# add control for position (as it has no marker, RViz decides which one to use).
control = InteractiveMarkerControl()
control.orientation.w = 1
control.orientation.x = 0
control.orientation.y = 1
control.orientation.z = 0
control.interaction_mode = InteractiveMarkerControl.MOVE_PLANE
int_marker.controls.append(copy.deepcopy(control))

# add control for the height (as it has no marker, RViz decides which one to use).
control.interaction_mode = InteractiveMarkerControl.MOVE_AXIS
int_marker.controls.append(copy.deepcopy(control))

# add control for pose publishing. A marker is required in this case, RViz does not
# assign one.
control.interaction_mode = InteractiveMarkerControl.BUTTON
control.markers.append(makeMarker()) # This is required, it will not work otherwise.
int_marker.controls.append(control)

edit retag close merge delete

Sort by » oldest newest most voted

Just look at the make marker function, it gives you the visual form of the marker controlled by the interactive object: Cylinder, Box, Sphere ... and its size and color:

marker = Marker()
marker.type = Marker.CYLINDER
marker.scale.x =  0.3
marker.scale.y =  0.3
marker.scale.z =  0.3
marker.color.g = 1.0
marker.color.a = 1.0


UPDATE:

In my opinion I guess it probably should work without the first append, I do not see any reason why it should not do so, maybe the author added it twice by accident.

more

I understand that. My concern is about the second line from the last, why do I have to ad another marker to be able to click on it, and not just add the control as for the other two controls (move plane and move axis)?

( 2015-07-07 16:09:50 -0600 )edit

hmm, that's a good point have you tried to compile it without the first append? In my opinion I guess it probably should work, I do not see any reason why it should not ...

( 2015-07-07 17:50:10 -0600 )edit

Can you post this last comment as an answer so I can accept it? It solved (and simplified) my code :)

( 2015-07-08 02:34:16 -0600 )edit

The problem was not the last append, but the first. It solved some other problems I had by just using the last marker.

( 2015-07-08 05:18:52 -0600 )edit

Oh yes, I corrected it ;-)

( 2015-07-08 08:04:56 -0600 )edit

I believe (and if I'm wrong, I'd really appreciate being corrected!) it's because a button isn't associated with any default representation. That's not the case with MOVE_AXIS (represented by an arrow marker), ROTATE_AXIS (represented by a disc), etc.

I'm not sure I'm phrasing this right, but -- with no marker representation, there's no Ogre object (not for visualization, nor for locating in the virtual world, nor for locating on the projected ray under the mouse cursor, etc.).

This is borne out by looking at the autoComplete method in tools.cpp (that's a link to the source code; the method starts at line 101) in the interactive_markers package. You'll see the switch that fills in the default markers for all interaction_mode types except BUTTON (and the 3D types; not sure what happens with those) starting at line 114.

Don't ask me to trace how that ends up being called...it's complicated. I'm pretty sure I've done it before, don't really remember the data path anymore, and don't want to do it again unless I have to. :)

more

Thank you for this info. It was really helpful to understand. In fact, the problem was generated by having two markers. I have followed instructions in the other answer and it was solved :)

( 2015-07-08 02:33:51 -0600 )edit