Main Content

addRelativePose

Add relative pose to pose graph

Description

addRelativePose(poseGraph,measurement) creates a node based on the input measurement that connects to the last pose node in the pose graph. To add landmark nodes, see the addPointLandmark function.

addRelativePose(poseGraph,measurement,infoMat) also specifies the information matrix as part of the edge constraint, which represents the uncertainty of the pose measurement.

addRelativePose(poseGraph,measurement,infoMat,fromNodeID) creates a new pose node and connects it to the specific node specified by fromNodeID.

addRelativePose(poseGraph,measurement,infoMat,fromNodeID,toNodeID) creates an edge by specifying a relative pose measurement between existing nodes specified by fromNodeID and toNodeID. This edge is called a loop closure. If a loop closure already exists, the function appends the new measurement. Calling the optimizePoseGraph function combines multiple appended measurements into a single edge. This syntax does not support adding edges to a landmark node.

example

[nodePair,edgeID] = addRelativePose(___) returns the newly added edge and edge ID using any of the previous syntaxes.

Examples

collapse all

This example shows how to identify and remove spurious loop closures from pose graph. To do this, you can modify the relative pose of a loop closure edge and try optimizing the pose graph with and without removing the auto spurious loop closure and compare the results.

Load the Intel Research Lab Dataset that contains a 2-D pose graph. Optimize the pose graph. Plot the pose graph with IDs off. Red lines indicate loop closures identified in the dataset.

load intel-2d-posegraph.mat pg
optimizedPG = optimizePoseGraph(pg);
show(optimizedPG,IDs="off");
title("Optimized Pose Graph")

Figure contains an axes object. The axes object with title Optimized Pose Graph, xlabel X, ylabel Y contains 3 objects of type line. One or more of the lines displays its values using only markers

Modify the relative pose of the loop closure edge 1386 to some random values.

loopclosureId = 1386;
nodePair = edgeNodePairs(optimizedPG,loopclosureId);
[relPose,infoMat] = edgeConstraints(optimizedPG,loopclosureId);
relPose(2) = -5;
relPose(3) = 1.5;
addRelativePose(optimizedPG,relPose,infoMat,nodePair(1),nodePair(2));

Optimize the pose graph without auto loop closure trimming. Plot the optimized pose graph to see the poor adjustment of the nodes with loop closures.

[updatedPG,solutionInfo] = optimizePoseGraph(optimizedPG);
show(updatedPG,IDs="off");
title("Updated Pose Graph")

Figure contains an axes object. The axes object with title Updated Pose Graph, xlabel X, ylabel Y contains 3 objects of type line. One or more of the lines displays its values using only markers

Certain loop closures should be trimmed from the pose graph. Use the trimLoopClosures function to trim these bad loop closures. Set the truncation threshold and maximum iterations for the trimmer parameters.

trimParams = struct("TruncationThreshold",0.5,"MaxIterations",100);

Generate solver options.

solverOptions = poseGraphSolverOptions("g2o-levenberg-marquardt");

Use the trimLoopClosures function with the trimmer parameters and solver options. Plot the new pose graph to see the bad loop closures were removed.

[newPG,trimInfo] = trimLoopClosures(updatedPG,trimParams,solverOptions);
show(newPG,IDs="off");
title("New Pose Graph")

Figure contains an axes object. The axes object with title New Pose Graph, xlabel X, ylabel Y contains 3 objects of type line. One or more of the lines displays its values using only markers

Input Arguments

collapse all

Pose graph, specified as a poseGraph or poseGraph3D object.

Relative pose between nodes, specified as one of the following:

For poseGraph (2-D), the pose is a [x y theta] vector, which defines a xy-position and orientation angle, theta.

For poseGraph3D, the pose is a [x y z qw qx qy qz] vector, which defines by an xyz-position and quaternion orientation, [qw qx qy qz]

Note

Many other sources for 3-D pose graphs, including .g2o formats, specify the quaternion orientation in a different order, for example, [qx qy qz qw]. Check the source of your pose graph data before adding nodes to your poseGraph3D object.

Information matrices, specified in compact form as a six-element vector or 21-element vector.

Each vector is the compact form of the upper triangle of the square information matrix. An information matrix represents the uncertainty of the measurement. The matrix is calculated as the inverse of the covariance. If the measurement is an [x y theta] vector, the covariance matrix is a 3-by-3 of pairwise covariance calculations. Typically, the uncertainty is determined by the sensor model.

For poseGraph (2-D), each information matrix is a six-element vector. The default is [1 0 0 1 0 1]. For landmark nodes, the last three elements are returned as NaN.

For poseGraph3D, each information matrix is a 21-element vector. The default is [1 0 0 0 0 0 1 0 0 0 0 1 0 0 0 1 0 0 1 0 1].

Node to attach from, specified as a positive integer. This integer corresponds to the node ID of a node in poseGraph. When specified without toNodeID, addRelativePose creates a new node and adds an edge between the new node and the fromNodeID node.

Node to attach to, specified as a positive integer. This integer corresponds to the node ID of a node in poseGraph. addRelativePose adds an edge between this node and the fromNodeID node.

Output Arguments

collapse all

Edge node pairs in pose graph, returned as two-element vector that lists the IDs of the two nodes that each edge connects. Multiple edges may exist between the same pair of nodes.

ID of added edge, returned as a positive integer.

Extended Capabilities

Version History

Introduced in R2019b