class mola::MolaViz

Overview

MOLA GUI and visualization API - nanogui backend.

Implements VizInterface using nanogui / CDisplayWindowGUI. For the Dear ImGui backend see MolaVizImGui.

#include <MolaViz.h>

class MolaViz:
    public mola::ExecutableBase,
    public mola::VizInterface
{
public:
    // typedefs

    typedef std::string window_name_t;
    typedef std::string subwindow_name_t;
    typedef std::function<void(const mrpt::rtti::CObject::Ptr&, nanogui::Window*subWin, const window_name_t&parentWin, MolaViz*instance, const mrpt::containers::yaml*extra_parameters)> update_handler_t;
    typedef std::string class_name_t;

    // structs

    struct DataPerDatasetUI;
    struct DecayingCloud;
    struct PerWindowData;

    // fields

    static const window_name_t DEFAULT_WINDOW_NAME = "main";
    static const std::string BACKEND_NANOGUI = "nanogui";
    static const std::string BACKEND_IMGUI = "imgui";
    double console_text_font_size_ = 9.0;
    unsigned int max_console_lines_ = 5;
    bool show_rgbd_as_point_cloud_ = false;
    double assumed_sensor_rate_hz_ = 10.0;

    // construction

    MolaViz();
    MolaViz(const MolaViz&);
    MolaViz(MolaViz&&);

    // methods

    static bool IsRunning();
    static MolaViz* Instance();

    static void register_gui_handler(
        const class_name_t& name,
        const update_handler_t& handler
        );

    virtual const std::string& gui_backend() const;
    virtual std::future<void> create_subwindow_from_description(const mola::gui::WindowDescription& desc, const std::string& parentWindow = DEFAULT_WINDOW_NAME);
    virtual std::future<void> enqueue_custom_gui_code(const std::function<void()>& userCode);

    virtual void* get_subwindow_handle(
        const std::string& subWindowTitle,
        const std::string& parentWindow = DEFAULT_WINDOW_NAME
        );

    virtual std::future<std::optional<std::string>> open_file_dialog(
        const std::string& title,
        bool save,
        const std::vector<std::pair<std::string, std::string>>& filters = {},
        const std::string& default_path = "",
        const std::string& parentWindow = DEFAULT_WINDOW_NAME
        );

    virtual std::future<void> set_menu_bar(const mola::gui::MenuBar& bar, const std::string& parentWindow = DEFAULT_WINDOW_NAME);
    virtual MetricChannel::Ptr register_metric(const std::string& name, const std::string& unit = "");
    virtual void push_metric(const std::string& name, double t, double value);

    virtual std::future<bool> update_3d_object(
        const std::string& objName,
        const std::shared_ptr<mrpt::opengl::CSetOfObjects>& obj,
        const std::string& viewportName = "main",
        const std::string& parentWindow = DEFAULT_WINDOW_NAME,
        const std::string& parentFrame = ""
        );

    virtual std::future<bool> update_3d_object_frame(
        const std::string& frameName,
        const mrpt::math::TPose3D& pose,
        const std::string& viewportName = "main",
        const std::string& parentWindow = DEFAULT_WINDOW_NAME
        );

    virtual std::future<bool> insert_point_cloud_with_decay(
        const std::shared_ptr<mrpt::opengl::CPointCloudColoured>& cloud,
        double decay_time_seconds,
        const std::string& viewportName = "main",
        const std::string& parentWindow = DEFAULT_WINDOW_NAME,
        const std::string& parentFrame = ""
        );

    virtual std::future<bool> clear_all_point_clouds_with_decay(
        const std::string& viewportName = "main",
        const std::string& parentWindow = DEFAULT_WINDOW_NAME
        );

    virtual std::future<bool> update_viewport_look_at(
        const mrpt::math::TPoint3Df& lookAt,
        const std::string& viewportName = "main",
        const std::string& parentWindow = DEFAULT_WINDOW_NAME,
        const std::string& parentFrame = ""
        );

    virtual std::future<bool> update_viewport_camera_azimuth(
        double azimuth,
        bool absolute_falseForRelative = true,
        const std::string& viewportName = "main",
        const std::string& parentWindow = DEFAULT_WINDOW_NAME
        );

    virtual std::future<bool> update_viewport_camera_orthographic(
        bool orthographic,
        const std::string& viewportName = "main",
        const std::string& parentWindow = DEFAULT_WINDOW_NAME
        );

    virtual std::future<bool> execute_custom_code_on_background_scene(
        const std::function<void(mrpt::opengl::Scene&)>& userCode,
        const std::string& parentWindow = DEFAULT_WINDOW_NAME
        );

    virtual std::future<bool> subwindow_update_visualization(
        const mrpt::rtti::CObject::Ptr& obj,
        const std::string& subWindowTitle,
        const mrpt::containers::yaml* extra_parameters = nullptr,
        const std::string& parentWindow = DEFAULT_WINDOW_NAME
        );

    virtual std::future<bool> output_console_message(
        const std::string& msg,
        const std::string& parentWindow = DEFAULT_WINDOW_NAME
        );

    MolaViz& operator = (const MolaViz&);
    MolaViz& operator = (MolaViz&&);
    virtual void initialize(const Yaml& cfg);
    virtual void spinOnce();
    void markWindowForReLayout(const window_name_t& name);
};

