Graph
Graph is the main data structure the backend uses to contain any and all information about the map the
user made. For the most part, it contains a list of type Vertex and a list of type Edge, along with a
ton of functions for optimization, converting to a SparseOptimizer, and some utility functions to aid
certain metrics.
Vertex
Vertex is a very basic wrapper class to represent a single vertex of a Graph. It has four attributes:
- mode: the type of Vertex this is, represented as a VertexType enum. Either:
- Odometry: representing a phone position
- Tag: representing the center of a tag
- Tag Point: representing the corner of a tag (for SBA)
- Dummy: representing a dummy node (see the As Graph section)
- Waypoint: representing a user-saved location
-
estimate: a 7x1 ndarray, the estimated pose of this vertex with respect to the origin of Invisible
Map Creator’s AR Session. This will update as the optimization runs, and as such can represent
either the optimized or unoptimized estimate.
- fixed: a boolean, whether the estimate of this Vertex is allowed to be changed during optimization
- meta_data: a dict containing any other data this Vertex needs. Will contain
- For Tags and Tag Points, the id of the tag
- For Waypoints, the name of the saved location
In Graph, the vertices are stored in a dict of int to Vertex. Each key is a uid for the Vertex. While
typically assigned in order (i.e. the dict is essentially a list), this is not necessarily the case, so
make sure to watch out for this! Also note that these need to be converted to G2O’s own Vertex type
before optimization; typically a VertexSE3Expmap 1.
Edge
Edge is another wrapper class for Graph, containing the basic information needed to represent a
connection between two vertices. Its attributes are:
- startuid: the UID of the first Vertex this edge connects
- enduid: the UID of the last Vertex this edge connects
- measurement: a 7x1 ndarray, the pose of the end Vertex relative to the start Vertex
- information: The omega matrix for G2O - typically a diagonal matrix of the weights
- (Optional) information_prescaling: Values to create a prescaling matrix for information, defaults to 6x1 of ones
- (Optional) corner_ids: For SBA, the uids of the corners of the tag
- (Optional) camera_intrinsics: For SBA, the matrix needed to convert pixels to position in space
Like Vertex, Edges are stored as a dict of int to Edge. In general, we refer to edges as “odometry edges”,
“tag edges”, etc. This refers to the type of node it connects. Because of the way our mapping is set up,
all edges are connected to at least one odometry node. This will always be the start node. Therefore,
“odometry edge” is shorthand for “odometry-to-odometry edge” and “tag edge” is short for “odometry-to-tag
edge”, etc. Note also that these are only our own edge types; when converting to G2O, these need to be
converted to their own edge types. Most of the time, this will be EdgeSE3Expmap 2.
Other Attributes
There are a few other items Graph will store. These include:
- _weights: a dict of weights to give to the optimizer. The dict between 4 and 5 elements:
- odometry: 6x1 ndarray, the weights for odometry edges
- tag: 6x1 ndarray, the weights for tag edges without SBA
- Does not have to be included for SBA optimization
- tag_sba: 2x1 ndarray, the weights for tag edges with SBA
- Does not have to be included for non-SBA optimization
- dummy: 6x1 array, the weights for dummy edges
- odom_tag_ratio: Specifies the ratio between the magnitude of the odometry weights and the
tag weights. Currently unused in Graph, but see graph_utils.weight_dict_from_array and
graph_utils.normalize_weights.
- original_vertices: a dict of uid to Vertex, containing the vertices as they were before optimization
- is_sparse_bundle_adjustment: a boolean, whether to perform SBA during optimization
- _verts_to_edges: a mapping of Vertex UIDs to a Set of Edge UIDs
- gravity_axis: which axis is up/down. Defaulted to ‘y’
- Anything with huber and damping: relating to Huber matrixes, unimportant for now
- errors, observations, and anything with maximization: relating to automatically tuning weights, unimportant for now
- unoptimized_graph: a g2opy.SparseOptimizer, the graph to optimize with G2O
- optimized_graph: a g2opy.SparseOptimizer, the resulting graph from G2O
Methods
Update Graph
- set_weights: sets the weights, scaling by the amount of edges each type has, if specified
- update_edges: updates each edge with the current set of weights
- update_vertices: updates the estimates of each Vertex to match the ones in optimized_graph
- delete_tag_vertex: deletes a tag vertex from all attributes, except the SparseOptimizer(s)
- remove_edge: removes an edge from all attributes, except the SparseOptimizer(s)
Chi Squared and Evaluation
- check_optimized_edges (static): calculates the total chi2 from a SparseOptimizer
- get_chi2_of_edge (static): calculates the chi2 from a specific g2opy edge
- get_chi2_of_edge_type: returns a dict containing the chi2 values for each type of edge
-
map_odom_to_adj_chi2: given an odometry vertex, returns the chi2 from that vertex and the
number of tag vertices connecting to that tag
-
get_subgraph: returns a subgraph containing the vertices with UIDs between the given values.
Used to partition a graph for Duncan's evaluation metric
Optimization
- generate_unoptimized_graph: sets unoptimized_graph to the result of graph_to_optimizer
-
graph_to_optimizer: converts this Graph to a SparseOptimizer. Essentially, it pulls the
data from vertices and edges, then creates g2opy objects from that information.
- To actually optimize the Graph, see GraphManager.get_optimizer
While there are many other methods in Graph, the rest do not need to be rigorously explained.
They are either utility methods, not typically called outside of Graph, or relate to weight tuning
("expectation maximization"), which is not important for now.