Open3D icon indicating copy to clipboard operation
Open3D copied to clipboard

Scene disapears when clicked on

Open IArchi opened this issue 2 years ago • 2 comments

Checklist

Describe the issue

In the below code, when I click on the SceneWidget, it disapears.

To reproduce:

  1. python3 main.py
  2. Click on Start mapping
  3. Left-click on the scene (the control panel also disapear somewhere)
  4. Scene is gone ...

Steps to reproduce the bug

import open3d.visualization.gui as gui
import open3d.visualization.rendering as rendering

######################################
## Object to handle a single camera ##
######################################
class Zed:
    zed = None
    label = ''

class MultiCameraWindow:
    MENU_SHOW_SETTINGS = 1
    MENU_QUIT = 3

    def __init__(self):
        self.window = gui.Application.instance.create_window("Zed Multi-cameras")
        w = self.window
        em = w.theme.font_size

        # Create the menu. The menu is global (because the macOS menu is global),
        # so only create it once.
        if gui.Application.instance.menubar is None:
            menubar = gui.Menu()
            menu_settings = gui.Menu()
            menu_settings.add_item("Toggle settings panel", MultiCameraWindow.MENU_SHOW_SETTINGS)
            menu_settings.set_checked(MultiCameraWindow.MENU_SHOW_SETTINGS, True)
            menu_settings.add_separator()
            menu_settings.add_item("Quit", MultiCameraWindow.MENU_QUIT)
            menubar.add_menu("File", menu_settings)
            gui.Application.instance.menubar = menubar

        # Each window needs to know what to do with the menu items, so we need
        # to tell the window how to handle menu items.
        w.set_on_menu_item_activated(MultiCameraWindow.MENU_SHOW_SETTINGS, self._on_menu_toggle)
        w.set_on_menu_item_activated(MultiCameraWindow.MENU_QUIT, self._on_menu_quit)

        #######################
        ##     Display      ##
        #######################
        self._mainlayout = gui.Vert()

        # 3D scene
        self._scene = gui.SceneWidget()
        self._scene.scene = rendering.Open3DScene(w.renderer)
        self._scene.scene.set_background([255, 255, 0, 255])
        self._scene.scene.show_skybox(True)
        self._scene.scene.show_axes(True)
        self._scene.visible = False
        self._scene.set_view_controls(gui.SceneWidget.Controls.ROTATE_CAMERA)
        self._mainlayout.add_child(self._scene)

        # Camera preview (during calibration)
        self._camerasgrid = gui.VGrid(2, 0.25 * em)
        self._camerasgrid.enabled = False
        self._camera_previews = []
        for i in range(4):
            self._camera_previews.append(gui.WidgetProxy())
            self._camera_previews[i].set_widget(gui.ImageWidget("./sample.jpg"))
            self._camerasgrid.add_child(self._camera_previews[i])
        self._mainlayout.add_child(self._camerasgrid)

        #######################
        ##   Control panel   ##
        #######################
        self._controlpanel = gui.Vert(0, gui.Margins(0.5 * em, 0.5 * em, 0.5 * em, 0.5 * em))

        #######################
        ##      Cameras      ##
        #######################
        cameras_collapse = gui.CollapsableVert("Cameras", 0.33 * em, gui.Margins(em, 0, 0, 0))
        cameras_collapse.set_is_open(True)

        # Add a list of cameras
        self._cameras_list = gui.ListView()
        self._cameras_list.set_items([])
        self._cameras_list.set_max_visible_items(4)
        cameras_collapse.add_child(self._cameras_list)

        # Add button
        cameras_refresh = gui.Button('Refresh')
        cameras_refresh.set_on_clicked(self._on_cameras_reset)
        cameras_collapse.add_child(cameras_refresh)

        # Attach to control panel
        self._controlpanel.add_child(cameras_collapse)

        #######################
        ##   View control    ##
        #######################
        view_collapse = gui.CollapsableVert("Scene", 0.33 * em, gui.Margins(em, 0, 0, 0))
        view_collapse.set_is_open(False)

        # View controls
        view_controls = gui.Horiz(spacing=5)
        view_controls.add_child(gui.Label('View controls '))
        view_controls_list = gui.Combobox()
        view_controls_list.add_item("Fly")
        view_controls_list.add_item("Follow camera")
        view_controls_list.selected_index = view_controls_list.selected_index + 2
        view_controls_list.set_on_selection_changed(self._on_viewcontrol_change)
        view_controls.add_child(view_controls_list)
        view_collapse.add_child(view_controls)

        # Attach to control panel
        self._controlpanel.add_child(view_collapse)

        #######################
        ##    Calibration    ##
        #######################
        calibration_collapse = gui.CollapsableVert("Calibration", 0.33 * em, gui.Margins(em, 0, 0, 0))
        calibration_collapse.set_is_open(False)

        # Add toggle
        calibration_toggle = gui.Checkbox("Enable calibration")
        calibration_toggle.set_on_checked(self._on_toggle_calibration)
        calibration_collapse.add_child(calibration_toggle)

        # Add button
        calibration_reset = gui.Button('Calibrate with ArUco')
        calibration_reset.set_on_clicked(self._on_reset_calibration)
        calibration_collapse.add_child(calibration_reset)

        # Attach to control panel
        self._controlpanel.add_child(calibration_collapse)

        #######################
        ##    Zed settings   ##
        #######################
        settings_collapse = gui.CollapsableVert("Settings", 0.33 * em, gui.Margins(em, 0, 0, 0))
        settings_collapse.set_is_open(False)

        # Add resolution and FPS
        settings_resolution = gui.Horiz(spacing=5)
        settings_resolution.add_child(gui.Label('Resolution '))
        settings_resolution_list = gui.Combobox()
        settings_resolution_list.add_item("VGA")
        settings_resolution_list.add_item("HD720")
        settings_resolution_list.add_item("HD1080")
        settings_resolution_list.add_item("HD2K")
        settings_resolution_list.selected_index = settings_resolution_list.selected_index + 3
        settings_resolution_list.set_on_selection_changed(self._on_resolution_change)
        settings_resolution.add_child(settings_resolution_list)
        settings_resolution.add_child(gui.Label('FPS '))
        settings_fps = gui.NumberEdit(gui.NumberEdit.INT)
        settings_fps.int_value = 30
        settings_fps.set_limits(1, 60)
        settings_resolution.add_child(settings_fps)
        settings_collapse.add_child(settings_resolution)

        # Add Depth mode
        settings_depthmode = gui.Horiz(spacing=5)
        settings_depthmode.add_child(gui.Label('Depth mode '))
        settings_depthmode_list = gui.Combobox()
        settings_depthmode_list.add_item("NEURAL")
        settings_depthmode_list.add_item("ULTRA")
        settings_depthmode_list.add_item("QUALITY")
        settings_depthmode_list.add_item("PERFORMANCE")
        settings_depthmode_list.add_item("NONE")
        settings_depthmode_list.selected_index = settings_depthmode_list.selected_index + 2
        settings_depthmode_list.set_on_selection_changed(self._on_depthmode_change)
        settings_depthmode.add_child(settings_depthmode_list)
        settings_collapse.add_child(settings_depthmode)

        # Add depth minimum distance
        settings_depthdistance = gui.Horiz(spacing=5)
        settings_depthdistance.add_child(gui.Label('Depth min. distance (mm) '))
        settings_depthdistance_mm = gui.NumberEdit(gui.NumberEdit.INT)
        settings_depthdistance_mm.int_value = 200
        settings_depthdistance_mm.set_limits(200, 700)
        settings_depthdistance.add_child(settings_depthdistance_mm)
        settings_collapse.add_child(settings_depthdistance)

        # Attach to control panel
        self._controlpanel.add_child(settings_collapse)

        #######################
        ##      Mapping      ##
        #######################
        mapping_collapse = gui.CollapsableVert("Mapping", 0.33 * em, gui.Margins(em, 0, 0, 0))
        mapping_collapse.set_is_open(False)

        # Point cloud or Mesh
        mapping_type = gui.Horiz(spacing=5)
        mapping_type.add_child(gui.Label('Type '))
        mapping_type_list = gui.Combobox()
        mapping_type_list.add_item("Point cloud (PLY)")
        mapping_type_list.add_item("Mesh (OBJ)")
        mapping_type_list.selected_index = mapping_type_list.selected_index + 2
        mapping_type_list.set_on_selection_changed(self._on_mappingrange_change)
        mapping_type.add_child(mapping_type_list)
        mapping_collapse.add_child(mapping_type)

        # Range
        mapping_range = gui.Horiz(spacing=5)
        mapping_range.add_child(gui.Label('Range '))
        mapping_range_list = gui.Combobox()
        mapping_range_list.add_item("AUTO")
        mapping_range_list.add_item("LONG")
        mapping_range_list.add_item("MEDIUM")
        mapping_range_list.add_item("SHORT")
        mapping_range_list.selected_index = mapping_range_list.selected_index + 2
        mapping_range_list.set_on_selection_changed(self._on_mappingrange_change)
        mapping_range.add_child(mapping_range_list)
        mapping_collapse.add_child(mapping_range)

        # Resolution
        mapping_resolution = gui.Horiz(spacing=5)
        mapping_resolution.add_child(gui.Label('Resolution '))
        mapping_resolution_list = gui.Combobox()
        mapping_resolution_list.add_item("HIGH")
        mapping_resolution_list.add_item("MEDIUM")
        mapping_resolution_list.add_item("LOW")
        mapping_resolution_list.selected_index = mapping_resolution_list.selected_index + 2
        mapping_resolution_list.set_on_selection_changed(self._on_mappingresolution_change)
        mapping_resolution.add_child(mapping_resolution_list)
        mapping_collapse.add_child(mapping_resolution)

        # Attach to control panel
        self._controlpanel.add_child(mapping_collapse)

        #######################
        ##       Save        ##
        #######################
        save_collapse = gui.CollapsableVert("Save", 0.33 * em, gui.Margins(em, 0, 0, 0.25 * em))
        save_collapse.set_is_open(False)

        # SVO
        self._save_toggle_svo = gui.ToggleSwitch("Save SVO")
        save_collapse.add_child(self._save_toggle_svo)

        # Area
        self._save_toggle_area = gui.ToggleSwitch("Save Area")
        save_collapse.add_child(self._save_toggle_area)

        # PLY or OBJ
        self._save_toggle_map = gui.ToggleSwitch("Save PLY or OBJ")
        save_collapse.add_child(self._save_toggle_map)

        # Attach to control panel
        self._controlpanel.add_child(save_collapse)

        #######################
        ##     Controls      ##
        #######################
        self._controls = gui.Horiz(0, gui.Margins(0.25 * em, 0.25 * em, 0.25 * em, 0.25 * em))
        self._controls.background_color = gui.Color(0.9, 0.9, 0.9)

        # Start / Stop
        self._controls_start = gui.Button("Start mapping")
        self._controls_start.set_on_clicked(self._on_start)
        self._controls.add_child(self._controls_start)

        self._controls.add_stretch()

        # Save
        self._controls_save = gui.Button("Save")
        self._controls_save.enabled = False
        self._controls_save.set_on_clicked(self._on_save)
        self._controls.add_child(self._controls_save)

        #######################
        ##      Global       ##
        #######################
        w.set_on_layout(self._on_layout)
        w.add_child(self._mainlayout)
        w.add_child(self._controls)
        w.add_child(self._controlpanel)

        #######################
        ##  Initialization   ##
        #######################
        self._cameras_list.set_items(list(map(lambda x:x.label, self._zed_load_cameras())))
        # TODO : Load configuration from file

    def _on_layout(self, layout_context):
        r = self.window.content_rect

        controlpanel_width = 21 * layout_context.theme.font_size
        controlpanel_height = min(r.height, self._controlpanel.calc_preferred_size(layout_context, gui.Widget.Constraints()).height)
        self._controlpanel.frame = gui.Rect(r.get_right() - controlpanel_width, r.y, controlpanel_width, controlpanel_height)

        controls_height = 2.8 * layout_context.theme.font_size
        self._controls.frame = gui.Rect(r.x, r.get_bottom() - controls_height, r.width, controls_height)

        self._mainlayout.frame = self._camerasgrid.frame = self._scene.frame = gui.Rect(r.x, r.y, r.width, r.height - controls_height)

    def _on_menu_toggle(self, force=None):
        self._controlpanel.visible = force if force is not None else not self._controlpanel.visible
        gui.Application.instance.menubar.set_checked(MultiCameraWindow.MENU_SHOW_SETTINGS, self._controlpanel.visible)

    def _on_menu_quit(self):
        gui.Application.instance.quit()

    def _on_viewcontrol_change(self, new_val, is_dbl_click):
        print(new_val)

    def _on_cameras_reset(self):
        self._cameras_list.set_items(list(map(lambda x:x.label, self._zed_load_cameras())))

    def _on_reset_calibration(self):
        self.show_message_dialog("There might be a problem...", "Reset")

    def _on_toggle_calibration(self, is_checked):
        if is_checked:
            text = "Sorry, effects are unimplemented"
        else:
            text = "Good choice"

        self.show_message_dialog("There might be a problem...", text)

    def _on_resolution_change(self, new_val, is_dbl_click):
        print(new_val)

    def _on_depthmode_change(self, new_val, is_dbl_click):
        print(new_val)

    def _on_mappingrange_change(self, new_val, is_dbl_click):
        print(new_val)

    def _on_mappingresolution_change(self, new_val, is_dbl_click):
        print(new_val)

    def _on_start(self):
        if self._scene.visible == False:
            self._camerasgrid.visible = False
            self._scene.visible = True
            self._on_menu_toggle(False)
            self._controls_start.text = "Pause mapping"
            self._zed_start_mapping()
        else:
            self._camerasgrid.visible = True
            self._scene.visible = False
            self._controls_start.text = "Start mapping"
            self._controls_save.enabled = True
            self._zed_stop_mapping()

    def _on_save(self):
        self._zed_save()

    def _on_exit(self):
        gui.Application.instance.quit()

    # This function is essentially the same as window.show_message_box(),
    # so for something this simple just use that, but it illustrates making a
    # dialog.
    def show_message_dialog(self, title, message):
        # A Dialog is just a widget, so you make its child a layout just like
        # a Window.
        dlg = gui.Dialog(title)

        # Add the message text
        em = self.window.theme.font_size
        dlg_layout = gui.Vert(em, gui.Margins(em, em, em, em))
        dlg_layout.add_child(gui.Label(message))

        # Add the Ok button. We need to define a callback function to handle
        # the click.
        ok_button = gui.Button("Ok")
        ok_button.set_on_clicked(self._on_dialog_ok)

        # We want the Ok button to be an the right side, so we need to add
        # a stretch item to the layout, otherwise the button will be the size
        # of the entire row. A stretch item takes up as much space as it can,
        # which forces the button to be its minimum size.
        button_layout = gui.Horiz()
        button_layout.add_stretch()
        button_layout.add_child(ok_button)

        # Add the button layout,
        dlg_layout.add_child(button_layout)
        # ... then add the layout as the child of the Dialog
        dlg.add_child(dlg_layout)
        # ... and now we can show the dialog
        self.window.show_dialog(dlg)

    def _on_dialog_ok(self):
        self.window.close_dialog()

    def _zed_load_cameras(self):
        z1 = Zed()
        z1.label = "ZED2i_0000000"
        z2 = Zed()
        z2.label = "ZED2i_0000001"
        z3 = Zed()
        z3.label = "ZED2i_0000002"
        z4 = Zed()
        z4.label = "ZED2i_0000003"
        self._zeds = [z1, z2, z3, z4]
        return self._zeds

    def _zed_start_mapping(self):
        print('Start mapping')

    def _zed_stop_mapping(self):
        print('Stop mapping')

    def _zed_save(self):
        print('Save')
        if self._save_toggle_svo.is_on:
            print('Save SVO')
        if self._save_toggle_area.is_on:
            print('Save Area')
        if self._save_toggle_map.is_on:
            print('Save Map')

def main():
    gui.Application.instance.initialize()
    w = MultiCameraWindow()
    gui.Application.instance.run()

if __name__ == "__main__":
    main()

Error message

No message

Expected behavior

The scene should be displayed.

Open3D, Python and System information

- Operating system: Jetson Xavier NX JP 4.6.1
- Python version: Python 3.7
- Open3D version: output from python: 0.15.2
- System architecture: Jetson
- Is this a remote workstation?: yes or no
- How did you install Open3D?: build from source
- Compiler version (if built from source): gcc 7.5.0

Additional information

No response

IArchi avatar Jul 21 '22 14:07 IArchi

I had this issue and it got solved when I assigned the SceneWidget as a direct child of the window and not as a child of a layout.

natecdr avatar Jul 29 '22 15:07 natecdr

Seems weird but it solved my issue.

IArchi avatar Aug 05 '22 09:08 IArchi

For maintainers, the above issue can be easily reproduced using code from PR itself - https://github.com/isl-org/Open3D/pull/3212

saurabheights avatar Mar 28 '23 17:03 saurabheights