Inherited Members

public:
    // typedefs

    typedef std::shared_ptr<VizInterface> Ptr;

    // structs

    struct DiagnosticsOutput;

    // methods

    virtual void initialize(const Yaml& cfg) = 0;
    virtual void spinOnce() = 0;
    ExecutableBase& operator = (const ExecutableBase&);
    ExecutableBase& operator = (ExecutableBase&&);

    virtual std::future<void> create_subwindow_from_description(
        const mola::gui::WindowDescription& desc,
        const std::string& parentWindow = "main"
        ) = 0;

    virtual std::future<void> enqueue_custom_gui_code(const std::function<void()>& userCode) = 0;
    virtual const std::string& gui_backend() const = 0;

    virtual std::future<void> set_menu_bar(
        const mola::gui::MenuBar& bar,
        const std::string& parentWindow = "main"
        ) = 0;

    virtual void* get_subwindow_handle(
        const std::string& subWindowTitle,
        const std::string& parentWindow = "main"
        ) = 0;

    virtual std::future<bool> update_3d_object(
        const std::string& objName,
        const std::shared_ptr<mrpt::opengl::CSetOfObjects>& obj,
        const std::string& viewportName = "main",
        const std::string& parentWindow = "main",
        const std::string& parentFrame = ""
        ) = 0;

    virtual std::future<bool> update_3d_object_frame(
        const std::string& frameName,
        const mrpt::math::TPose3D& pose,
        const std::string& viewportName = "main",
        const std::string& parentWindow = "main"
        ) = 0;

    virtual std::future<bool> insert_point_cloud_with_decay(
        const std::shared_ptr<mrpt::opengl::CPointCloudColoured>& cloud,
        double decay_time_seconds,
        const std::string& viewportName = "main",
        const std::string& parentWindow = "main",
        const std::string& parentFrame = ""
        ) = 0;

    virtual std::future<bool> clear_all_point_clouds_with_decay(
        const std::string& viewportName = "main",
        const std::string& parentWindow = "main"
        ) = 0;

    virtual std::future<bool> update_viewport_look_at(
        const mrpt::math::TPoint3Df& lookAt,
        const std::string& viewportName = "main",
        const std::string& parentWindow = "main",
        const std::string& parentFrame = ""
        ) = 0;

    virtual std::future<bool> update_viewport_camera_azimuth(
        double azimuth,
        bool absolute_falseForRelative = true,
        const std::string& viewportName = "main",
        const std::string& parentWindow = "main"
        ) = 0;

    virtual std::future<bool> update_viewport_camera_orthographic(
        bool orthographic,
        const std::string& viewportName = "main",
        const std::string& parentWindow = "main"
        ) = 0;

    virtual std::future<bool> execute_custom_code_on_background_scene(
        const std::function<void(mrpt::opengl::Scene&)>& userCode,
        const std::string& parentWindow = "main"
        ) = 0;

    virtual std::future<bool> subwindow_update_visualization(
        const mrpt::rtti::CObject::Ptr& obj,
        const std::string& subWindowTitle,
        const mrpt::containers::yaml* extra_parameters = nullptr,
        const std::string& parentWindow = "main"
        ) = 0;

    virtual std::future<bool> output_console_message(
        const std::string& msg,
        const std::string& parentWindow = "main"
        ) = 0;

    virtual std::future<std::optional<std::string>> open_file_dialog(
        const std::string& title,
        bool save,
        const std::vector<std::pair<std::string, std::string>>& filters = {},
        const std::string& default_path = "",
        const std::string& parentWindow = "main"
        ) = 0;

    virtual MetricChannel::Ptr register_metric(const std::string& name, const std::string& unit = "") = 0;
    virtual void push_metric(const std::string& name, double t, double value) = 0;
    VizInterface& operator = (const VizInterface&);
    VizInterface& operator = (VizInterface&&);

Fields

static const std::string BACKEND_NANOGUI = "nanogui"

Canonical backend name returned by MolaViz (nanogui).

static const std::string BACKEND_IMGUI = "imgui"

Canonical backend name returned by MolaVizImGui (Dear ImGui).

double assumed_sensor_rate_hz_ = 10.0

