|
| 1 | +# Creating Graphs |
| 2 | + |
| 3 | +In this section constructing DFG graphs will be discussed. To start, bring DistributedFactorGraphs into your workspace: |
| 4 | + |
| 5 | +```julia |
| 6 | +using DistributedFactorGraphs |
| 7 | +``` |
| 8 | + |
| 9 | +We recommend using IncrementalInference (IIF) to populate DFG graphs. DFG provides the structure, but IIF overloads the provided `addVariable!` and `addFactor!` functions and creates solver-specific data that allows the graph to be solved. So although you can use DFG's `addVariable!` and `addFactor!`, it is better to start with IIF's functions so that the graph is solvable. |
| 10 | + |
| 11 | +So for the following examples, IncrementalInference will be used to create the variables and factors. It should be added and imported to run the examples: |
| 12 | + |
| 13 | +```julia |
| 14 | +using Pkg |
| 15 | +Pkg.add("IncrementalInference") |
| 16 | +using IncrementalInference |
| 17 | +``` |
| 18 | + |
| 19 | +## Initializing a Graph |
| 20 | + |
| 21 | +DFG graphs can be built using various drivers (different representations of the underlying graph). At the moment DFG supports 3 drivers: |
| 22 | +- GraphsDFG: An in-memory graph that uses Graphs.jl for representing the graph. |
| 23 | +- LightDFG: An in-memory graph that uses LightGraphs.jl for representing the graph. |
| 24 | +- CloudGraphs: A database-driven graph that uses Neo4j.jl for interacting with the graph. |
| 25 | + |
| 26 | +In general the first two are used for building and solving graphs, and CloudGraphs is used for persisting in-memory graphs into a database. In the long term we recommend using the LightDFG driver for in-memory operation because Graphs.jl is not actively supported and over time that driver may be deprecated. |
| 27 | + |
| 28 | +To continue the example, run one of the following to create a DFG driver: |
| 29 | + |
| 30 | +### Creating a GraphsDFG Graph |
| 31 | + |
| 32 | +```julia |
| 33 | +# Create a DFG with default solver parameters using the Graphs.jl driver. |
| 34 | +dfg = GraphsDFG{SolverParams}(params=SolverParams()) |
| 35 | +``` |
| 36 | + |
| 37 | +### Creating a LightDFG Graph |
| 38 | + |
| 39 | +```julia |
| 40 | +# Create a DFG with default solver parameters using the LightGraphs.jl driver. |
| 41 | +dfg = LightDFG{SolverParams}(params=SolverParams()) |
| 42 | +``` |
| 43 | + |
| 44 | +### Creating a CloudGraphsDFG Graph |
| 45 | + |
| 46 | +```julia |
| 47 | +# Create a DFG with no solver parameters (just to demonstrate the difference) using the CloudGraphs driver, and connect it to a local Neo4j instance. |
| 48 | +dfg = CloudGraphsDFG{NoSolverParams}("localhost", 7474, "neo4j", "test", |
| 49 | + "testUser", "testRobot", "testSession", |
| 50 | + nothing, |
| 51 | + nothing, |
| 52 | + IncrementalInference.decodePackedType, |
| 53 | + IncrementalInference.rebuildFactorMetadata!) |
| 54 | +``` |
| 55 | + |
| 56 | +## Creating Variables and Factors |
| 57 | + |
| 58 | +DFG and IIF rely on a CRUD (Create, Read, Update, and Delete) interface to allow users to create and edit graphs. |
| 59 | + |
| 60 | +### Creating Variables with IIF |
| 61 | + |
| 62 | +Variables are added using IncrementalInference's `addVariable!` function. To create the variable, you provide the following parameters: |
| 63 | +- The graph the variable is being added to |
| 64 | +- The variable's label (e.g. :x1 or :a) |
| 65 | +- The variable inference type (aka soft type), which is a subtype of InferenceVariable |
| 66 | + |
| 67 | +**NOTE**: Once variables are initialized to a specific soft type, variable node data (solver data) is templated to that type. |
| 68 | + |
| 69 | +In addition, the following optional parameters are provided: |
| 70 | +- Additional labels for the variable (in DFG these are referred to as tags) |
| 71 | +- A `solvable` flag to indicate whether the variable is ready to be added to a solution |
| 72 | + |
| 73 | +Three variables are added: |
| 74 | + |
| 75 | +```julia |
| 76 | +v1 = addVariable!(dfg, :x0, ContinuousScalar, labels = [:POSE], solvable=1) |
| 77 | +v2 = addVariable!(dfg, :x1, ContinuousScalar, labels = [:POSE], solvable=1) |
| 78 | +v3 = addVariable!(dfg, :l0, ContinuousScalar, labels = [:LANDMARK], solvable=1) |
| 79 | +``` |
| 80 | + |
| 81 | +### Creating Factors with IIF |
| 82 | + |
| 83 | +Similarly to variables, it is recommended that users start with the IIF implementation of the `addFactor!` functions to create factors. To create the factors, you provide the following parameters: |
| 84 | +- The graph the variable is being added to |
| 85 | +- The labels for the variables that the factor is linking |
| 86 | +- The factor function (which is a subtype of ) |
| 87 | + |
| 88 | +Additionally, the solvable flag is also set to indicate that the factor can be used in solving graphs. |
| 89 | + |
| 90 | +**NOTE:** Every graph requires a prior for it to be solvable, so it is a good practice to make sure one is added (generally by adding to the first variable in the graph). |
| 91 | + |
| 92 | +Four factors are added: a prior, a linear conditional relationship with a normal distribution between x0 and x1, and a pair of linear conditional relationships between each pose and the landmark. |
| 93 | + |
| 94 | +```julia |
| 95 | +prior = addFactor!(dfg, [:x0], Prior(Normal(0,1))) |
| 96 | +f1 = addFactor!(dfg, [:x0; :x1], LinearConditional(Normal(50.0,2.0)), solvable=1) |
| 97 | +f1 = addFactor!(dfg, [:l0; :x0], LinearConditional(Normal(40.0,5.0)), solvable=1) |
| 98 | +f1 = addFactor!(dfg, [:l0; :x1], LinearConditional(Normal(-10.0,5.0)), solvable=1) |
| 99 | +``` |
| 100 | + |
| 101 | +The produced factor graph is: |
| 102 | + |
| 103 | + |
| 104 | + |
| 105 | +(For more information on producing plots of the graph, please refer to the |
| 106 | +[Drawing Graphs](DrawingGraphs.md) section). |
| 107 | + |
| 108 | +## Listing Variables and Factors |
| 109 | + |
| 110 | +Reading, updating, and deleting all use DFG functions (as opposed to adding, |
| 111 | +where using the IncrementalInference functions are recommended). |
| 112 | + |
| 113 | +Each variable and factor is uniquely identified by its label. The list of |
| 114 | +variable and factor labels can be retrieved with the `ls`/`getVariableIds` and |
| 115 | +`lsf`/`getFactorIds` functions: |
| 116 | + |
| 117 | +```@docs |
| 118 | +getVariableIds |
| 119 | +ls |
| 120 | +``` |
| 121 | + |
| 122 | +```@docs |
| 123 | +getFactorIds |
| 124 | +lsf |
| 125 | +``` |
| 126 | + |
| 127 | +To list all variables or factors (instead of just their labels), use the |
| 128 | +`getVariables` and `getFactors` functions: |
| 129 | + |
| 130 | +```@docs |
| 131 | +getVariables |
| 132 | +getFactors |
| 133 | +``` |
| 134 | + |
| 135 | +**NOTE**: `getNeighbors` is also worth mentioning at this point as it is a simple way to |
| 136 | +find the bigraph relationships. More information on this and other ways to |
| 137 | +retrieve filtered lists of variables/factors (an area that's currently WIP in |
| 138 | +DFG) can be found in [Traversing and Querying](TraversingAndQuerying.md). |
| 139 | + |
| 140 | +## Getting (Reading) Variables and Factors |
| 141 | + |
| 142 | +Individual variables and factors can be retrieved from their labels using the following functions: |
| 143 | + |
| 144 | +```@docs |
| 145 | +getVariable |
| 146 | +``` |
| 147 | + |
| 148 | +```@docs |
| 149 | +getFactor |
| 150 | +``` |
| 151 | + |
| 152 | +It is worth noting that `getVariable` allows a user to retrieve only a single |
| 153 | +solver entry, so that subsets of the solver data can be retrieved individually |
| 154 | +(say, in the case that there are many solutions). These can then be updated |
| 155 | +independently using the functions as discussed in the update section below. |
| 156 | + |
| 157 | +## Updating Variables and Factors |
| 158 | + |
| 159 | +Full variables and factors can be updated using the following functions: |
| 160 | + |
| 161 | +```@docs |
| 162 | +updateVariable! |
| 163 | +``` |
| 164 | + |
| 165 | +```@docs |
| 166 | +updateFactor! |
| 167 | +``` |
| 168 | + |
| 169 | +**NOTE**: Skeleton and summary variables are read-only. To perform updates you |
| 170 | +should use the full factors and variables. |
| 171 | + |
| 172 | +**NOTE**: `updateVariable`/`updateFactor` performs a complete update of the |
| 173 | +respective node. It's not a very efficient way to edit fine-grain detail. There |
| 174 | +are other methods to perform smaller in-place changes. This is discussed in |
| 175 | +more detail in [Data Structure](DataStructure.md). |
| 176 | + |
| 177 | +## Deleting Variables and Factors |
| 178 | + |
| 179 | +Variables and factors can be deleted using the following functions: |
| 180 | + |
| 181 | +```@docs |
| 182 | +deleteVariable! |
| 183 | +``` |
| 184 | + |
| 185 | +```@docs |
| 186 | +deleteFactor! |
| 187 | +``` |
0 commit comments