The envire graph is the backbone of the whole library. It stores arbitrary data and time & space transformations between the data.

Structure

The graph itself is implemented as inheritance chain. Each class in the chain adds some of the functionality.

graphuml

envire::core::Graph<E,V> is the root class of the graph structure. It extends a boost::labeled_graph. The template parameters E and V are edge and vertex properties, i.e. they define the type of the data that can be stored in the edges and vertices of the graph. Edge properties need to implement the envire::core::EdgePropertyConcept while vertex properties need to implement envire::core::FramePropertyConcept.

The following features are provided by the Graph:

  • Frames (vertices) are indexed by a unique string-based frame id and can be retrieved in O(1).
  • A double-linked graph structure is enforced. I.e. if an edge is added, the inverse edge is calculated and added automatically. If an edge is updated, the inverse is updated as well.
  • Users are informed about changes in the graph structure via a publisher subscriber based event system.
  • TreeViews and Paths are provided to navigate the graph structure.

The TransformGraph<V> extends Graph<Transformation, V>. It adds functionality to calculate and set transformations between frames.

The EnvireGraph extends TransformGraph<Frame>. It adds functionality to add, remove and manipulate items.

Edge & Vertex Property Concepts

Edge and vertex properties need to follow special concepts to be compatible with the Graph. All edge properties need to implement envire::core::EdgePropertyConcept while all vertex properties have to implement envire::core::FramePropertyConcept.

Both concepts ensure, that the property is serializable using boost serialization (boost::SerializableConcept) and that a graphviz representation of the vertex/edge can be generated. The graphviz representation is used when visualizing the graph.

Furthermore edge properties need to implement an inverse() method, that inverts the meaning of the edge.

Vertex properties need to implement const FrameId& getId() and void setId(const FrameId&). Those methods are used to store a unique vertex identifier inside each vertex.

Frames

Frames are vertices in the structure of the EnvireGraph and implement the FramePropertyConcept. Additionally each Frame carries a set of items indexed by type.

Transformations

Transformations (envire::core::Transformation) are edges in the EnvireGraph. They implement the EdgePropertyConcept and describe the spatial and temporal displacement between frames.

Items

The data elements that are stored in the Frames of the graph are called Items. Every item must inherit from envire::core::ItemBase. getTypeInfo() and getEmbeddedTypeInfo() need to be overridden to provide correct type information about the item. getTypeInfo() should return the type_info of the item itself while getEmbeddedTypeInfo() should return the type of the encapsulated data (i.e. the type of the data that is returned in getRawData()).

A template (envire::core::Item<T>) that inherits from ItemBase and carries arbitrary data is provided for convenience. Thus manually inheriting from ItemBase should not be necessary. A minimal working example, that shows how to create new items can be found here

Tree Views

TreeViews are lightweight structures that view a portion of the graph as tree. Views are generated by bfs-visiting the graph starting at a given frame. All frames that are reachable from that frame will be part of the view. The structure does not contain any loops (it is a tree, not a graph). Edges that would create loops in the tree are called cross-edges and are stored in a special list inside the TreeView.

A TreeView can either be static or dynamic. A static view is a snapshot of the graph at the time it was taken. I.e. it will not update or change. If the graph changes, parts of the tree might become invalid.

A dynamic TreeView is updated automatically whenever the underlying graph changes. The view provides signals that will be emitted when that happens. Dynamic views significantly increase the computational cost of all manipulative graph operations. Especially the removal of edges might be costly.

A TreeView contains pointers to the actual data, thus if the underlying graph is destroyed, the view becomes invalid.