Assumed sensor rate [Hz] used to compute max number of decaying clouds from the decay_time_seconds parameter.

Methods

virtual const std::string& gui_backend() const

Returns “nanogui”.

See also:

VizInterface::BACKEND_NANOGUI

virtual std::future<void> create_subwindow_from_description(
    const mola::gui::WindowDescription& desc,
    const std::string& parentWindow = DEFAULT_WINDOW_NAME
    )

Creates a sub-window described by a GuiWidgetDescription.

The description carries the window title, initial position/size hints, tab structure, and all widget definitions including their initial values and on_change callbacks.

The returned future resolves once the window has been created in the GUI thread and all widgets are live. Callers that need to know when construction is complete should call .get() on the future.

Position and size in the description are treated as first-use hints :

  • nanogui backend : applied unconditionally via setPosition/setFixedWidth.

  • ImGui backend : passed as ImGuiCond_FirstUseEver, so the dock manager and imgui.ini take over from the second run.

Label text is updated at any time and from any thread by calling LiveString::set() on the LiveString instances embedded in the description. The backend polls them on each frame / spinOnce tick.

Parameters:

desc

Full window and widget description.

parentWindow

Name of the parent host window (default: “main”).

Returns:

future<void> that resolves when the window is live.

See also:

mola::gui::WindowDescription, mola::gui::LiveString

virtual std::future<void> enqueue_custom_gui_code(const std::function<void()>& userCode)

Enqueues a callable to run on the GUI thread at the next frame. The callable must not block. Replaces enqueue_custom_nanogui_code().

Core implementation: enqueue a callable to run on the GUI thread.

virtual void* get_subwindow_handle(
    const std::string& subWindowTitle,
    const std::string& parentWindow = DEFAULT_WINDOW_NAME
    )

Returns the underlying nanogui::Window* cast to void*, or nullptr if the sub-window does not exist yet. Cast only inside nanogui-aware .cpp files.

virtual std::future<std::optional<std::string>> open_file_dialog(
    const std::string& title,
    bool save,
    const std::vector<std::pair<std::string, std::string>>& filters = {},
    const std::string& default_path = "",
    const std::string& parentWindow = DEFAULT_WINDOW_NAME
    )

Opens a modal file-picker dialog on the GUI thread.

The call is non-blocking: it enqueues the dialog to open on the GUI thread and returns a future that resolves when the user dismisses it.

Parameters:

title

Dialog window title, e.g. “Open point cloud”.

save

true → “Save as” dialog (prompts before overwrite). false → “Open” dialog (validates file exists).

filters

List of {description, comma-separated-extensions} pairs. Example: {{“LAS files”,”las,laz”},{“All files”,”*”}} Pass an empty vector to show all files.

default_path

Initial directory or full path suggestion. Empty string means the backend’s default (usually the current working directory).

parentWindow

Host window name.

Returns:

future resolving to the chosen absolute path, or std::nullopt if the user cancelled.

virtual std::future<void> set_menu_bar(
    const mola::gui::MenuBar& bar,
    const std::string& parentWindow = DEFAULT_WINDOW_NAME
    )

Does nothing in nanogui backend.

virtual MetricChannel::Ptr register_metric(const std::string& name, const std::string& unit = "")

Metrics plotting is an ImGui-backend feature. Returns a no-op handle whose push() does nothing.

virtual void push_metric(const std::string& name, double t, double value)

Does nothing in nanogui backend.

virtual std::future<bool> update_3d_object(
    const std::string& objName,
    const std::shared_ptr<mrpt::opengl::CSetOfObjects>& obj,
    const std::string& viewportName = "main",
    const std::string& parentWindow = DEFAULT_WINDOW_NAME,
    const std::string& parentFrame = ""
    )

Updates or inserts a 3D object in the background scene.

The update is performed in the GUI thread. If the named object already exists, its contents are replaced by copying the shared pointers inside obj.

Parameters:

objName

Name used to identify the object (upsert key).

obj

Object to display.

viewportName

Viewport inside the parent window.

parentWindow

Host window name.

parentFrame

Optional name of a movable reference-frame node previously created via update_3d_object_frame(). When non-empty, the object is attached as a child of that frame (so moving the frame moves the object without re-rendering it); the frame node is auto-created at the identity pose if it does not exist yet. Empty (default) attaches to the viewport root, as before.

Returns:

future<bool>; resolves to true when executed.

virtual std::future<bool> update_3d_object_frame(
    const std::string& frameName,
    const mrpt::math::TPose3D& pose,
    const std::string& viewportName = "main",
    const std::string& parentWindow = DEFAULT_WINDOW_NAME
    )

Creates or repositions a named movable “reference frame” node.

