[Documentation] [TitleIndex] [WordIndex

This page describes a high-level overview of the internal structure of rviz.

VisualizationManager

The VisualizationManager class is the top-level manager of almost everything in rviz. It manages the displays, tools, view controllers, handles render throttling, etc. It also owns and has accessors for any other manager you might want. A pointer to the VisualizationManager is available in some form in most places in rviz.

The VisualizationManager does not manage the GUI, or directly know anything about how the GUI is setup. Any communication between them is either done GUI -> VM, or through callbacks registered with the VM. (The list of the available signals is at the bottom of the VisualizationManager class declaration).

Displays

The Display concept is what most of rviz is built around. Displays take some input (topic, tf, etc.), and show it in the 3D view.

Displays are loaded through plugins which can be loaded/unloaded at runtime. Since the code segment for the display itself may be unloaded at runtime, they need to be manage by something else. Enter the DisplayWrapper class. The DisplayWrapper is responsible for creating the display when its plugin is available, and destroying it when the plugin is unloaded. It also ensures that the properties for that display are saved/loaded even if the plugin for it (and thus the code for the display itself) is not loaded.

Currently the only restriction on a Display is that it must do any ogre calls from within the main update thread, generally in the update() virtual function.

View Controllers

A View Controller is something that takes input (generally keyboard/mouse) and sets controls an ogre Camera. These were originally called camera controllers, but it was confusing for users who are not familiar with 3D graphics, since the robot also has cameras.

View controllers are not currently plugin-based, but it should be relatively trivial to make them be (in fact there are some comments to that effect in the source). The main reason they weren't was due to the initial plugin implementation being very Display-based, but that has since been fixed (see the plugin manager section for details).

Tools

A Tool is one of the buttons on the toolbar. For example, the "Move Camera" tool simply forwards the mouse events to the current View Controller, while the "Select" tool captures the input to do selection.

Tools are also not pluggable, for the same reason as view controllers, but they should be easy to make so.

Plugins

The plugin manager predates, and works similarly to, pluginlib with a few key differences. First, it provides the ability to load/unload individual plugins. Second, it access to the plugin description yaml file, and allows you to put custom information inside it. Third, it has signals that callbacks can be registered with to allow notification of plugin loading/unloading.

The actual handling of an individual plugin (.so/.dll) is handled by the Plugin class.

While plugin management originally only worked for Display types, as of version 1.2 this has been generalized to support any class type. See the PointCloudBase class in src/rviz/default_plugin for an example of using it.

Everything to do with plugin loading is in the src/rviz/plugin directory.

Properties

rviz has a property system that is a lot closer tied to wxWidgets than it should be, mainly because it evolved in a haphazard manner. Every PropertyManager is connected to a wxPropertyGrid.

A property in rviz is bound to a getter/setter function. Creating a property is done by type, using the PropertyManager::createProperty() method, e.g.:

   1 property_manager_->createProperty<TFFrameProperty>("Reference Frame", property_prefix_, boost::bind(&AxesDisplay::getFrame, this), boost::bind(&AxesDisplay::setFrame, this, _1), parent_category_, this);

When a property is created, a weak pointer to that property is returned. This is because deletion of a parent property will delete all child properties. Every access of a property must then be checked. If the properties weren't so directly tied to wxPropertyGrid, this wouldn't be necessary.

Because properties are weak pointers, there are a number of functions available to operate on them as weak pointers that do the lock()/null check for you. For example, whenever a property's value changes you must notify it of the change, and you can do so with the propertyChanged() method:

   1 template<class T>
   2 void propertyChanged(boost::weak_ptr<T>& wprop)
   3 {
   4   if (boost::shared_ptr<T> prop = wprop.lock())
   5   {
   6     prop->changed();
   7   }
   8 }

The property code is all in the src/rviz/properties directory.

Selection

Selection is done through the SelectionManager, and is done per-pixel by rendering everything in the scene to a texture, with a selection id as their color. The rgb value is then translated back into the selection id.

Every selectable object is associated with a SelectionHandler, which provides some information about the selected object(s), and allows you to do things pre- and post-selection rendering, as well as when an object is selected or deselected.

In general, selection in rviz never moved beyond the prototype stage. The actual selection of objects (picking) by color works (though it's not as efficient as it could be), but everything else needs redoing.

Future

Work has already begun on the underpinnings of rviz2, called RVE. The goal of RVE is to be a library for writing visualization tools, so rviz2 would end up just being a GUI written on top of that library.

A lot of the problems with rviz as it stands have potential solutions implemented in RVE. For example, rve_properties divorces the properties themselves from any save/load mechanism or GUI, and easily supports multiple save/load or GUI implementations. The render framework divorces "picking" (per object or part of object) from "selection", which may mean different things for different GUIs.

RVE's rendering framework also does not directly allow access to Ogre, and requires all rendering go through a specific path, which means that rendering changes/improvements can happen in a central location without breaking any plugins/etc.

GUI

The biggest mistake (IMHO) with rviz's GUI design is the displays property panel. While it can be convenient to have the properties in the same place as the list of displays, it's also very limiting -- selecting displays is impossible, as is multiple selection, or any kind of unified selection scheme. Something more like the traditional way of doing this kind of thing, with a tree of objects that when selected show their properties is likely a better option.


2022-05-28 13:01