ros-visualization / interactive_markers

Interactive marker library for RViz and similar visualizers.
27 stars 59 forks source link

Markers are not re-displayed in rviz when using multiple server names in the same node #96

Open heuristicus opened 2 years ago

heuristicus commented 2 years ago

When using multiple servers which have different names within the same node, disabling and re-enabling the visualisation of the markers in rviz does not work correctly.

The cause of this is likely the update_full topic being used to know when there are markers available. Because this is a latched topic generated by the server, it only retains the last published message on the topic. Each server with a different server_id publishes to the same topic, which means that it's only possible for the process function to get the init message for a single one of the servers.

https://github.com/ros-visualization/interactive_markers/blob/36740b17068a42f44dc564d29b6b25c21c3a01a0/src/single_client.cpp#L66

https://github.com/ros-visualization/interactive_markers/blob/36740b17068a42f44dc564d29b6b25c21c3a01a0/src/interactive_marker_client.cpp#L151-L166

Use the code below to reproduce.

First, start rviz and add an interactive marker visualiser on the topic /test/interactive. Then, run this node. You will see a couple of markers appear, like this:

Screenshot from 2022-07-20 12-07-32

The messages are as expected:

Screenshot from 2022-07-20 12-15-14

Then, uncheck the box to display the markers, and re-check it. You will now only be able to see the arrow marker, since that is the last one which was published on update_full. The status indicates that the circle client is still waiting for an initialisation message.

Screenshot from 2022-07-20 12-16-44

#!/usr/bin/env python
import rospy

from interactive_markers.interactive_marker_server import InteractiveMarkerServer
from visualization_msgs.msg import InteractiveMarker, InteractiveMarkerControl, Marker
from geometry_msgs.msg import Point, Vector3
from std_msgs.msg import ColorRGBA, Header

def generate_circle():
    int_marker = InteractiveMarker()
    int_marker.header.frame_id = "map"
    int_marker.scale = 1
    int_marker.name = "circle"
    int_marker.description = "Move and rotate circle"

    int_marker.pose.position = Point(x=1)

    plane_plus_rot = InteractiveMarkerControl()
    plane_plus_rot.name = "planar_plus_rotation"
    plane_plus_rot.orientation.w = 1
    plane_plus_rot.orientation.x = 0
    plane_plus_rot.orientation.y = 1
    plane_plus_rot.orientation.z = 0
    plane_plus_rot.interaction_mode = InteractiveMarkerControl.MOVE_ROTATE
    int_marker.controls.append(plane_plus_rot)

    z_adjustment = InteractiveMarkerControl()
    z_adjustment.name = "z_adjustment"
    z_adjustment.orientation.w = 1
    z_adjustment.orientation.x = 0
    z_adjustment.orientation.y = 1
    z_adjustment.orientation.z = 0
    z_adjustment.interaction_mode = InteractiveMarkerControl.MOVE_AXIS
    int_marker.controls.append(z_adjustment)

    return int_marker

def generate_arrow():
    int_marker = InteractiveMarker()
    int_marker.header.frame_id = "map"
    int_marker.scale = 1
    int_marker.name = "arrow"
    int_marker.description = "Arrow control"

    int_marker.pose.position.x = 0.5
    int_marker.pose.orientation.w = 1

    arrow_control = InteractiveMarkerControl()
    direction_marker = Marker(
        pose=int_marker.pose,
        id=-1,
        type=Marker.ARROW,
        scale=Vector3(0.2, 0.1, 0.1),
        color=ColorRGBA(r=1, b=1, a=1),
        header=Header(frame_id="map"),
        ns="edges/temp",
        action=Marker.ADD,
    )
    arrow_control.markers.append(direction_marker)
    arrow_control.always_visible = True
    arrow_control.interaction_mode = InteractiveMarkerControl.MENU
    arrow_control.name = "arrow_menu_control"
    int_marker.controls.append(arrow_control)

    return int_marker

if __name__ == "__main__":
    rospy.init_node("multiple_server_test")
    circle_marker_server = InteractiveMarkerServer(
        "/test/interactive", server_id="circle"
    )
    arrow_marker_server = InteractiveMarkerServer(
        "/test/interactive", server_id="arrow"
    )
    # Allow servers to initialise
    rospy.sleep(1)

    circle_marker_server.insert(generate_circle())
    circle_marker_server.applyChanges()

    arrow_marker_server.insert(generate_arrow())
    arrow_marker_server.applyChanges()

    rospy.spin()
Southyang commented 1 year ago

Hello, have you solved this problem?