A frame node is an (initially empty) container placed at the viewport root. Objects can be attached to it via the parentFrame argument of update_3d_object(); moving the frame then relocates all attached objects at once, without re-uploading their geometry. This is how a back end such as mola_mapper_3d keeps a front end’s dense clouds / local map (drawn once in its own {odom_i} frame) correctly placed in {map} as it estimates the T_map_to_odom_i transform online.

Idempotent: the first call creates the node; later calls only update its pose, preserving any already-attached children.

Parameters:

frameName

Name of the frame node (upsert key). Must be non-empty.

pose

Pose of the frame in the viewport (i.e. in {map}).

viewportName

Viewport inside the parent window.

parentWindow

Host window name.

Returns:

future<bool>; resolves to true when executed.

virtual std::future<bool> insert_point_cloud_with_decay(
    const std::shared_ptr<mrpt::opengl::CPointCloudColoured>& cloud,
    double decay_time_seconds,
    const std::string& viewportName = "main",
    const std::string& parentWindow = DEFAULT_WINDOW_NAME,
    const std::string& parentFrame = ""
    )

Inserts a temporary point cloud visible for decay_time_seconds.

Parameters:

cloud

Cloud to display.

decay_time_seconds

Lifetime in seconds before the cloud fades out.

viewportName

Target viewport.

parentWindow

Host window name.

parentFrame

If non-empty, the cloud is attached as a child of the named movable frame node (same semantics as the parentFrame argument of update_3d_object()).

Returns:

future<bool> resolving to true when executed.

virtual std::future<bool> clear_all_point_clouds_with_decay(
    const std::string& viewportName = "main",
    const std::string& parentWindow = DEFAULT_WINDOW_NAME
    )

Removes all clouds previously inserted with insert_point_cloud_with_decay().

virtual std::future<bool> update_viewport_look_at(
    const mrpt::math::TPoint3Df& lookAt,
    const std::string& viewportName = "main",
    const std::string& parentWindow = DEFAULT_WINDOW_NAME,
    const std::string& parentFrame = ""
    )

Moves the viewport camera look-at point.

Parameters:

lookAt

Target point in the local coordinate frame of parentFrame (if given) or in world/scene space.

parentFrame

If non-empty, the backend looks up the named movable frame node, applies its current scene pose to lookAt, and uses the resulting world-space point as the target. This makes the camera follow a vehicle rendered under a frame node rather than chasing its odom-frame coords.

virtual std::future<bool> update_viewport_camera_azimuth(
    double azimuth,
    bool absolute_falseForRelative = true,
    const std::string& viewportName = "main",
    const std::string& parentWindow = DEFAULT_WINDOW_NAME
    )

Rotates the viewport camera around the vertical axis.

Parameters:

azimuth

Angle in radians.

absolute_falseForRelative

true → set absolute azimuth; false → add increment to current value.

virtual std::future<bool> update_viewport_camera_orthographic(
    bool orthographic,
    const std::string& viewportName = "main",
    const std::string& parentWindow = DEFAULT_WINDOW_NAME
    )

Switches the viewport camera between perspective and orthographic.

virtual std::future<bool> execute_custom_code_on_background_scene(
    const std::function<void(mrpt::opengl::Scene&)>& userCode,
    const std::string& parentWindow = DEFAULT_WINDOW_NAME
    )

Executes arbitrary user code on the mrpt::opengl::Scene of the background viewport.

Use this to modify viewport properties, add sub-viewports, change background colour, etc. The callable runs in the GUI thread.

This method operates on the mrpt OpenGL scene, not on GUI toolkit widgets, so it is backend-agnostic: both nanogui and ImGui backends embed an mrpt scene in their OpenGL canvas.

virtual std::future<bool> subwindow_update_visualization(
    const mrpt::rtti::CObject::Ptr& obj,
    const std::string& subWindowTitle,
    const mrpt::containers::yaml* extra_parameters = nullptr,
    const std::string& parentWindow = DEFAULT_WINDOW_NAME
    )

Updates a sub-window’s content from an MRPT object.

The correct handler is selected based on the runtime type of obj. Custom handlers can be registered via MolaViz::register_gui_handler().

Returns:

future<bool> resolving to false if no handler exists for the object’s type.

virtual std::future<bool> output_console_message(
    const std::string& msg,
    const std::string& parentWindow = DEFAULT_WINDOW_NAME
    )

Appends a line of text to the on-screen console overlay.

virtual void initialize(const Yaml& cfg)

This must be implemented to read all the required parameters

This should be reimplemented to read all the required parameters

virtual void spinOnce()

Runs any required action on a timely manner

void markWindowForReLayout(const window_name_t& name)

Schedules a nanogui performLayout() for name at the next frame. Called from GUI-thread helpers that add or resize widgets.