Migrated all examples and tests
parent
8a130c1a54
commit
03306cba9c
|
@ -35,17 +35,17 @@ def run(args):
|
||||||
graph = gtsam.NonlinearFactorGraph()
|
graph = gtsam.NonlinearFactorGraph()
|
||||||
|
|
||||||
# Priors
|
# Priors
|
||||||
prior = gtsam.noiseModel_Isotropic.Sigma(3, 1)
|
prior = gtsam.noiseModel.Isotropic.Sigma(3, 1)
|
||||||
graph.add(gtsam.PriorFactorPose2(11, T11, prior))
|
graph.add(gtsam.PriorFactorPose2(11, T11, prior))
|
||||||
graph.add(gtsam.PriorFactorPose2(21, T21, prior))
|
graph.add(gtsam.PriorFactorPose2(21, T21, prior))
|
||||||
|
|
||||||
# Odometry
|
# Odometry
|
||||||
model = gtsam.noiseModel_Diagonal.Sigmas(np.array([0.01, 0.01, 0.3]))
|
model = gtsam.noiseModel.Diagonal.Sigmas(np.array([0.01, 0.01, 0.3]))
|
||||||
graph.add(gtsam.BetweenFactorPose2(11, 12, T11.between(T12), model))
|
graph.add(gtsam.BetweenFactorPose2(11, 12, T11.between(T12), model))
|
||||||
graph.add(gtsam.BetweenFactorPose2(21, 22, T21.between(T22), model))
|
graph.add(gtsam.BetweenFactorPose2(21, 22, T21.between(T22), model))
|
||||||
|
|
||||||
# Range
|
# Range
|
||||||
model_rho = gtsam.noiseModel_Isotropic.Sigma(1, 0.01)
|
model_rho = gtsam.noiseModel.Isotropic.Sigma(1, 0.01)
|
||||||
graph.add(gtsam.RangeFactorPose2(12, 22, 1.0, model_rho))
|
graph.add(gtsam.RangeFactorPose2(12, 22, 1.0, model_rho))
|
||||||
|
|
||||||
params = gtsam.DoglegParams()
|
params = gtsam.DoglegParams()
|
||||||
|
|
|
@ -26,8 +26,8 @@ lon0 = -84.30626
|
||||||
h0 = 274
|
h0 = 274
|
||||||
|
|
||||||
# Create noise models
|
# Create noise models
|
||||||
GPS_NOISE = gtsam.noiseModel_Isotropic.Sigma(3, 0.1)
|
GPS_NOISE = gtsam.noiseModel.Isotropic.Sigma(3, 0.1)
|
||||||
PRIOR_NOISE = gtsam.noiseModel_Isotropic.Sigma(6, 0.25)
|
PRIOR_NOISE = gtsam.noiseModel.Isotropic.Sigma(6, 0.25)
|
||||||
|
|
||||||
# Create an empty nonlinear factor graph
|
# Create an empty nonlinear factor graph
|
||||||
graph = gtsam.NonlinearFactorGraph()
|
graph = gtsam.NonlinearFactorGraph()
|
||||||
|
|
|
@ -12,14 +12,13 @@ Author: Frank Dellaert, Varun Agrawal
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
|
import argparse
|
||||||
import math
|
import math
|
||||||
|
|
||||||
import gtsam
|
import gtsam
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from gtsam import symbol_shorthand_B as B
|
from gtsam.symbol_shorthand import B, V, X
|
||||||
from gtsam import symbol_shorthand_V as V
|
|
||||||
from gtsam import symbol_shorthand_X as X
|
|
||||||
from gtsam.utils.plot import plot_pose3
|
from gtsam.utils.plot import plot_pose3
|
||||||
from mpl_toolkits.mplot3d import Axes3D
|
from mpl_toolkits.mplot3d import Axes3D
|
||||||
|
|
||||||
|
@ -33,24 +32,27 @@ np.set_printoptions(precision=3, suppress=True)
|
||||||
|
|
||||||
class ImuFactorExample(PreintegrationExample):
|
class ImuFactorExample(PreintegrationExample):
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, twist_scenario="sick_twist"):
|
||||||
self.velocity = np.array([2, 0, 0])
|
self.velocity = np.array([2, 0, 0])
|
||||||
self.priorNoise = gtsam.noiseModel_Isotropic.Sigma(6, 0.1)
|
self.priorNoise = gtsam.noiseModel.Isotropic.Sigma(6, 0.1)
|
||||||
self.velNoise = gtsam.noiseModel_Isotropic.Sigma(3, 0.1)
|
self.velNoise = gtsam.noiseModel.Isotropic.Sigma(3, 0.1)
|
||||||
|
|
||||||
# Choose one of these twists to change scenario:
|
# Choose one of these twists to change scenario:
|
||||||
zero_twist = (np.zeros(3), np.zeros(3))
|
twist_scenarios = dict(
|
||||||
forward_twist = (np.zeros(3), self.velocity)
|
zero_twist=(np.zeros(3), np.zeros(3)),
|
||||||
loop_twist = (np.array([0, -math.radians(30), 0]), self.velocity)
|
forward_twist=(np.zeros(3), self.velocity),
|
||||||
sick_twist = (
|
loop_twist=(np.array([0, -math.radians(30), 0]), self.velocity),
|
||||||
np.array([math.radians(30), -math.radians(30), 0]), self.velocity)
|
sick_twist=(np.array([math.radians(30), -math.radians(30), 0]),
|
||||||
|
self.velocity)
|
||||||
|
)
|
||||||
|
|
||||||
accBias = np.array([-0.3, 0.1, 0.2])
|
accBias = np.array([-0.3, 0.1, 0.2])
|
||||||
gyroBias = np.array([0.1, 0.3, -0.1])
|
gyroBias = np.array([0.1, 0.3, -0.1])
|
||||||
bias = gtsam.imuBias_ConstantBias(accBias, gyroBias)
|
bias = gtsam.imuBias.ConstantBias(accBias, gyroBias)
|
||||||
|
|
||||||
dt = 1e-2
|
dt = 1e-2
|
||||||
super(ImuFactorExample, self).__init__(sick_twist, bias, dt)
|
super(ImuFactorExample, self).__init__(twist_scenarios[twist_scenario],
|
||||||
|
bias, dt)
|
||||||
|
|
||||||
def addPrior(self, i, graph):
|
def addPrior(self, i, graph):
|
||||||
state = self.scenario.navState(i)
|
state = self.scenario.navState(i)
|
||||||
|
@ -59,65 +61,73 @@ class ImuFactorExample(PreintegrationExample):
|
||||||
graph.push_back(gtsam.PriorFactorVector(
|
graph.push_back(gtsam.PriorFactorVector(
|
||||||
V(i), state.velocity(), self.velNoise))
|
V(i), state.velocity(), self.velNoise))
|
||||||
|
|
||||||
def run(self):
|
def run(self, T=12, compute_covariances=False, verbose=True):
|
||||||
graph = gtsam.NonlinearFactorGraph()
|
graph = gtsam.NonlinearFactorGraph()
|
||||||
|
|
||||||
# initialize data structure for pre-integrated IMU measurements
|
# initialize data structure for pre-integrated IMU measurements
|
||||||
pim = gtsam.PreintegratedImuMeasurements(self.params, self.actualBias)
|
pim = gtsam.PreintegratedImuMeasurements(self.params, self.actualBias)
|
||||||
|
|
||||||
T = 12
|
T = 12
|
||||||
num_poses = T + 1 # assumes 1 factor per second
|
num_poses = T # assumes 1 factor per second
|
||||||
initial = gtsam.Values()
|
initial = gtsam.Values()
|
||||||
initial.insert(BIAS_KEY, self.actualBias)
|
initial.insert(BIAS_KEY, self.actualBias)
|
||||||
for i in range(num_poses):
|
|
||||||
state_i = self.scenario.navState(float(i))
|
|
||||||
|
|
||||||
poseNoise = gtsam.Pose3.Expmap(np.random.randn(3)*0.1)
|
|
||||||
pose = state_i.pose().compose(poseNoise)
|
|
||||||
|
|
||||||
velocity = state_i.velocity() + np.random.randn(3)*0.1
|
|
||||||
|
|
||||||
initial.insert(X(i), pose)
|
|
||||||
initial.insert(V(i), velocity)
|
|
||||||
|
|
||||||
# simulate the loop
|
# simulate the loop
|
||||||
i = 0 # state index
|
i = 0 # state index
|
||||||
actual_state_i = self.scenario.navState(0)
|
initial_state_i = self.scenario.navState(0)
|
||||||
|
initial.insert(X(i), initial_state_i.pose())
|
||||||
|
initial.insert(V(i), initial_state_i.velocity())
|
||||||
|
|
||||||
|
# add prior on beginning
|
||||||
|
self.addPrior(0, graph)
|
||||||
|
|
||||||
for k, t in enumerate(np.arange(0, T, self.dt)):
|
for k, t in enumerate(np.arange(0, T, self.dt)):
|
||||||
# get measurements and add them to PIM
|
# get measurements and add them to PIM
|
||||||
measuredOmega = self.runner.measuredAngularVelocity(t)
|
measuredOmega = self.runner.measuredAngularVelocity(t)
|
||||||
measuredAcc = self.runner.measuredSpecificForce(t)
|
measuredAcc = self.runner.measuredSpecificForce(t)
|
||||||
pim.integrateMeasurement(measuredAcc, measuredOmega, self.dt)
|
pim.integrateMeasurement(measuredAcc, measuredOmega, self.dt)
|
||||||
|
|
||||||
poseNoise = gtsam.Pose3.Expmap(np.random.randn(3)*0.1)
|
|
||||||
|
|
||||||
actual_state_i = gtsam.NavState(
|
|
||||||
actual_state_i.pose().compose(poseNoise),
|
|
||||||
actual_state_i.velocity() + np.random.randn(3)*0.1)
|
|
||||||
|
|
||||||
# Plot IMU many times
|
# Plot IMU many times
|
||||||
if k % 10 == 0:
|
if k % 10 == 0:
|
||||||
self.plotImu(t, measuredOmega, measuredAcc)
|
self.plotImu(t, measuredOmega, measuredAcc)
|
||||||
|
|
||||||
|
if (k+1) % int(1 / self.dt) == 0:
|
||||||
# Plot every second
|
# Plot every second
|
||||||
if k % int(1 / self.dt) == 0:
|
self.plotGroundTruthPose(t, scale=1)
|
||||||
self.plotGroundTruthPose(t)
|
plt.title("Ground Truth Trajectory")
|
||||||
|
|
||||||
# create IMU factor every second
|
# create IMU factor every second
|
||||||
if (k + 1) % int(1 / self.dt) == 0:
|
factor = gtsam.ImuFactor(X(i), V(i),
|
||||||
factor = gtsam.ImuFactor(X(i), V(i), X(
|
X(i + 1), V(i + 1),
|
||||||
i + 1), V(i + 1), BIAS_KEY, pim)
|
BIAS_KEY, pim)
|
||||||
graph.push_back(factor)
|
graph.push_back(factor)
|
||||||
if True:
|
|
||||||
|
if verbose:
|
||||||
print(factor)
|
print(factor)
|
||||||
print(pim.predict(actual_state_i, self.actualBias))
|
print(pim.predict(actual_state_i, self.actualBias))
|
||||||
|
|
||||||
pim.resetIntegration()
|
pim.resetIntegration()
|
||||||
|
|
||||||
|
rotationNoise = gtsam.Rot3.Expmap(np.random.randn(3)*0.1)
|
||||||
|
translationNoise = gtsam.Point3(*np.random.randn(3)*1)
|
||||||
|
poseNoise = gtsam.Pose3(rotationNoise, translationNoise)
|
||||||
|
|
||||||
actual_state_i = self.scenario.navState(t + self.dt)
|
actual_state_i = self.scenario.navState(t + self.dt)
|
||||||
|
print("Actual state at {0}:\n{1}".format(
|
||||||
|
t+self.dt, actual_state_i))
|
||||||
|
|
||||||
|
noisy_state_i = gtsam.NavState(
|
||||||
|
actual_state_i.pose().compose(poseNoise),
|
||||||
|
actual_state_i.velocity() + np.random.randn(3)*0.1)
|
||||||
|
|
||||||
|
initial.insert(X(i+1), noisy_state_i.pose())
|
||||||
|
initial.insert(V(i+1), noisy_state_i.velocity())
|
||||||
i += 1
|
i += 1
|
||||||
|
|
||||||
# add priors on beginning and end
|
# add priors on end
|
||||||
self.addPrior(0, graph)
|
# self.addPrior(num_poses - 1, graph)
|
||||||
self.addPrior(num_poses - 1, graph)
|
|
||||||
|
initial.print_("Initial values:")
|
||||||
|
|
||||||
# optimize using Levenberg-Marquardt optimization
|
# optimize using Levenberg-Marquardt optimization
|
||||||
params = gtsam.LevenbergMarquardtParams()
|
params = gtsam.LevenbergMarquardtParams()
|
||||||
|
@ -125,9 +135,13 @@ class ImuFactorExample(PreintegrationExample):
|
||||||
optimizer = gtsam.LevenbergMarquardtOptimizer(graph, initial, params)
|
optimizer = gtsam.LevenbergMarquardtOptimizer(graph, initial, params)
|
||||||
result = optimizer.optimize()
|
result = optimizer.optimize()
|
||||||
|
|
||||||
|
result.print_("Optimized values:")
|
||||||
|
|
||||||
|
if compute_covariances:
|
||||||
# Calculate and print marginal covariances
|
# Calculate and print marginal covariances
|
||||||
marginals = gtsam.Marginals(graph, result)
|
marginals = gtsam.Marginals(graph, result)
|
||||||
print("Covariance on bias:\n", marginals.marginalCovariance(BIAS_KEY))
|
print("Covariance on bias:\n",
|
||||||
|
marginals.marginalCovariance(BIAS_KEY))
|
||||||
for i in range(num_poses):
|
for i in range(num_poses):
|
||||||
print("Covariance on pose {}:\n{}\n".format(
|
print("Covariance on pose {}:\n{}\n".format(
|
||||||
i, marginals.marginalCovariance(X(i))))
|
i, marginals.marginalCovariance(X(i))))
|
||||||
|
@ -138,16 +152,29 @@ class ImuFactorExample(PreintegrationExample):
|
||||||
i = 0
|
i = 0
|
||||||
while result.exists(X(i)):
|
while result.exists(X(i)):
|
||||||
pose_i = result.atPose3(X(i))
|
pose_i = result.atPose3(X(i))
|
||||||
plot_pose3(POSES_FIG, pose_i, 0.1)
|
plot_pose3(POSES_FIG+1, pose_i, 1)
|
||||||
i += 1
|
i += 1
|
||||||
|
plt.title("Estimated Trajectory")
|
||||||
|
|
||||||
gtsam.utils.plot.set_axes_equal(POSES_FIG)
|
gtsam.utils.plot.set_axes_equal(POSES_FIG+1)
|
||||||
|
|
||||||
print(result.atimuBias_ConstantBias(BIAS_KEY))
|
print("Bias Values", result.atConstantBias(BIAS_KEY))
|
||||||
|
|
||||||
plt.ioff()
|
plt.ioff()
|
||||||
plt.show()
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
ImuFactorExample().run()
|
parser = argparse.ArgumentParser("ImuFactorExample.py")
|
||||||
|
parser.add_argument("--twist_scenario",
|
||||||
|
default="sick_twist",
|
||||||
|
choices=("zero_twist", "forward_twist", "loop_twist", "sick_twist"))
|
||||||
|
parser.add_argument("--time", "-T", default=12,
|
||||||
|
type=int, help="Total time in seconds")
|
||||||
|
parser.add_argument("--compute_covariances",
|
||||||
|
default=False, action='store_true')
|
||||||
|
parser.add_argument("--verbose", default=False, action='store_true')
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
ImuFactorExample(args.twist_scenario).run(
|
||||||
|
args.time, args.compute_covariances, args.verbose)
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
"""
|
"""
|
||||||
iSAM2 example with ImuFactor.
|
iSAM2 example with ImuFactor.
|
||||||
Author: Robert Truax (C++), Frank Dellaert (Python)
|
Author: Robert Truax (C++), Frank Dellaert, Varun Agrawal
|
||||||
"""
|
"""
|
||||||
# pylint: disable=invalid-name, E1101
|
# pylint: disable=invalid-name, E1101
|
||||||
|
|
||||||
|
@ -9,7 +9,6 @@ from __future__ import print_function
|
||||||
import math
|
import math
|
||||||
|
|
||||||
import gtsam
|
import gtsam
|
||||||
import gtsam.utils.plot as gtsam_plot
|
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from gtsam import (ISAM2, BetweenFactorConstantBias, Cal3_S2,
|
from gtsam import (ISAM2, BetweenFactorConstantBias, Cal3_S2,
|
||||||
|
@ -17,9 +16,8 @@ from gtsam import (ISAM2, BetweenFactorConstantBias, Cal3_S2,
|
||||||
PinholeCameraCal3_S2, Point3, Pose3,
|
PinholeCameraCal3_S2, Point3, Pose3,
|
||||||
PriorFactorConstantBias, PriorFactorPose3,
|
PriorFactorConstantBias, PriorFactorPose3,
|
||||||
PriorFactorVector, Rot3, Values)
|
PriorFactorVector, Rot3, Values)
|
||||||
from gtsam import symbol_shorthand_B as B
|
from gtsam.symbol_shorthand import B, V, X
|
||||||
from gtsam import symbol_shorthand_V as V
|
from gtsam.utils import plot
|
||||||
from gtsam import symbol_shorthand_X as X
|
|
||||||
from mpl_toolkits.mplot3d import Axes3D # pylint: disable=W0611
|
from mpl_toolkits.mplot3d import Axes3D # pylint: disable=W0611
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,70 +26,63 @@ def vector3(x, y, z):
|
||||||
return np.array([x, y, z], dtype=np.float)
|
return np.array([x, y, z], dtype=np.float)
|
||||||
|
|
||||||
|
|
||||||
def ISAM2_plot(values, fignum=0):
|
|
||||||
"""Plot poses."""
|
|
||||||
fig = plt.figure(fignum)
|
|
||||||
axes = fig.gca(projection='3d')
|
|
||||||
plt.cla()
|
|
||||||
|
|
||||||
i = 0
|
|
||||||
min_bounds = 0, 0, 0
|
|
||||||
max_bounds = 0, 0, 0
|
|
||||||
while values.exists(X(i)):
|
|
||||||
pose_i = values.atPose3(X(i))
|
|
||||||
gtsam_plot.plot_pose3(fignum, pose_i, 10)
|
|
||||||
position = pose_i.translation().vector()
|
|
||||||
min_bounds = [min(v1, v2) for (v1, v2) in zip(position, min_bounds)]
|
|
||||||
max_bounds = [max(v1, v2) for (v1, v2) in zip(position, max_bounds)]
|
|
||||||
# max_bounds = min(pose_i.x(), max_bounds[0]), 0, 0
|
|
||||||
i += 1
|
|
||||||
|
|
||||||
# draw
|
|
||||||
axes.set_xlim3d(min_bounds[0]-1, max_bounds[0]+1)
|
|
||||||
axes.set_ylim3d(min_bounds[1]-1, max_bounds[1]+1)
|
|
||||||
axes.set_zlim3d(min_bounds[2]-1, max_bounds[2]+1)
|
|
||||||
plt.pause(1)
|
|
||||||
|
|
||||||
|
|
||||||
# IMU preintegration parameters
|
|
||||||
# Default Params for a Z-up navigation frame, such as ENU: gravity points along negative Z-axis
|
|
||||||
g = 9.81
|
g = 9.81
|
||||||
n_gravity = vector3(0, 0, -g)
|
n_gravity = vector3(0, 0, -g)
|
||||||
PARAMS = gtsam.PreintegrationParams.MakeSharedU(g)
|
|
||||||
I = np.eye(3)
|
|
||||||
PARAMS.setAccelerometerCovariance(I * 0.1)
|
|
||||||
PARAMS.setGyroscopeCovariance(I * 0.1)
|
|
||||||
PARAMS.setIntegrationCovariance(I * 0.1)
|
|
||||||
PARAMS.setUse2ndOrderCoriolis(False)
|
|
||||||
PARAMS.setOmegaCoriolis(vector3(0, 0, 0))
|
|
||||||
|
|
||||||
BIAS_COVARIANCE = gtsam.noiseModel_Isotropic.Variance(6, 0.1)
|
|
||||||
DELTA = Pose3(Rot3.Rodrigues(0, 0, 0),
|
def preintegration_parameters():
|
||||||
|
# IMU preintegration parameters
|
||||||
|
# Default Params for a Z-up navigation frame, such as ENU: gravity points along negative Z-axis
|
||||||
|
PARAMS = gtsam.PreintegrationParams.MakeSharedU(g)
|
||||||
|
I = np.eye(3)
|
||||||
|
PARAMS.setAccelerometerCovariance(I * 0.1)
|
||||||
|
PARAMS.setGyroscopeCovariance(I * 0.1)
|
||||||
|
PARAMS.setIntegrationCovariance(I * 0.1)
|
||||||
|
PARAMS.setUse2ndOrderCoriolis(False)
|
||||||
|
PARAMS.setOmegaCoriolis(vector3(0, 0, 0))
|
||||||
|
|
||||||
|
BIAS_COVARIANCE = gtsam.noiseModel.Isotropic.Variance(6, 0.1)
|
||||||
|
DELTA = Pose3(Rot3.Rodrigues(0, 0, 0),
|
||||||
Point3(0.05, -0.10, 0.20))
|
Point3(0.05, -0.10, 0.20))
|
||||||
|
|
||||||
|
return PARAMS, BIAS_COVARIANCE, DELTA
|
||||||
|
|
||||||
|
|
||||||
|
def get_camera(radius):
|
||||||
|
up = Point3(0, 0, 1)
|
||||||
|
target = Point3(0, 0, 0)
|
||||||
|
position = Point3(radius, 0, 0)
|
||||||
|
camera = PinholeCameraCal3_S2.Lookat(position, target, up, Cal3_S2())
|
||||||
|
return camera
|
||||||
|
|
||||||
|
|
||||||
|
def get_scenario(radius, pose_0, angular_velocity, delta_t):
|
||||||
|
"""Create the set of ground-truth landmarks and poses"""
|
||||||
|
|
||||||
|
angular_velocity_vector = vector3(0, -angular_velocity, 0)
|
||||||
|
linear_velocity_vector = vector3(radius * angular_velocity, 0, 0)
|
||||||
|
scenario = ConstantTwistScenario(
|
||||||
|
angular_velocity_vector, linear_velocity_vector, pose_0)
|
||||||
|
|
||||||
|
return scenario
|
||||||
|
|
||||||
|
|
||||||
def IMU_example():
|
def IMU_example():
|
||||||
"""Run iSAM 2 example with IMU factor."""
|
"""Run iSAM 2 example with IMU factor."""
|
||||||
|
|
||||||
# Start with a camera on x-axis looking at origin
|
# Start with a camera on x-axis looking at origin
|
||||||
radius = 30
|
radius = 30
|
||||||
up = Point3(0, 0, 1)
|
camera = get_camera(radius)
|
||||||
target = Point3(0, 0, 0)
|
|
||||||
position = Point3(radius, 0, 0)
|
|
||||||
camera = PinholeCameraCal3_S2.Lookat(position, target, up, Cal3_S2())
|
|
||||||
pose_0 = camera.pose()
|
pose_0 = camera.pose()
|
||||||
|
|
||||||
# Create the set of ground-truth landmarks and poses
|
|
||||||
angular_velocity = math.radians(180) # rad/sec
|
|
||||||
delta_t = 1.0/18 # makes for 10 degrees per step
|
delta_t = 1.0/18 # makes for 10 degrees per step
|
||||||
|
angular_velocity = math.radians(180) # rad/sec
|
||||||
|
scenario = get_scenario(radius, pose_0, angular_velocity, delta_t)
|
||||||
|
|
||||||
angular_velocity_vector = vector3(0, -angular_velocity, 0)
|
PARAMS, BIAS_COVARIANCE, DELTA = preintegration_parameters()
|
||||||
linear_velocity_vector = vector3(radius * angular_velocity, 0, 0)
|
|
||||||
scenario = ConstantTwistScenario(
|
|
||||||
angular_velocity_vector, linear_velocity_vector, pose_0)
|
|
||||||
|
|
||||||
# Create a factor graph
|
# Create a factor graph
|
||||||
newgraph = NonlinearFactorGraph()
|
graph = NonlinearFactorGraph()
|
||||||
|
|
||||||
# Create (incremental) ISAM2 solver
|
# Create (incremental) ISAM2 solver
|
||||||
isam = ISAM2()
|
isam = ISAM2()
|
||||||
|
@ -102,23 +93,23 @@ def IMU_example():
|
||||||
|
|
||||||
# Add a prior on pose x0. This indirectly specifies where the origin is.
|
# Add a prior on pose x0. This indirectly specifies where the origin is.
|
||||||
# 30cm std on x,y,z 0.1 rad on roll,pitch,yaw
|
# 30cm std on x,y,z 0.1 rad on roll,pitch,yaw
|
||||||
noise = gtsam.noiseModel_Diagonal.Sigmas(
|
noise = gtsam.noiseModel.Diagonal.Sigmas(
|
||||||
np.array([0.1, 0.1, 0.1, 0.3, 0.3, 0.3]))
|
np.array([0.1, 0.1, 0.1, 0.3, 0.3, 0.3]))
|
||||||
newgraph.push_back(PriorFactorPose3(X(0), pose_0, noise))
|
graph.push_back(PriorFactorPose3(X(0), pose_0, noise))
|
||||||
|
|
||||||
# Add imu priors
|
# Add imu priors
|
||||||
biasKey = B(0)
|
biasKey = B(0)
|
||||||
biasnoise = gtsam.noiseModel_Isotropic.Sigma(6, 0.1)
|
biasnoise = gtsam.noiseModel.Isotropic.Sigma(6, 0.1)
|
||||||
biasprior = PriorFactorConstantBias(biasKey, gtsam.imuBias_ConstantBias(),
|
biasprior = PriorFactorConstantBias(biasKey, gtsam.imuBias.ConstantBias(),
|
||||||
biasnoise)
|
biasnoise)
|
||||||
newgraph.push_back(biasprior)
|
graph.push_back(biasprior)
|
||||||
initialEstimate.insert(biasKey, gtsam.imuBias_ConstantBias())
|
initialEstimate.insert(biasKey, gtsam.imuBias.ConstantBias())
|
||||||
velnoise = gtsam.noiseModel_Isotropic.Sigma(3, 0.1)
|
velnoise = gtsam.noiseModel.Isotropic.Sigma(3, 0.1)
|
||||||
|
|
||||||
# Calculate with correct initial velocity
|
# Calculate with correct initial velocity
|
||||||
n_velocity = vector3(0, angular_velocity * radius, 0)
|
n_velocity = vector3(0, angular_velocity * radius, 0)
|
||||||
velprior = PriorFactorVector(V(0), n_velocity, velnoise)
|
velprior = PriorFactorVector(V(0), n_velocity, velnoise)
|
||||||
newgraph.push_back(velprior)
|
graph.push_back(velprior)
|
||||||
initialEstimate.insert(V(0), n_velocity)
|
initialEstimate.insert(V(0), n_velocity)
|
||||||
|
|
||||||
accum = gtsam.PreintegratedImuMeasurements(PARAMS)
|
accum = gtsam.PreintegratedImuMeasurements(PARAMS)
|
||||||
|
@ -139,9 +130,9 @@ def IMU_example():
|
||||||
if i % 5 == 0:
|
if i % 5 == 0:
|
||||||
biasKey += 1
|
biasKey += 1
|
||||||
factor = BetweenFactorConstantBias(
|
factor = BetweenFactorConstantBias(
|
||||||
biasKey - 1, biasKey, gtsam.imuBias_ConstantBias(), BIAS_COVARIANCE)
|
biasKey - 1, biasKey, gtsam.imuBias.ConstantBias(), BIAS_COVARIANCE)
|
||||||
newgraph.add(factor)
|
graph.add(factor)
|
||||||
initialEstimate.insert(biasKey, gtsam.imuBias_ConstantBias())
|
initialEstimate.insert(biasKey, gtsam.imuBias.ConstantBias())
|
||||||
|
|
||||||
# Predict acceleration and gyro measurements in (actual) body frame
|
# Predict acceleration and gyro measurements in (actual) body frame
|
||||||
nRb = scenario.rotation(t).matrix()
|
nRb = scenario.rotation(t).matrix()
|
||||||
|
@ -152,21 +143,24 @@ def IMU_example():
|
||||||
|
|
||||||
# Add Imu Factor
|
# Add Imu Factor
|
||||||
imufac = ImuFactor(X(i - 1), V(i - 1), X(i), V(i), biasKey, accum)
|
imufac = ImuFactor(X(i - 1), V(i - 1), X(i), V(i), biasKey, accum)
|
||||||
newgraph.add(imufac)
|
graph.add(imufac)
|
||||||
|
|
||||||
# insert new velocity, which is wrong
|
# insert new velocity, which is wrong
|
||||||
initialEstimate.insert(V(i), n_velocity)
|
initialEstimate.insert(V(i), n_velocity)
|
||||||
accum.resetIntegration()
|
accum.resetIntegration()
|
||||||
|
|
||||||
# Incremental solution
|
# Incremental solution
|
||||||
isam.update(newgraph, initialEstimate)
|
isam.update(graph, initialEstimate)
|
||||||
result = isam.calculateEstimate()
|
result = isam.calculateEstimate()
|
||||||
ISAM2_plot(result)
|
plot.plot_incremental_trajectory(0, result,
|
||||||
|
start=i, scale=3, time_interval=0.01)
|
||||||
|
|
||||||
# reset
|
# reset
|
||||||
newgraph = NonlinearFactorGraph()
|
graph = NonlinearFactorGraph()
|
||||||
initialEstimate.clear()
|
initialEstimate.clear()
|
||||||
|
|
||||||
|
plt.show()
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
IMU_example()
|
IMU_example()
|
|
@ -21,8 +21,8 @@ import matplotlib.pyplot as plt
|
||||||
import gtsam.utils.plot as gtsam_plot
|
import gtsam.utils.plot as gtsam_plot
|
||||||
|
|
||||||
# Create noise models
|
# Create noise models
|
||||||
ODOMETRY_NOISE = gtsam.noiseModel_Diagonal.Sigmas(np.array([0.2, 0.2, 0.1]))
|
ODOMETRY_NOISE = gtsam.noiseModel.Diagonal.Sigmas(np.array([0.2, 0.2, 0.1]))
|
||||||
PRIOR_NOISE = gtsam.noiseModel_Diagonal.Sigmas(np.array([0.3, 0.3, 0.1]))
|
PRIOR_NOISE = gtsam.noiseModel.Diagonal.Sigmas(np.array([0.3, 0.3, 0.1]))
|
||||||
|
|
||||||
# Create an empty nonlinear factor graph
|
# Create an empty nonlinear factor graph
|
||||||
graph = gtsam.NonlinearFactorGraph()
|
graph = gtsam.NonlinearFactorGraph()
|
||||||
|
|
|
@ -167,13 +167,11 @@ class ThreeLinkArm(object):
|
||||||
axes = fig.gca()
|
axes = fig.gca()
|
||||||
|
|
||||||
sXl1 = Pose2(0, 0, math.radians(90))
|
sXl1 = Pose2(0, 0, math.radians(90))
|
||||||
t = sXl1.translation()
|
p1 = sXl1.translation()
|
||||||
p1 = np.array([t.x(), t.y()])
|
|
||||||
gtsam_plot.plot_pose2_on_axes(axes, sXl1)
|
gtsam_plot.plot_pose2_on_axes(axes, sXl1)
|
||||||
|
|
||||||
def plot_line(p, g, color):
|
def plot_line(p, g, color):
|
||||||
t = g.translation()
|
q = g.translation()
|
||||||
q = np.array([t.x(), t.y()])
|
|
||||||
line = np.append(p[np.newaxis], q[np.newaxis], axis=0)
|
line = np.append(p[np.newaxis], q[np.newaxis], axis=0)
|
||||||
axes.plot(line[:, 0], line[:, 1], color)
|
axes.plot(line[:, 0], line[:, 1], color)
|
||||||
return q
|
return q
|
||||||
|
|
|
@ -13,15 +13,15 @@ Author: Alex Cunningham (C++), Kevin Deng & Frank Dellaert (Python)
|
||||||
|
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
import gtsam
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from gtsam import symbol_shorthand_L as L
|
|
||||||
from gtsam import symbol_shorthand_X as X
|
import gtsam
|
||||||
|
from gtsam.symbol_shorthand import X, L
|
||||||
|
|
||||||
# Create noise models
|
# Create noise models
|
||||||
PRIOR_NOISE = gtsam.noiseModel_Diagonal.Sigmas(np.array([0.3, 0.3, 0.1]))
|
PRIOR_NOISE = gtsam.noiseModel.Diagonal.Sigmas(np.array([0.3, 0.3, 0.1]))
|
||||||
ODOMETRY_NOISE = gtsam.noiseModel_Diagonal.Sigmas(np.array([0.2, 0.2, 0.1]))
|
ODOMETRY_NOISE = gtsam.noiseModel.Diagonal.Sigmas(np.array([0.2, 0.2, 0.1]))
|
||||||
MEASUREMENT_NOISE = gtsam.noiseModel_Diagonal.Sigmas(np.array([0.1, 0.2]))
|
MEASUREMENT_NOISE = gtsam.noiseModel.Diagonal.Sigmas(np.array([0.1, 0.2]))
|
||||||
|
|
||||||
# Create an empty nonlinear factor graph
|
# Create an empty nonlinear factor graph
|
||||||
graph = gtsam.NonlinearFactorGraph()
|
graph = gtsam.NonlinearFactorGraph()
|
||||||
|
|
|
@ -27,10 +27,9 @@ def vector3(x, y, z):
|
||||||
"""Create 3d double numpy array."""
|
"""Create 3d double numpy array."""
|
||||||
return np.array([x, y, z], dtype=np.float)
|
return np.array([x, y, z], dtype=np.float)
|
||||||
|
|
||||||
|
|
||||||
# Create noise models
|
# Create noise models
|
||||||
PRIOR_NOISE = gtsam.noiseModel_Diagonal.Sigmas(vector3(0.3, 0.3, 0.1))
|
PRIOR_NOISE = gtsam.noiseModel.Diagonal.Sigmas(vector3(0.3, 0.3, 0.1))
|
||||||
ODOMETRY_NOISE = gtsam.noiseModel_Diagonal.Sigmas(vector3(0.2, 0.2, 0.1))
|
ODOMETRY_NOISE = gtsam.noiseModel.Diagonal.Sigmas(vector3(0.2, 0.2, 0.1))
|
||||||
|
|
||||||
# 1. Create a factor graph container and add factors to it
|
# 1. Create a factor graph container and add factors to it
|
||||||
graph = gtsam.NonlinearFactorGraph()
|
graph = gtsam.NonlinearFactorGraph()
|
||||||
|
|
|
@ -53,7 +53,7 @@ graph, initial = gtsam.readG2o(g2oFile, is3D)
|
||||||
assert args.kernel == "none", "Supplied kernel type is not yet implemented"
|
assert args.kernel == "none", "Supplied kernel type is not yet implemented"
|
||||||
|
|
||||||
# Add prior on the pose having index (key) = 0
|
# Add prior on the pose having index (key) = 0
|
||||||
priorModel = gtsam.noiseModel_Diagonal.Variances(vector3(1e-6, 1e-6, 1e-8))
|
priorModel = gtsam.noiseModel.Diagonal.Variances(vector3(1e-6, 1e-6, 1e-8))
|
||||||
graph.add(gtsam.PriorFactorPose2(0, gtsam.Pose2(), priorModel))
|
graph.add(gtsam.PriorFactorPose2(0, gtsam.Pose2(), priorModel))
|
||||||
|
|
||||||
params = gtsam.GaussNewtonParams()
|
params = gtsam.GaussNewtonParams()
|
||||||
|
@ -82,7 +82,7 @@ else:
|
||||||
print ("Done!")
|
print ("Done!")
|
||||||
|
|
||||||
if args.plot:
|
if args.plot:
|
||||||
resultPoses = gtsam.utilities_extractPose2(result)
|
resultPoses = gtsam.utilities.extractPose2(result)
|
||||||
for i in range(resultPoses.shape[0]):
|
for i in range(resultPoses.shape[0]):
|
||||||
plot.plot_pose2(1, gtsam.Pose2(resultPoses[i, :]))
|
plot.plot_pose2(1, gtsam.Pose2(resultPoses[i, :]))
|
||||||
plt.show()
|
plt.show()
|
||||||
|
|
|
@ -39,11 +39,11 @@ is3D = True
|
||||||
graph, initial = gtsam.readG2o(g2oFile, is3D)
|
graph, initial = gtsam.readG2o(g2oFile, is3D)
|
||||||
|
|
||||||
# Add Prior on the first key
|
# Add Prior on the first key
|
||||||
priorModel = gtsam.noiseModel_Diagonal.Variances(vector6(1e-6, 1e-6, 1e-6,
|
priorModel = gtsam.noiseModel.Diagonal.Variances(vector6(1e-6, 1e-6, 1e-6,
|
||||||
1e-4, 1e-4, 1e-4))
|
1e-4, 1e-4, 1e-4))
|
||||||
|
|
||||||
print("Adding prior to g2o file ")
|
print("Adding prior to g2o file ")
|
||||||
firstKey = initial.keys().at(0)
|
firstKey = initial.keys()[0]
|
||||||
graph.add(gtsam.PriorFactorPose3(firstKey, gtsam.Pose3(), priorModel))
|
graph.add(gtsam.PriorFactorPose3(firstKey, gtsam.Pose3(), priorModel))
|
||||||
|
|
||||||
params = gtsam.GaussNewtonParams()
|
params = gtsam.GaussNewtonParams()
|
||||||
|
@ -65,7 +65,7 @@ else:
|
||||||
print ("Done!")
|
print ("Done!")
|
||||||
|
|
||||||
if args.plot:
|
if args.plot:
|
||||||
resultPoses = gtsam.utilities_allPose3s(result)
|
resultPoses = gtsam.utilities.allPose3s(result)
|
||||||
for i in range(resultPoses.size()):
|
for i in range(resultPoses.size()):
|
||||||
plot.plot_pose3(1, resultPoses.atPose3(i))
|
plot.plot_pose3(1, resultPoses.atPose3(i))
|
||||||
plt.show()
|
plt.show()
|
||||||
|
|
|
@ -24,9 +24,9 @@ is3D = True
|
||||||
graph, initial = gtsam.readG2o(g2oFile, is3D)
|
graph, initial = gtsam.readG2o(g2oFile, is3D)
|
||||||
|
|
||||||
# Add prior on the first key. TODO: assumes first key ios z
|
# Add prior on the first key. TODO: assumes first key ios z
|
||||||
priorModel = gtsam.noiseModel_Diagonal.Variances(
|
priorModel = gtsam.noiseModel.Diagonal.Variances(
|
||||||
np.array([1e-6, 1e-6, 1e-6, 1e-4, 1e-4, 1e-4]))
|
np.array([1e-6, 1e-6, 1e-6, 1e-4, 1e-4, 1e-4]))
|
||||||
firstKey = initial.keys().at(0)
|
firstKey = initial.keys()[0]
|
||||||
graph.add(gtsam.PriorFactorPose3(0, gtsam.Pose3(), priorModel))
|
graph.add(gtsam.PriorFactorPose3(0, gtsam.Pose3(), priorModel))
|
||||||
|
|
||||||
# Initializing Pose3 - chordal relaxation"
|
# Initializing Pose3 - chordal relaxation"
|
||||||
|
|
|
@ -10,12 +10,11 @@ A script validating the Preintegration of IMU measurements
|
||||||
|
|
||||||
import math
|
import math
|
||||||
|
|
||||||
|
import gtsam
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from mpl_toolkits.mplot3d import Axes3D
|
|
||||||
|
|
||||||
import gtsam
|
|
||||||
from gtsam.utils.plot import plot_pose3
|
from gtsam.utils.plot import plot_pose3
|
||||||
|
from mpl_toolkits.mplot3d import Axes3D
|
||||||
|
|
||||||
IMU_FIG = 1
|
IMU_FIG = 1
|
||||||
POSES_FIG = 2
|
POSES_FIG = 2
|
||||||
|
@ -68,60 +67,62 @@ class PreintegrationExample(object):
|
||||||
else:
|
else:
|
||||||
accBias = np.array([0, 0.1, 0])
|
accBias = np.array([0, 0.1, 0])
|
||||||
gyroBias = np.array([0, 0, 0])
|
gyroBias = np.array([0, 0, 0])
|
||||||
self.actualBias = gtsam.imuBias_ConstantBias(accBias, gyroBias)
|
self.actualBias = gtsam.imuBias.ConstantBias(accBias, gyroBias)
|
||||||
|
|
||||||
self.runner = gtsam.ScenarioRunner(
|
self.runner = gtsam.ScenarioRunner(
|
||||||
self.scenario, self.params, self.dt, self.actualBias)
|
self.scenario, self.params, self.dt, self.actualBias)
|
||||||
|
|
||||||
|
fig, self.axes = plt.subplots(4, 3)
|
||||||
|
fig.set_tight_layout(True)
|
||||||
|
|
||||||
def plotImu(self, t, measuredOmega, measuredAcc):
|
def plotImu(self, t, measuredOmega, measuredAcc):
|
||||||
plt.figure(IMU_FIG)
|
plt.figure(IMU_FIG)
|
||||||
|
|
||||||
# plot angular velocity
|
# plot angular velocity
|
||||||
omega_b = self.scenario.omega_b(t)
|
omega_b = self.scenario.omega_b(t)
|
||||||
for i, (label, color) in enumerate(zip(self.labels, self.colors)):
|
for i, (label, color) in enumerate(zip(self.labels, self.colors)):
|
||||||
plt.subplot(4, 3, i + 1)
|
ax = self.axes[0][i]
|
||||||
plt.scatter(t, omega_b[i], color='k', marker='.')
|
ax.scatter(t, omega_b[i], color='k', marker='.')
|
||||||
plt.scatter(t, measuredOmega[i], color=color, marker='.')
|
ax.scatter(t, measuredOmega[i], color=color, marker='.')
|
||||||
plt.xlabel('angular velocity ' + label)
|
ax.set_xlabel('angular velocity ' + label)
|
||||||
|
|
||||||
# plot acceleration in nav
|
# plot acceleration in nav
|
||||||
acceleration_n = self.scenario.acceleration_n(t)
|
acceleration_n = self.scenario.acceleration_n(t)
|
||||||
for i, (label, color) in enumerate(zip(self.labels, self.colors)):
|
for i, (label, color) in enumerate(zip(self.labels, self.colors)):
|
||||||
plt.subplot(4, 3, i + 4)
|
ax = self.axes[1][i]
|
||||||
plt.scatter(t, acceleration_n[i], color=color, marker='.')
|
ax.scatter(t, acceleration_n[i], color=color, marker='.')
|
||||||
plt.xlabel('acceleration in nav ' + label)
|
ax.set_xlabel('acceleration in nav ' + label)
|
||||||
|
|
||||||
# plot acceleration in body
|
# plot acceleration in body
|
||||||
acceleration_b = self.scenario.acceleration_b(t)
|
acceleration_b = self.scenario.acceleration_b(t)
|
||||||
for i, (label, color) in enumerate(zip(self.labels, self.colors)):
|
for i, (label, color) in enumerate(zip(self.labels, self.colors)):
|
||||||
plt.subplot(4, 3, i + 7)
|
ax = self.axes[2][i]
|
||||||
plt.scatter(t, acceleration_b[i], color=color, marker='.')
|
ax.scatter(t, acceleration_b[i], color=color, marker='.')
|
||||||
plt.xlabel('acceleration in body ' + label)
|
ax.set_xlabel('acceleration in body ' + label)
|
||||||
|
|
||||||
# plot actual specific force, as well as corrupted
|
# plot actual specific force, as well as corrupted
|
||||||
actual = self.runner.actualSpecificForce(t)
|
actual = self.runner.actualSpecificForce(t)
|
||||||
for i, (label, color) in enumerate(zip(self.labels, self.colors)):
|
for i, (label, color) in enumerate(zip(self.labels, self.colors)):
|
||||||
plt.subplot(4, 3, i + 10)
|
ax = self.axes[3][i]
|
||||||
plt.scatter(t, actual[i], color='k', marker='.')
|
ax.scatter(t, actual[i], color='k', marker='.')
|
||||||
plt.scatter(t, measuredAcc[i], color=color, marker='.')
|
ax.scatter(t, measuredAcc[i], color=color, marker='.')
|
||||||
plt.xlabel('specific force ' + label)
|
ax.set_xlabel('specific force ' + label)
|
||||||
|
|
||||||
def plotGroundTruthPose(self, t):
|
def plotGroundTruthPose(self, t, scale=0.3, time_interval=0.01):
|
||||||
# plot ground truth pose, as well as prediction from integrated IMU measurements
|
# plot ground truth pose, as well as prediction from integrated IMU measurements
|
||||||
actualPose = self.scenario.pose(t)
|
actualPose = self.scenario.pose(t)
|
||||||
plot_pose3(POSES_FIG, actualPose, 0.3)
|
plot_pose3(POSES_FIG, actualPose, 0.3)
|
||||||
t = actualPose.translation()
|
t = actualPose.translation()
|
||||||
self.maxDim = max([abs(t.x()), abs(t.y()), abs(t.z()), self.maxDim])
|
self.maxDim = max([max(np.abs(t)), self.maxDim])
|
||||||
ax = plt.gca()
|
ax = plt.gca()
|
||||||
ax.set_xlim3d(-self.maxDim, self.maxDim)
|
ax.set_xlim3d(-self.maxDim, self.maxDim)
|
||||||
ax.set_ylim3d(-self.maxDim, self.maxDim)
|
ax.set_ylim3d(-self.maxDim, self.maxDim)
|
||||||
ax.set_zlim3d(-self.maxDim, self.maxDim)
|
ax.set_zlim3d(-self.maxDim, self.maxDim)
|
||||||
|
|
||||||
plt.pause(0.01)
|
plt.pause(time_interval)
|
||||||
|
|
||||||
def run(self):
|
def run(self, T=12):
|
||||||
# simulate the loop
|
# simulate the loop
|
||||||
T = 12
|
|
||||||
for i, t in enumerate(np.arange(0, T, self.dt)):
|
for i, t in enumerate(np.arange(0, T, self.dt)):
|
||||||
measuredOmega = self.runner.measuredAngularVelocity(t)
|
measuredOmega = self.runner.measuredAngularVelocity(t)
|
||||||
measuredAcc = self.runner.measuredSpecificForce(t)
|
measuredAcc = self.runner.measuredSpecificForce(t)
|
||||||
|
|
|
@ -1,17 +1,12 @@
|
||||||
These examples are almost identical to the old handwritten python wrapper
|
|
||||||
examples. However, there are just some slight name changes, for example
|
|
||||||
`noiseModel.Diagonal` becomes `noiseModel_Diagonal` etc...
|
|
||||||
Also, instead of `gtsam.Symbol('b', 0)` we can simply say `gtsam.symbol_shorthand_B(0)` or `B(0)` if we use python aliasing.
|
|
||||||
|
|
||||||
# Porting Progress
|
# Porting Progress
|
||||||
|
|
||||||
| C++ Example Name | Ported |
|
| C++ Example Name | Ported |
|
||||||
|-------------------------------------------------------|--------|
|
|-------------------------------------------------------|--------|
|
||||||
| CameraResectioning | |
|
| CameraResectioning | |
|
||||||
| CreateSFMExampleData | |
|
| CreateSFMExampleData | |
|
||||||
| DiscreteBayesNet_FG | none of the required discrete functionality is exposed through cython |
|
| DiscreteBayesNet_FG | none of the required discrete functionality is exposed through Python |
|
||||||
| easyPoint2KalmanFilter | ExtendedKalmanFilter not exposed through cython |
|
| easyPoint2KalmanFilter | ExtendedKalmanFilter not yet exposed through Python |
|
||||||
| elaboratePoint2KalmanFilter | GaussianSequentialSolver not exposed through cython |
|
| elaboratePoint2KalmanFilter | GaussianSequentialSolver not yet exposed through Python |
|
||||||
| ImuFactorExample2 | X |
|
| ImuFactorExample2 | X |
|
||||||
| ImuFactorsExample | |
|
| ImuFactorsExample | |
|
||||||
| ISAM2Example_SmartFactor | |
|
| ISAM2Example_SmartFactor | |
|
||||||
|
@ -25,7 +20,7 @@ Also, instead of `gtsam.Symbol('b', 0)` we can simply say `gtsam.symbol_shorthan
|
||||||
| Pose2SLAMExample_g2o | X |
|
| Pose2SLAMExample_g2o | X |
|
||||||
| Pose2SLAMExample_graph | |
|
| Pose2SLAMExample_graph | |
|
||||||
| Pose2SLAMExample_graphviz | |
|
| Pose2SLAMExample_graphviz | |
|
||||||
| Pose2SLAMExample_lago | lago not exposed through cython |
|
| Pose2SLAMExample_lago | lago not yet exposed through Python |
|
||||||
| Pose2SLAMStressTest | |
|
| Pose2SLAMStressTest | |
|
||||||
| Pose2SLAMwSPCG | |
|
| Pose2SLAMwSPCG | |
|
||||||
| Pose3SLAMExample_changeKeys | |
|
| Pose3SLAMExample_changeKeys | |
|
||||||
|
@ -47,8 +42,8 @@ Also, instead of `gtsam.Symbol('b', 0)` we can simply say `gtsam.symbol_shorthan
|
||||||
| StereoVOExample | |
|
| StereoVOExample | |
|
||||||
| StereoVOExample_large | |
|
| StereoVOExample_large | |
|
||||||
| TimeTBB | |
|
| TimeTBB | |
|
||||||
| UGM_chain | discrete functionality not exposed |
|
| UGM_chain | discrete functionality not yet exposed |
|
||||||
| UGM_small | discrete functionality not exposed |
|
| UGM_small | discrete functionality not yet exposed |
|
||||||
| VisualISAM2Example | X |
|
| VisualISAM2Example | X |
|
||||||
| VisualISAMExample | X |
|
| VisualISAMExample | X |
|
||||||
|
|
||||||
|
|
|
@ -13,14 +13,15 @@ from __future__ import print_function
|
||||||
import gtsam
|
import gtsam
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from gtsam import symbol_shorthand_L as L
|
from gtsam import symbol_shorthand
|
||||||
from gtsam import symbol_shorthand_X as X
|
L = symbol_shorthand.L
|
||||||
|
X = symbol_shorthand.X
|
||||||
|
|
||||||
from gtsam.examples import SFMdata
|
from gtsam.examples import SFMdata
|
||||||
from gtsam.gtsam import (Cal3_S2, DoglegOptimizer,
|
from gtsam import (Cal3_S2, DoglegOptimizer,
|
||||||
GenericProjectionFactorCal3_S2, Marginals,
|
GenericProjectionFactorCal3_S2, Marginals,
|
||||||
NonlinearFactorGraph, PinholeCameraCal3_S2, Point3,
|
NonlinearFactorGraph, PinholeCameraCal3_S2, Point3,
|
||||||
Pose3, PriorFactorPoint3, PriorFactorPose3, Rot3,
|
Pose3, PriorFactorPoint3, PriorFactorPose3, Rot3, Values)
|
||||||
PinholeCameraCal3_S2, Values)
|
|
||||||
from gtsam.utils import plot
|
from gtsam.utils import plot
|
||||||
|
|
||||||
|
|
||||||
|
@ -56,7 +57,7 @@ def main():
|
||||||
K = Cal3_S2(50.0, 50.0, 0.0, 50.0, 50.0)
|
K = Cal3_S2(50.0, 50.0, 0.0, 50.0, 50.0)
|
||||||
|
|
||||||
# Define the camera observation noise model
|
# Define the camera observation noise model
|
||||||
measurement_noise = gtsam.noiseModel_Isotropic.Sigma(2, 1.0) # one pixel in u and v
|
measurement_noise = gtsam.noiseModel.Isotropic.Sigma(2, 1.0) # one pixel in u and v
|
||||||
|
|
||||||
# Create the set of ground-truth landmarks
|
# Create the set of ground-truth landmarks
|
||||||
points = SFMdata.createPoints()
|
points = SFMdata.createPoints()
|
||||||
|
@ -69,7 +70,7 @@ def main():
|
||||||
|
|
||||||
# Add a prior on pose x1. This indirectly specifies where the origin is.
|
# Add a prior on pose x1. This indirectly specifies where the origin is.
|
||||||
# 0.3 rad std on roll,pitch,yaw and 0.1m on x,y,z
|
# 0.3 rad std on roll,pitch,yaw and 0.1m on x,y,z
|
||||||
pose_noise = gtsam.noiseModel_Diagonal.Sigmas(np.array([0.3, 0.3, 0.3, 0.1, 0.1, 0.1]))
|
pose_noise = gtsam.noiseModel.Diagonal.Sigmas(np.array([0.3, 0.3, 0.3, 0.1, 0.1, 0.1]))
|
||||||
factor = PriorFactorPose3(X(0), poses[0], pose_noise)
|
factor = PriorFactorPose3(X(0), poses[0], pose_noise)
|
||||||
graph.push_back(factor)
|
graph.push_back(factor)
|
||||||
|
|
||||||
|
@ -85,7 +86,7 @@ def main():
|
||||||
# Because the structure-from-motion problem has a scale ambiguity, the problem is still under-constrained
|
# Because the structure-from-motion problem has a scale ambiguity, the problem is still under-constrained
|
||||||
# Here we add a prior on the position of the first landmark. This fixes the scale by indicating the distance
|
# Here we add a prior on the position of the first landmark. This fixes the scale by indicating the distance
|
||||||
# between the first camera and the first landmark. All other landmark positions are interpreted using this scale.
|
# between the first camera and the first landmark. All other landmark positions are interpreted using this scale.
|
||||||
point_noise = gtsam.noiseModel_Isotropic.Sigma(3, 0.1)
|
point_noise = gtsam.noiseModel.Isotropic.Sigma(3, 0.1)
|
||||||
factor = PriorFactorPoint3(L(0), points[0], point_noise)
|
factor = PriorFactorPoint3(L(0), points[0], point_noise)
|
||||||
graph.push_back(factor)
|
graph.push_back(factor)
|
||||||
graph.print_('Factor Graph:\n')
|
graph.print_('Factor Graph:\n')
|
||||||
|
@ -97,7 +98,7 @@ def main():
|
||||||
transformed_pose = pose.retract(0.1*np.random.randn(6,1))
|
transformed_pose = pose.retract(0.1*np.random.randn(6,1))
|
||||||
initial_estimate.insert(X(i), transformed_pose)
|
initial_estimate.insert(X(i), transformed_pose)
|
||||||
for j, point in enumerate(points):
|
for j, point in enumerate(points):
|
||||||
transformed_point = Point3(point.vector() + 0.1*np.random.randn(3))
|
transformed_point = point + 0.1*np.random.randn(3)
|
||||||
initial_estimate.insert(L(j), transformed_point)
|
initial_estimate.insert(L(j), transformed_point)
|
||||||
initial_estimate.print_('Initial Estimates:\n')
|
initial_estimate.print_('Initial Estimates:\n')
|
||||||
|
|
||||||
|
|
|
@ -33,7 +33,8 @@ def createPoses(K):
|
||||||
poses = []
|
poses = []
|
||||||
for theta in angles:
|
for theta in angles:
|
||||||
position = gtsam.Point3(radius*np.cos(theta),
|
position = gtsam.Point3(radius*np.cos(theta),
|
||||||
radius*np.sin(theta), height)
|
radius*np.sin(theta),
|
||||||
|
height)
|
||||||
camera = gtsam.PinholeCameraCal3_S2.Lookat(position, target, up, K)
|
camera = gtsam.PinholeCameraCal3_S2.Lookat(position, target, up, K)
|
||||||
poses.append(camera.pose())
|
poses.append(camera.pose())
|
||||||
return poses
|
return poses
|
||||||
|
|
|
@ -10,10 +10,9 @@ This example will perform a relatively trivial optimization on
|
||||||
a single variable with a single factor.
|
a single variable with a single factor.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
import gtsam
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from gtsam import symbol_shorthand_X as X
|
import gtsam
|
||||||
|
from gtsam.symbol_shorthand import X
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""
|
"""
|
||||||
|
@ -33,7 +32,7 @@ def main():
|
||||||
"""
|
"""
|
||||||
prior = gtsam.Rot2.fromAngle(np.deg2rad(30))
|
prior = gtsam.Rot2.fromAngle(np.deg2rad(30))
|
||||||
prior.print_('goal angle')
|
prior.print_('goal angle')
|
||||||
model = gtsam.noiseModel_Isotropic.Sigma(dim=1, sigma=np.deg2rad(1))
|
model = gtsam.noiseModel.Isotropic.Sigma(dim=1, sigma=np.deg2rad(1))
|
||||||
key = X(1)
|
key = X(1)
|
||||||
factor = gtsam.PriorFactorRot2(key, prior, model)
|
factor = gtsam.PriorFactorRot2(key, prior, model)
|
||||||
|
|
||||||
|
|
|
@ -17,8 +17,7 @@ import gtsam
|
||||||
import gtsam.utils.plot as gtsam_plot
|
import gtsam.utils.plot as gtsam_plot
|
||||||
import matplotlib.pyplot as plt
|
import matplotlib.pyplot as plt
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from gtsam import symbol_shorthand_L as L
|
from gtsam.symbol_shorthand import L, X
|
||||||
from gtsam import symbol_shorthand_X as X
|
|
||||||
from gtsam.examples import SFMdata
|
from gtsam.examples import SFMdata
|
||||||
from mpl_toolkits.mplot3d import Axes3D # pylint: disable=W0611
|
from mpl_toolkits.mplot3d import Axes3D # pylint: disable=W0611
|
||||||
|
|
||||||
|
@ -64,7 +63,7 @@ def visual_ISAM2_example():
|
||||||
K = gtsam.Cal3_S2(50.0, 50.0, 0.0, 50.0, 50.0)
|
K = gtsam.Cal3_S2(50.0, 50.0, 0.0, 50.0, 50.0)
|
||||||
|
|
||||||
# Define the camera observation noise model
|
# Define the camera observation noise model
|
||||||
measurement_noise = gtsam.noiseModel_Isotropic.Sigma(
|
measurement_noise = gtsam.noiseModel.Isotropic.Sigma(
|
||||||
2, 1.0) # one pixel in u and v
|
2, 1.0) # one pixel in u and v
|
||||||
|
|
||||||
# Create the set of ground-truth landmarks
|
# Create the set of ground-truth landmarks
|
||||||
|
@ -110,12 +109,12 @@ def visual_ISAM2_example():
|
||||||
# at least twice before adding it to iSAM.
|
# at least twice before adding it to iSAM.
|
||||||
if i == 0:
|
if i == 0:
|
||||||
# Add a prior on pose x0
|
# Add a prior on pose x0
|
||||||
pose_noise = gtsam.noiseModel_Diagonal.Sigmas(np.array(
|
pose_noise = gtsam.noiseModel.Diagonal.Sigmas(np.array(
|
||||||
[0.1, 0.1, 0.1, 0.3, 0.3, 0.3])) # 30cm std on x,y,z 0.1 rad on roll,pitch,yaw
|
[0.1, 0.1, 0.1, 0.3, 0.3, 0.3])) # 30cm std on x,y,z 0.1 rad on roll,pitch,yaw
|
||||||
graph.push_back(gtsam.PriorFactorPose3(X(0), poses[0], pose_noise))
|
graph.push_back(gtsam.PriorFactorPose3(X(0), poses[0], pose_noise))
|
||||||
|
|
||||||
# Add a prior on landmark l0
|
# Add a prior on landmark l0
|
||||||
point_noise = gtsam.noiseModel_Isotropic.Sigma(3, 0.1)
|
point_noise = gtsam.noiseModel.Isotropic.Sigma(3, 0.1)
|
||||||
graph.push_back(gtsam.PriorFactorPoint3(
|
graph.push_back(gtsam.PriorFactorPoint3(
|
||||||
L(0), points[0], point_noise)) # add directly to graph
|
L(0), points[0], point_noise)) # add directly to graph
|
||||||
|
|
||||||
|
@ -123,7 +122,7 @@ def visual_ISAM2_example():
|
||||||
# Intentionally initialize the variables off from the ground truth
|
# Intentionally initialize the variables off from the ground truth
|
||||||
for j, point in enumerate(points):
|
for j, point in enumerate(points):
|
||||||
initial_estimate.insert(L(j), gtsam.Point3(
|
initial_estimate.insert(L(j), gtsam.Point3(
|
||||||
point.x()-0.25, point.y()+0.20, point.z()+0.15))
|
point[0]-0.25, point[1]+0.20, point[2]+0.15))
|
||||||
else:
|
else:
|
||||||
# Update iSAM with the new factors
|
# Update iSAM with the new factors
|
||||||
isam.update(graph, initial_estimate)
|
isam.update(graph, initial_estimate)
|
||||||
|
|
|
@ -15,13 +15,11 @@ from __future__ import print_function
|
||||||
import numpy as np
|
import numpy as np
|
||||||
import gtsam
|
import gtsam
|
||||||
from gtsam.examples import SFMdata
|
from gtsam.examples import SFMdata
|
||||||
from gtsam.gtsam import (Cal3_S2, GenericProjectionFactorCal3_S2,
|
from gtsam import (Cal3_S2, GenericProjectionFactorCal3_S2,
|
||||||
NonlinearFactorGraph, NonlinearISAM, Point3, Pose3,
|
NonlinearFactorGraph, NonlinearISAM, Pose3,
|
||||||
PriorFactorPoint3, PriorFactorPose3, Rot3,
|
PriorFactorPoint3, PriorFactorPose3, Rot3,
|
||||||
PinholeCameraCal3_S2, Values)
|
PinholeCameraCal3_S2, Values, Point3)
|
||||||
from gtsam import symbol_shorthand_L as L
|
from gtsam.symbol_shorthand import X, L
|
||||||
from gtsam import symbol_shorthand_X as X
|
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
"""
|
"""
|
||||||
|
@ -34,7 +32,8 @@ def main():
|
||||||
K = Cal3_S2(50.0, 50.0, 0.0, 50.0, 50.0)
|
K = Cal3_S2(50.0, 50.0, 0.0, 50.0, 50.0)
|
||||||
|
|
||||||
# Define the camera observation noise model
|
# Define the camera observation noise model
|
||||||
camera_noise = gtsam.noiseModel_Isotropic.Sigma(2, 1.0) # one pixel in u and v
|
camera_noise = gtsam.noiseModel.Isotropic.Sigma(
|
||||||
|
2, 1.0) # one pixel in u and v
|
||||||
|
|
||||||
# Create the set of ground-truth landmarks
|
# Create the set of ground-truth landmarks
|
||||||
points = SFMdata.createPoints()
|
points = SFMdata.createPoints()
|
||||||
|
@ -55,11 +54,13 @@ def main():
|
||||||
# Add factors for each landmark observation
|
# Add factors for each landmark observation
|
||||||
for j, point in enumerate(points):
|
for j, point in enumerate(points):
|
||||||
measurement = camera.project(point)
|
measurement = camera.project(point)
|
||||||
factor = GenericProjectionFactorCal3_S2(measurement, camera_noise, X(i), L(j), K)
|
factor = GenericProjectionFactorCal3_S2(
|
||||||
|
measurement, camera_noise, X(i), L(j), K)
|
||||||
graph.push_back(factor)
|
graph.push_back(factor)
|
||||||
|
|
||||||
# Intentionally initialize the variables off from the ground truth
|
# Intentionally initialize the variables off from the ground truth
|
||||||
noise = Pose3(r=Rot3.Rodrigues(-0.1, 0.2, 0.25), t=Point3(0.05, -0.10, 0.20))
|
noise = Pose3(r=Rot3.Rodrigues(-0.1, 0.2, 0.25),
|
||||||
|
t=Point3(0.05, -0.10, 0.20))
|
||||||
initial_xi = pose.compose(noise)
|
initial_xi = pose.compose(noise)
|
||||||
|
|
||||||
# Add an initial guess for the current pose
|
# Add an initial guess for the current pose
|
||||||
|
@ -71,12 +72,13 @@ def main():
|
||||||
# adding it to iSAM.
|
# adding it to iSAM.
|
||||||
if i == 0:
|
if i == 0:
|
||||||
# Add a prior on pose x0, with 0.3 rad std on roll,pitch,yaw and 0.1m x,y,z
|
# Add a prior on pose x0, with 0.3 rad std on roll,pitch,yaw and 0.1m x,y,z
|
||||||
pose_noise = gtsam.noiseModel_Diagonal.Sigmas(np.array([0.3, 0.3, 0.3, 0.1, 0.1, 0.1]))
|
pose_noise = gtsam.noiseModel.Diagonal.Sigmas(
|
||||||
|
np.array([0.3, 0.3, 0.3, 0.1, 0.1, 0.1]))
|
||||||
factor = PriorFactorPose3(X(0), poses[0], pose_noise)
|
factor = PriorFactorPose3(X(0), poses[0], pose_noise)
|
||||||
graph.push_back(factor)
|
graph.push_back(factor)
|
||||||
|
|
||||||
# Add a prior on landmark l0
|
# Add a prior on landmark l0
|
||||||
point_noise = gtsam.noiseModel_Isotropic.Sigma(3, 0.1)
|
point_noise = gtsam.noiseModel.Isotropic.Sigma(3, 0.1)
|
||||||
factor = PriorFactorPoint3(L(0), points[0], point_noise)
|
factor = PriorFactorPoint3(L(0), points[0], point_noise)
|
||||||
graph.push_back(factor)
|
graph.push_back(factor)
|
||||||
|
|
||||||
|
@ -84,8 +86,8 @@ def main():
|
||||||
noise = np.array([-0.25, 0.20, 0.15])
|
noise = np.array([-0.25, 0.20, 0.15])
|
||||||
for j, point in enumerate(points):
|
for j, point in enumerate(points):
|
||||||
# Intentionally initialize the variables off from the ground truth
|
# Intentionally initialize the variables off from the ground truth
|
||||||
initial_lj = points[j].vector() + noise
|
initial_lj = points[j] + noise
|
||||||
initial_estimate.insert(L(j), Point3(initial_lj))
|
initial_estimate.insert(L(j), initial_lj)
|
||||||
else:
|
else:
|
||||||
# Update iSAM with the new factors
|
# Update iSAM with the new factors
|
||||||
isam.update(graph, initial_estimate)
|
isam.update(graph, initial_estimate)
|
||||||
|
|
|
@ -32,7 +32,7 @@ class TestScenarioRunner(GtsamTestCase):
|
||||||
|
|
||||||
dt = 0.1
|
dt = 0.1
|
||||||
params = gtsam.PreintegrationParams.MakeSharedU(self.g)
|
params = gtsam.PreintegrationParams.MakeSharedU(self.g)
|
||||||
bias = gtsam.imuBias_ConstantBias()
|
bias = gtsam.imuBias.ConstantBias()
|
||||||
runner = gtsam.ScenarioRunner(
|
runner = gtsam.ScenarioRunner(
|
||||||
scenario, params, dt, bias)
|
scenario, params, dt, bias)
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,7 @@ import unittest
|
||||||
|
|
||||||
import gtsam
|
import gtsam
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from gtsam import symbol_shorthand_X as X
|
from gtsam.symbol_shorthand import X
|
||||||
from gtsam.utils.test_case import GtsamTestCase
|
from gtsam.utils.test_case import GtsamTestCase
|
||||||
|
|
||||||
|
|
||||||
|
@ -28,8 +28,8 @@ def create_graph():
|
||||||
x1 = X(1)
|
x1 = X(1)
|
||||||
x2 = X(2)
|
x2 = X(2)
|
||||||
|
|
||||||
BETWEEN_NOISE = gtsam.noiseModel_Diagonal.Sigmas(np.ones(1))
|
BETWEEN_NOISE = gtsam.noiseModel.Diagonal.Sigmas(np.ones(1))
|
||||||
PRIOR_NOISE = gtsam.noiseModel_Diagonal.Sigmas(np.ones(1))
|
PRIOR_NOISE = gtsam.noiseModel.Diagonal.Sigmas(np.ones(1))
|
||||||
|
|
||||||
graph.add(x1, np.eye(1), x0, -np.eye(1), np.ones(1), BETWEEN_NOISE)
|
graph.add(x1, np.eye(1), x0, -np.eye(1), np.ones(1), BETWEEN_NOISE)
|
||||||
graph.add(x2, np.eye(1), x1, -np.eye(1), 2*np.ones(1), BETWEEN_NOISE)
|
graph.add(x2, np.eye(1), x1, -np.eye(1), 2*np.ones(1), BETWEEN_NOISE)
|
||||||
|
|
|
@ -48,7 +48,7 @@ class TestJacobianFactor(GtsamTestCase):
|
||||||
# the RHS
|
# the RHS
|
||||||
b2 = np.array([-1., 1.5, 2., -1.])
|
b2 = np.array([-1., 1.5, 2., -1.])
|
||||||
sigmas = np.array([1., 1., 1., 1.])
|
sigmas = np.array([1., 1., 1., 1.])
|
||||||
model4 = gtsam.noiseModel_Diagonal.Sigmas(sigmas)
|
model4 = gtsam.noiseModel.Diagonal.Sigmas(sigmas)
|
||||||
combined = gtsam.JacobianFactor(x2, Ax2, l1, Al1, x1, Ax1, b2, model4)
|
combined = gtsam.JacobianFactor(x2, Ax2, l1, Al1, x1, Ax1, b2, model4)
|
||||||
|
|
||||||
# eliminate the first variable (x2) in the combined factor, destructive
|
# eliminate the first variable (x2) in the combined factor, destructive
|
||||||
|
@ -66,7 +66,7 @@ class TestJacobianFactor(GtsamTestCase):
|
||||||
[+0.00, -8.94427]])
|
[+0.00, -8.94427]])
|
||||||
d = np.array([2.23607, -1.56525])
|
d = np.array([2.23607, -1.56525])
|
||||||
expectedCG = gtsam.GaussianConditional(
|
expectedCG = gtsam.GaussianConditional(
|
||||||
x2, d, R11, l1, S12, x1, S13, gtsam.noiseModel_Unit.Create(2))
|
x2, d, R11, l1, S12, x1, S13, gtsam.noiseModel.Unit.Create(2))
|
||||||
# check if the result matches
|
# check if the result matches
|
||||||
self.gtsamAssertEquals(actualCG, expectedCG, 1e-4)
|
self.gtsamAssertEquals(actualCG, expectedCG, 1e-4)
|
||||||
|
|
||||||
|
@ -82,7 +82,7 @@ class TestJacobianFactor(GtsamTestCase):
|
||||||
# the RHS
|
# the RHS
|
||||||
b1 = np.array([0.0, 0.894427])
|
b1 = np.array([0.0, 0.894427])
|
||||||
|
|
||||||
model2 = gtsam.noiseModel_Diagonal.Sigmas(np.array([1., 1.]))
|
model2 = gtsam.noiseModel.Diagonal.Sigmas(np.array([1., 1.]))
|
||||||
expectedLF = gtsam.JacobianFactor(l1, Bl1, x1, Bx1, b1, model2)
|
expectedLF = gtsam.JacobianFactor(l1, Bl1, x1, Bx1, b1, model2)
|
||||||
|
|
||||||
# check if the result matches the combined (reduced) factor
|
# check if the result matches the combined (reduced) factor
|
||||||
|
|
|
@ -22,13 +22,13 @@ class TestKalmanFilter(GtsamTestCase):
|
||||||
F = np.eye(2)
|
F = np.eye(2)
|
||||||
B = np.eye(2)
|
B = np.eye(2)
|
||||||
u = np.array([1.0, 0.0])
|
u = np.array([1.0, 0.0])
|
||||||
modelQ = gtsam.noiseModel_Diagonal.Sigmas(np.array([0.1, 0.1]))
|
modelQ = gtsam.noiseModel.Diagonal.Sigmas(np.array([0.1, 0.1]))
|
||||||
Q = 0.01 * np.eye(2)
|
Q = 0.01 * np.eye(2)
|
||||||
H = np.eye(2)
|
H = np.eye(2)
|
||||||
z1 = np.array([1.0, 0.0])
|
z1 = np.array([1.0, 0.0])
|
||||||
z2 = np.array([2.0, 0.0])
|
z2 = np.array([2.0, 0.0])
|
||||||
z3 = np.array([3.0, 0.0])
|
z3 = np.array([3.0, 0.0])
|
||||||
modelR = gtsam.noiseModel_Diagonal.Sigmas(np.array([0.1, 0.1]))
|
modelR = gtsam.noiseModel.Diagonal.Sigmas(np.array([0.1, 0.1]))
|
||||||
R = 0.01 * np.eye(2)
|
R = 0.01 * np.eye(2)
|
||||||
|
|
||||||
# Create the set of expected output TestValues
|
# Create the set of expected output TestValues
|
||||||
|
|
|
@ -18,7 +18,7 @@ import numpy as np
|
||||||
from gtsam.utils.test_case import GtsamTestCase
|
from gtsam.utils.test_case import GtsamTestCase
|
||||||
|
|
||||||
KEY = 0
|
KEY = 0
|
||||||
MODEL = gtsam.noiseModel_Unit.Create(3)
|
MODEL = gtsam.noiseModel.Unit.Create(3)
|
||||||
|
|
||||||
|
|
||||||
def find_Karcher_mean_Rot3(rotations):
|
def find_Karcher_mean_Rot3(rotations):
|
||||||
|
@ -59,8 +59,8 @@ class TestKarcherMean(GtsamTestCase):
|
||||||
R12 = R.compose(R.compose(R))
|
R12 = R.compose(R.compose(R))
|
||||||
graph.add(gtsam.BetweenFactorRot3(1, 2, R12, MODEL))
|
graph.add(gtsam.BetweenFactorRot3(1, 2, R12, MODEL))
|
||||||
keys = gtsam.KeyVector()
|
keys = gtsam.KeyVector()
|
||||||
keys.push_back(1)
|
keys.append(1)
|
||||||
keys.push_back(2)
|
keys.append(2)
|
||||||
graph.add(gtsam.KarcherMeanFactorRot3(keys))
|
graph.add(gtsam.KarcherMeanFactorRot3(keys))
|
||||||
|
|
||||||
initial = gtsam.Values()
|
initial = gtsam.Values()
|
||||||
|
|
|
@ -26,7 +26,7 @@ class TestLocalizationExample(GtsamTestCase):
|
||||||
# Add two odometry factors
|
# Add two odometry factors
|
||||||
# create a measurement for both factors (the same in this case)
|
# create a measurement for both factors (the same in this case)
|
||||||
odometry = gtsam.Pose2(2.0, 0.0, 0.0)
|
odometry = gtsam.Pose2(2.0, 0.0, 0.0)
|
||||||
odometryNoise = gtsam.noiseModel_Diagonal.Sigmas(
|
odometryNoise = gtsam.noiseModel.Diagonal.Sigmas(
|
||||||
np.array([0.2, 0.2, 0.1])) # 20cm std on x,y, 0.1 rad on theta
|
np.array([0.2, 0.2, 0.1])) # 20cm std on x,y, 0.1 rad on theta
|
||||||
graph.add(gtsam.BetweenFactorPose2(0, 1, odometry, odometryNoise))
|
graph.add(gtsam.BetweenFactorPose2(0, 1, odometry, odometryNoise))
|
||||||
graph.add(gtsam.BetweenFactorPose2(1, 2, odometry, odometryNoise))
|
graph.add(gtsam.BetweenFactorPose2(1, 2, odometry, odometryNoise))
|
||||||
|
@ -37,7 +37,7 @@ class TestLocalizationExample(GtsamTestCase):
|
||||||
groundTruth.insert(0, gtsam.Pose2(0.0, 0.0, 0.0))
|
groundTruth.insert(0, gtsam.Pose2(0.0, 0.0, 0.0))
|
||||||
groundTruth.insert(1, gtsam.Pose2(2.0, 0.0, 0.0))
|
groundTruth.insert(1, gtsam.Pose2(2.0, 0.0, 0.0))
|
||||||
groundTruth.insert(2, gtsam.Pose2(4.0, 0.0, 0.0))
|
groundTruth.insert(2, gtsam.Pose2(4.0, 0.0, 0.0))
|
||||||
model = gtsam.noiseModel_Diagonal.Sigmas(np.array([0.1, 0.1, 10.]))
|
model = gtsam.noiseModel.Diagonal.Sigmas(np.array([0.1, 0.1, 10.]))
|
||||||
for i in range(3):
|
for i in range(3):
|
||||||
graph.add(gtsam.PriorFactorPose2(i, groundTruth.atPose2(i), model))
|
graph.add(gtsam.PriorFactorPose2(i, groundTruth.atPose2(i), model))
|
||||||
|
|
||||||
|
|
|
@ -15,11 +15,11 @@ from __future__ import print_function
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
import gtsam
|
import gtsam
|
||||||
from gtsam import (DoglegOptimizer, DoglegParams, GaussNewtonOptimizer,
|
from gtsam import (DoglegOptimizer, DoglegParams,
|
||||||
|
DummyPreconditionerParameters, GaussNewtonOptimizer,
|
||||||
GaussNewtonParams, LevenbergMarquardtOptimizer,
|
GaussNewtonParams, LevenbergMarquardtOptimizer,
|
||||||
LevenbergMarquardtParams, PCGSolverParameters,
|
LevenbergMarquardtParams, NonlinearFactorGraph, Ordering,
|
||||||
DummyPreconditionerParameters, NonlinearFactorGraph, Ordering,
|
PCGSolverParameters, Point2, PriorFactorPoint2, Values)
|
||||||
Point2, PriorFactorPoint2, Values)
|
|
||||||
from gtsam.utils.test_case import GtsamTestCase
|
from gtsam.utils.test_case import GtsamTestCase
|
||||||
|
|
||||||
KEY1 = 1
|
KEY1 = 1
|
||||||
|
@ -30,7 +30,7 @@ class TestScenario(GtsamTestCase):
|
||||||
def test_optimize(self):
|
def test_optimize(self):
|
||||||
"""Do trivial test with three optimizer variants."""
|
"""Do trivial test with three optimizer variants."""
|
||||||
fg = NonlinearFactorGraph()
|
fg = NonlinearFactorGraph()
|
||||||
model = gtsam.noiseModel_Unit.Create(2)
|
model = gtsam.noiseModel.Unit.Create(2)
|
||||||
fg.add(PriorFactorPoint2(KEY1, Point2(0, 0), model))
|
fg.add(PriorFactorPoint2(KEY1, Point2(0, 0), model))
|
||||||
|
|
||||||
# test error at minimum
|
# test error at minimum
|
||||||
|
|
|
@ -25,7 +25,7 @@ class TestOdometryExample(GtsamTestCase):
|
||||||
|
|
||||||
# Add a Gaussian prior on pose x_1
|
# Add a Gaussian prior on pose x_1
|
||||||
priorMean = gtsam.Pose2(0.0, 0.0, 0.0) # prior mean is at origin
|
priorMean = gtsam.Pose2(0.0, 0.0, 0.0) # prior mean is at origin
|
||||||
priorNoise = gtsam.noiseModel_Diagonal.Sigmas(
|
priorNoise = gtsam.noiseModel.Diagonal.Sigmas(
|
||||||
np.array([0.3, 0.3, 0.1])) # 30cm std on x,y, 0.1 rad on theta
|
np.array([0.3, 0.3, 0.1])) # 30cm std on x,y, 0.1 rad on theta
|
||||||
# add directly to graph
|
# add directly to graph
|
||||||
graph.add(gtsam.PriorFactorPose2(1, priorMean, priorNoise))
|
graph.add(gtsam.PriorFactorPose2(1, priorMean, priorNoise))
|
||||||
|
@ -33,7 +33,7 @@ class TestOdometryExample(GtsamTestCase):
|
||||||
# Add two odometry factors
|
# Add two odometry factors
|
||||||
# create a measurement for both factors (the same in this case)
|
# create a measurement for both factors (the same in this case)
|
||||||
odometry = gtsam.Pose2(2.0, 0.0, 0.0)
|
odometry = gtsam.Pose2(2.0, 0.0, 0.0)
|
||||||
odometryNoise = gtsam.noiseModel_Diagonal.Sigmas(
|
odometryNoise = gtsam.noiseModel.Diagonal.Sigmas(
|
||||||
np.array([0.2, 0.2, 0.1])) # 20cm std on x,y, 0.1 rad on theta
|
np.array([0.2, 0.2, 0.1])) # 20cm std on x,y, 0.1 rad on theta
|
||||||
graph.add(gtsam.BetweenFactorPose2(1, 2, odometry, odometryNoise))
|
graph.add(gtsam.BetweenFactorPose2(1, 2, odometry, odometryNoise))
|
||||||
graph.add(gtsam.BetweenFactorPose2(2, 3, odometry, odometryNoise))
|
graph.add(gtsam.BetweenFactorPose2(2, 3, odometry, odometryNoise))
|
||||||
|
|
|
@ -32,13 +32,13 @@ class TestPlanarSLAM(GtsamTestCase):
|
||||||
# Add prior
|
# Add prior
|
||||||
# gaussian for prior
|
# gaussian for prior
|
||||||
priorMean = gtsam.Pose2(0.0, 0.0, 0.0) # prior at origin
|
priorMean = gtsam.Pose2(0.0, 0.0, 0.0) # prior at origin
|
||||||
priorNoise = gtsam.noiseModel_Diagonal.Sigmas(np.array([0.3, 0.3, 0.1]))
|
priorNoise = gtsam.noiseModel.Diagonal.Sigmas(np.array([0.3, 0.3, 0.1]))
|
||||||
# add directly to graph
|
# add directly to graph
|
||||||
graph.add(gtsam.PriorFactorPose2(1, priorMean, priorNoise))
|
graph.add(gtsam.PriorFactorPose2(1, priorMean, priorNoise))
|
||||||
|
|
||||||
# Add odometry
|
# Add odometry
|
||||||
# general noisemodel for odometry
|
# general noisemodel for odometry
|
||||||
odometryNoise = gtsam.noiseModel_Diagonal.Sigmas(np.array([0.2, 0.2, 0.1]))
|
odometryNoise = gtsam.noiseModel.Diagonal.Sigmas(np.array([0.2, 0.2, 0.1]))
|
||||||
graph.add(gtsam.BetweenFactorPose2(
|
graph.add(gtsam.BetweenFactorPose2(
|
||||||
1, 2, gtsam.Pose2(2.0, 0.0, 0.0), odometryNoise))
|
1, 2, gtsam.Pose2(2.0, 0.0, 0.0), odometryNoise))
|
||||||
graph.add(gtsam.BetweenFactorPose2(
|
graph.add(gtsam.BetweenFactorPose2(
|
||||||
|
@ -49,7 +49,7 @@ class TestPlanarSLAM(GtsamTestCase):
|
||||||
4, 5, gtsam.Pose2(2.0, 0.0, pi / 2), odometryNoise))
|
4, 5, gtsam.Pose2(2.0, 0.0, pi / 2), odometryNoise))
|
||||||
|
|
||||||
# Add pose constraint
|
# Add pose constraint
|
||||||
model = gtsam.noiseModel_Diagonal.Sigmas(np.array([0.2, 0.2, 0.1]))
|
model = gtsam.noiseModel.Diagonal.Sigmas(np.array([0.2, 0.2, 0.1]))
|
||||||
graph.add(gtsam.BetweenFactorPose2(5, 2, gtsam.Pose2(2.0, 0.0, pi / 2), model))
|
graph.add(gtsam.BetweenFactorPose2(5, 2, gtsam.Pose2(2.0, 0.0, pi / 2), model))
|
||||||
|
|
||||||
# Initialize to noisy points
|
# Initialize to noisy points
|
||||||
|
|
|
@ -32,13 +32,13 @@ class TestPose2SLAMExample(GtsamTestCase):
|
||||||
# Add prior
|
# Add prior
|
||||||
# gaussian for prior
|
# gaussian for prior
|
||||||
priorMean = gtsam.Pose2(0.0, 0.0, 0.0) # prior at origin
|
priorMean = gtsam.Pose2(0.0, 0.0, 0.0) # prior at origin
|
||||||
priorNoise = gtsam.noiseModel_Diagonal.Sigmas(np.array([0.3, 0.3, 0.1]))
|
priorNoise = gtsam.noiseModel.Diagonal.Sigmas(np.array([0.3, 0.3, 0.1]))
|
||||||
# add directly to graph
|
# add directly to graph
|
||||||
graph.add(gtsam.PriorFactorPose2(1, priorMean, priorNoise))
|
graph.add(gtsam.PriorFactorPose2(1, priorMean, priorNoise))
|
||||||
|
|
||||||
# Add odometry
|
# Add odometry
|
||||||
# general noisemodel for odometry
|
# general noisemodel for odometry
|
||||||
odometryNoise = gtsam.noiseModel_Diagonal.Sigmas(np.array([0.2, 0.2, 0.1]))
|
odometryNoise = gtsam.noiseModel.Diagonal.Sigmas(np.array([0.2, 0.2, 0.1]))
|
||||||
graph.add(gtsam.BetweenFactorPose2(
|
graph.add(gtsam.BetweenFactorPose2(
|
||||||
1, 2, gtsam.Pose2(2.0, 0.0, 0.0), odometryNoise))
|
1, 2, gtsam.Pose2(2.0, 0.0, 0.0), odometryNoise))
|
||||||
graph.add(gtsam.BetweenFactorPose2(
|
graph.add(gtsam.BetweenFactorPose2(
|
||||||
|
@ -49,7 +49,7 @@ class TestPose2SLAMExample(GtsamTestCase):
|
||||||
4, 5, gtsam.Pose2(2.0, 0.0, pi / 2), odometryNoise))
|
4, 5, gtsam.Pose2(2.0, 0.0, pi / 2), odometryNoise))
|
||||||
|
|
||||||
# Add pose constraint
|
# Add pose constraint
|
||||||
model = gtsam.noiseModel_Diagonal.Sigmas(np.array([0.2, 0.2, 0.1]))
|
model = gtsam.noiseModel.Diagonal.Sigmas(np.array([0.2, 0.2, 0.1]))
|
||||||
graph.add(gtsam.BetweenFactorPose2(5, 2, gtsam.Pose2(2.0, 0.0, pi / 2), model))
|
graph.add(gtsam.BetweenFactorPose2(5, 2, gtsam.Pose2(2.0, 0.0, pi / 2), model))
|
||||||
|
|
||||||
# Initialize to noisy points
|
# Initialize to noisy points
|
||||||
|
|
|
@ -30,7 +30,7 @@ class TestPose3SLAMExample(GtsamTestCase):
|
||||||
fg = gtsam.NonlinearFactorGraph()
|
fg = gtsam.NonlinearFactorGraph()
|
||||||
fg.add(gtsam.NonlinearEqualityPose3(0, p0))
|
fg.add(gtsam.NonlinearEqualityPose3(0, p0))
|
||||||
delta = p0.between(p1)
|
delta = p0.between(p1)
|
||||||
covariance = gtsam.noiseModel_Diagonal.Sigmas(
|
covariance = gtsam.noiseModel.Diagonal.Sigmas(
|
||||||
np.array([0.05, 0.05, 0.05, 5. * pi / 180, 5. * pi / 180, 5. * pi / 180]))
|
np.array([0.05, 0.05, 0.05, 5. * pi / 180, 5. * pi / 180, 5. * pi / 180]))
|
||||||
fg.add(gtsam.BetweenFactorPose3(0, 1, delta, covariance))
|
fg.add(gtsam.BetweenFactorPose3(0, 1, delta, covariance))
|
||||||
fg.add(gtsam.BetweenFactorPose3(1, 2, delta, covariance))
|
fg.add(gtsam.BetweenFactorPose3(1, 2, delta, covariance))
|
||||||
|
|
|
@ -23,14 +23,14 @@ class TestPriorFactor(GtsamTestCase):
|
||||||
|
|
||||||
key = 5
|
key = 5
|
||||||
priorPose3 = gtsam.Pose3()
|
priorPose3 = gtsam.Pose3()
|
||||||
model = gtsam.noiseModel_Unit.Create(6)
|
model = gtsam.noiseModel.Unit.Create(6)
|
||||||
factor = gtsam.PriorFactorPose3(key, priorPose3, model)
|
factor = gtsam.PriorFactorPose3(key, priorPose3, model)
|
||||||
values.insert(key, priorPose3)
|
values.insert(key, priorPose3)
|
||||||
self.assertEqual(factor.error(values), 0)
|
self.assertEqual(factor.error(values), 0)
|
||||||
|
|
||||||
key = 3
|
key = 3
|
||||||
priorVector = np.array([0., 0., 0.])
|
priorVector = np.array([0., 0., 0.])
|
||||||
model = gtsam.noiseModel_Unit.Create(3)
|
model = gtsam.noiseModel.Unit.Create(3)
|
||||||
factor = gtsam.PriorFactorVector(key, priorVector, model)
|
factor = gtsam.PriorFactorVector(key, priorVector, model)
|
||||||
values.insert(key, priorVector)
|
values.insert(key, priorVector)
|
||||||
self.assertEqual(factor.error(values), 0)
|
self.assertEqual(factor.error(values), 0)
|
||||||
|
@ -45,14 +45,14 @@ class TestPriorFactor(GtsamTestCase):
|
||||||
# define and add Pose3 prior
|
# define and add Pose3 prior
|
||||||
key = 5
|
key = 5
|
||||||
priorPose3 = gtsam.Pose3()
|
priorPose3 = gtsam.Pose3()
|
||||||
model = gtsam.noiseModel_Unit.Create(6)
|
model = gtsam.noiseModel.Unit.Create(6)
|
||||||
graph.addPriorPose3(key, priorPose3, model)
|
graph.addPriorPose3(key, priorPose3, model)
|
||||||
self.assertEqual(graph.size(), 1)
|
self.assertEqual(graph.size(), 1)
|
||||||
|
|
||||||
# define and add Vector prior
|
# define and add Vector prior
|
||||||
key = 3
|
key = 3
|
||||||
priorVector = np.array([0., 0., 0.])
|
priorVector = np.array([0., 0., 0.])
|
||||||
model = gtsam.noiseModel_Unit.Create(3)
|
model = gtsam.noiseModel.Unit.Create(3)
|
||||||
graph.addPriorVector(key, priorVector, model)
|
graph.addPriorVector(key, priorVector, model)
|
||||||
self.assertEqual(graph.size(), 2)
|
self.assertEqual(graph.size(), 2)
|
||||||
|
|
||||||
|
|
|
@ -15,8 +15,9 @@ import numpy as np
|
||||||
import gtsam
|
import gtsam
|
||||||
import gtsam.utils.visual_data_generator as generator
|
import gtsam.utils.visual_data_generator as generator
|
||||||
from gtsam import symbol
|
from gtsam import symbol
|
||||||
|
from gtsam.noiseModel import Isotropic, Diagonal
|
||||||
from gtsam.utils.test_case import GtsamTestCase
|
from gtsam.utils.test_case import GtsamTestCase
|
||||||
|
from gtsam.symbol_shorthand import X, P
|
||||||
|
|
||||||
class TestSFMExample(GtsamTestCase):
|
class TestSFMExample(GtsamTestCase):
|
||||||
|
|
||||||
|
@ -34,29 +35,29 @@ class TestSFMExample(GtsamTestCase):
|
||||||
graph = gtsam.NonlinearFactorGraph()
|
graph = gtsam.NonlinearFactorGraph()
|
||||||
|
|
||||||
# Add factors for all measurements
|
# Add factors for all measurements
|
||||||
measurementNoise = gtsam.noiseModel_Isotropic.Sigma(2, measurementNoiseSigma)
|
measurementNoise = Isotropic.Sigma(2, measurementNoiseSigma)
|
||||||
for i in range(len(data.Z)):
|
for i in range(len(data.Z)):
|
||||||
for k in range(len(data.Z[i])):
|
for k in range(len(data.Z[i])):
|
||||||
j = data.J[i][k]
|
j = data.J[i][k]
|
||||||
graph.add(gtsam.GenericProjectionFactorCal3_S2(
|
graph.add(gtsam.GenericProjectionFactorCal3_S2(
|
||||||
data.Z[i][k], measurementNoise,
|
data.Z[i][k], measurementNoise,
|
||||||
symbol(ord('x'), i), symbol(ord('p'), j), data.K))
|
X(i), P(j), data.K))
|
||||||
|
|
||||||
posePriorNoise = gtsam.noiseModel_Diagonal.Sigmas(poseNoiseSigmas)
|
posePriorNoise = Diagonal.Sigmas(poseNoiseSigmas)
|
||||||
graph.add(gtsam.PriorFactorPose3(symbol(ord('x'), 0),
|
graph.add(gtsam.PriorFactorPose3(X(0),
|
||||||
truth.cameras[0].pose(), posePriorNoise))
|
truth.cameras[0].pose(), posePriorNoise))
|
||||||
pointPriorNoise = gtsam.noiseModel_Isotropic.Sigma(3, pointNoiseSigma)
|
pointPriorNoise = Isotropic.Sigma(3, pointNoiseSigma)
|
||||||
graph.add(gtsam.PriorFactorPoint3(symbol(ord('p'), 0),
|
graph.add(gtsam.PriorFactorPoint3(P(0),
|
||||||
truth.points[0], pointPriorNoise))
|
truth.points[0], pointPriorNoise))
|
||||||
|
|
||||||
# Initial estimate
|
# Initial estimate
|
||||||
initialEstimate = gtsam.Values()
|
initialEstimate = gtsam.Values()
|
||||||
for i in range(len(truth.cameras)):
|
for i in range(len(truth.cameras)):
|
||||||
pose_i = truth.cameras[i].pose()
|
pose_i = truth.cameras[i].pose()
|
||||||
initialEstimate.insert(symbol(ord('x'), i), pose_i)
|
initialEstimate.insert(X(i), pose_i)
|
||||||
for j in range(len(truth.points)):
|
for j in range(len(truth.points)):
|
||||||
point_j = truth.points[j]
|
point_j = truth.points[j]
|
||||||
initialEstimate.insert(symbol(ord('p'), j), point_j)
|
initialEstimate.insert(P(j), point_j)
|
||||||
|
|
||||||
# Optimization
|
# Optimization
|
||||||
optimizer = gtsam.LevenbergMarquardtOptimizer(graph, initialEstimate)
|
optimizer = gtsam.LevenbergMarquardtOptimizer(graph, initialEstimate)
|
||||||
|
@ -66,16 +67,16 @@ class TestSFMExample(GtsamTestCase):
|
||||||
|
|
||||||
# Marginalization
|
# Marginalization
|
||||||
marginals = gtsam.Marginals(graph, result)
|
marginals = gtsam.Marginals(graph, result)
|
||||||
marginals.marginalCovariance(symbol(ord('p'), 0))
|
marginals.marginalCovariance(P(0))
|
||||||
marginals.marginalCovariance(symbol(ord('x'), 0))
|
marginals.marginalCovariance(X(0))
|
||||||
|
|
||||||
# Check optimized results, should be equal to ground truth
|
# Check optimized results, should be equal to ground truth
|
||||||
for i in range(len(truth.cameras)):
|
for i in range(len(truth.cameras)):
|
||||||
pose_i = result.atPose3(symbol(ord('x'), i))
|
pose_i = result.atPose3(X(i))
|
||||||
self.gtsamAssertEquals(pose_i, truth.cameras[i].pose(), 1e-5)
|
self.gtsamAssertEquals(pose_i, truth.cameras[i].pose(), 1e-5)
|
||||||
|
|
||||||
for j in range(len(truth.points)):
|
for j in range(len(truth.points)):
|
||||||
point_j = result.atPoint3(symbol(ord('p'), j))
|
point_j = result.atPoint3(P(j))
|
||||||
self.gtsamAssertEquals(point_j, truth.points[j], 1e-5)
|
self.gtsamAssertEquals(point_j, truth.points[j], 1e-5)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -43,8 +43,11 @@ class TestScenario(GtsamTestCase):
|
||||||
# R = v/w, so test if loop crests at 2*R
|
# R = v/w, so test if loop crests at 2*R
|
||||||
R = v / w
|
R = v / w
|
||||||
T30 = scenario.pose(T)
|
T30 = scenario.pose(T)
|
||||||
|
xyz = T30.rotation().xyz()
|
||||||
|
if xyz[0] < 0:
|
||||||
|
xyz = -xyz
|
||||||
np.testing.assert_almost_equal(
|
np.testing.assert_almost_equal(
|
||||||
np.array([math.pi, 0, math.pi]), T30.rotation().xyz())
|
np.array([math.pi, 0, math.pi]), xyz)
|
||||||
self.gtsamAssertEquals(gtsam.Point3(
|
self.gtsamAssertEquals(gtsam.Point3(
|
||||||
0, 0, 2.0 * R), T30.translation(), 1e-9)
|
0, 0, 2.0 * R), T30.translation(), 1e-9)
|
||||||
|
|
||||||
|
|
|
@ -5,7 +5,7 @@ All Rights Reserved
|
||||||
|
|
||||||
See LICENSE for the license information
|
See LICENSE for the license information
|
||||||
|
|
||||||
PinholeCameraCal3_S2 unit tests.
|
SimpleCamera unit tests.
|
||||||
Author: Frank Dellaert & Duy Nguyen Ta (Python)
|
Author: Frank Dellaert & Duy Nguyen Ta (Python)
|
||||||
"""
|
"""
|
||||||
import math
|
import math
|
||||||
|
@ -14,7 +14,7 @@ import unittest
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
|
||||||
import gtsam
|
import gtsam
|
||||||
from gtsam import Cal3_S2, Point3, Pose2, Pose3, Rot3, PinholeCameraCal3_S2
|
from gtsam import Cal3_S2, Point3, Pose2, Pose3, Rot3, SimpleCamera
|
||||||
from gtsam.utils.test_case import GtsamTestCase
|
from gtsam.utils.test_case import GtsamTestCase
|
||||||
|
|
||||||
K = Cal3_S2(625, 625, 0, 0, 0)
|
K = Cal3_S2(625, 625, 0, 0, 0)
|
||||||
|
@ -23,14 +23,14 @@ class TestSimpleCamera(GtsamTestCase):
|
||||||
|
|
||||||
def test_constructor(self):
|
def test_constructor(self):
|
||||||
pose1 = Pose3(Rot3(np.diag([1, -1, -1])), Point3(0, 0, 0.5))
|
pose1 = Pose3(Rot3(np.diag([1, -1, -1])), Point3(0, 0, 0.5))
|
||||||
camera = PinholeCameraCal3_S2(pose1, K)
|
camera = SimpleCamera(pose1, K)
|
||||||
self.gtsamAssertEquals(camera.calibration(), K, 1e-9)
|
self.gtsamAssertEquals(camera.calibration(), K, 1e-9)
|
||||||
self.gtsamAssertEquals(camera.pose(), pose1, 1e-9)
|
self.gtsamAssertEquals(camera.pose(), pose1, 1e-9)
|
||||||
|
|
||||||
def test_level2(self):
|
def test_level2(self):
|
||||||
# Create a level camera, looking in Y-direction
|
# Create a level camera, looking in Y-direction
|
||||||
pose2 = Pose2(0.4,0.3,math.pi/2.0)
|
pose2 = Pose2(0.4,0.3,math.pi/2.0)
|
||||||
camera = PinholeCameraCal3_S2.Level(K, pose2, 0.1)
|
camera = SimpleCamera.Level(K, pose2, 0.1)
|
||||||
|
|
||||||
# expected
|
# expected
|
||||||
x = Point3(1,0,0)
|
x = Point3(1,0,0)
|
||||||
|
|
|
@ -28,11 +28,11 @@ class TestStereoVOExample(GtsamTestCase):
|
||||||
# - No noise on measurements
|
# - No noise on measurements
|
||||||
|
|
||||||
## Create keys for variables
|
## Create keys for variables
|
||||||
x1 = symbol(ord('x'),1)
|
x1 = symbol('x',1)
|
||||||
x2 = symbol(ord('x'),2)
|
x2 = symbol('x',2)
|
||||||
l1 = symbol(ord('l'),1)
|
l1 = symbol('l',1)
|
||||||
l2 = symbol(ord('l'),2)
|
l2 = symbol('l',2)
|
||||||
l3 = symbol(ord('l'),3)
|
l3 = symbol('l',3)
|
||||||
|
|
||||||
## Create graph container and add factors to it
|
## Create graph container and add factors to it
|
||||||
graph = gtsam.NonlinearFactorGraph()
|
graph = gtsam.NonlinearFactorGraph()
|
||||||
|
@ -44,7 +44,7 @@ class TestStereoVOExample(GtsamTestCase):
|
||||||
## Create realistic calibration and measurement noise model
|
## Create realistic calibration and measurement noise model
|
||||||
# format: fx fy skew cx cy baseline
|
# format: fx fy skew cx cy baseline
|
||||||
K = gtsam.Cal3_S2Stereo(1000, 1000, 0, 320, 240, 0.2)
|
K = gtsam.Cal3_S2Stereo(1000, 1000, 0, 320, 240, 0.2)
|
||||||
stereo_model = gtsam.noiseModel_Diagonal.Sigmas(np.array([1.0, 1.0, 1.0]))
|
stereo_model = gtsam.noiseModel.Diagonal.Sigmas(np.array([1.0, 1.0, 1.0]))
|
||||||
|
|
||||||
## Add measurements
|
## Add measurements
|
||||||
# pose 1
|
# pose 1
|
||||||
|
|
|
@ -0,0 +1,80 @@
|
||||||
|
"""
|
||||||
|
GTSAM Copyright 2010-2019, Georgia Tech Research Corporation,
|
||||||
|
Atlanta, Georgia 30332-0415
|
||||||
|
All Rights Reserved
|
||||||
|
|
||||||
|
See LICENSE for the license information
|
||||||
|
|
||||||
|
Test Triangulation
|
||||||
|
Author: Frank Dellaert & Fan Jiang (Python)
|
||||||
|
"""
|
||||||
|
import unittest
|
||||||
|
|
||||||
|
import numpy as np
|
||||||
|
|
||||||
|
import gtsam as g
|
||||||
|
from gtsam.utils.test_case import GtsamTestCase
|
||||||
|
from gtsam import Cal3_S2, Cal3Bundler, Rot3, Pose3, \
|
||||||
|
PinholeCameraCal3_S2, Point3, Point2Vector, Pose3Vector, triangulatePoint3
|
||||||
|
|
||||||
|
class TestVisualISAMExample(GtsamTestCase):
|
||||||
|
def test_TriangulationExample(self):
|
||||||
|
# Some common constants
|
||||||
|
sharedCal = Cal3_S2(1500, 1200, 0, 640, 480)
|
||||||
|
|
||||||
|
# Looking along X-axis, 1 meter above ground plane (x-y)
|
||||||
|
upright = Rot3.Ypr(-np.pi / 2, 0., -np.pi / 2)
|
||||||
|
pose1 = Pose3(upright, Point3(0, 0, 1))
|
||||||
|
camera1 = PinholeCameraCal3_S2(pose1, sharedCal)
|
||||||
|
|
||||||
|
# create second camera 1 meter to the right of first camera
|
||||||
|
pose2 = pose1.compose(Pose3(Rot3(), Point3(1, 0, 0)))
|
||||||
|
camera2 = PinholeCameraCal3_S2(pose2, sharedCal)
|
||||||
|
|
||||||
|
# landmark ~5 meters infront of camera
|
||||||
|
landmark = Point3(5, 0.5, 1.2)
|
||||||
|
|
||||||
|
# 1. Project two landmarks into two cameras and triangulate
|
||||||
|
z1 = camera1.project(landmark)
|
||||||
|
z2 = camera2.project(landmark)
|
||||||
|
|
||||||
|
# twoPoses
|
||||||
|
poses = Pose3Vector()
|
||||||
|
measurements = Point2Vector()
|
||||||
|
|
||||||
|
poses.append(pose1)
|
||||||
|
poses.append(pose2)
|
||||||
|
measurements.append(z1)
|
||||||
|
measurements.append(z2)
|
||||||
|
|
||||||
|
optimize = True
|
||||||
|
rank_tol = 1e-9
|
||||||
|
|
||||||
|
triangulated_landmark = triangulatePoint3(poses,sharedCal, measurements, rank_tol, optimize)
|
||||||
|
self.gtsamAssertEquals(landmark, triangulated_landmark,1e-9)
|
||||||
|
|
||||||
|
# 2. Add some noise and try again: result should be ~ (4.995, 0.499167, 1.19814)
|
||||||
|
measurements = Point2Vector()
|
||||||
|
measurements.append(z1 - np.array([0.1, 0.5]))
|
||||||
|
measurements.append(z2 - np.array([-0.2, 0.3]))
|
||||||
|
|
||||||
|
triangulated_landmark = triangulatePoint3(poses,sharedCal, measurements, rank_tol, optimize)
|
||||||
|
self.gtsamAssertEquals(landmark, triangulated_landmark,1e-2)
|
||||||
|
#
|
||||||
|
# # two Poses with Bundler Calibration
|
||||||
|
# bundlerCal = Cal3Bundler(1500, 0, 0, 640, 480)
|
||||||
|
# camera1 = PinholeCameraCal3Bundler(pose1, bundlerCal)
|
||||||
|
# camera2 = PinholeCameraCal3Bundler(pose2, bundlerCal)
|
||||||
|
#
|
||||||
|
# z1 = camera1.project(landmark)
|
||||||
|
# z2 = camera2.project(landmark)
|
||||||
|
#
|
||||||
|
# measurements = Point2Vector()
|
||||||
|
# measurements.append(z1)
|
||||||
|
# measurements.append(z2)
|
||||||
|
#
|
||||||
|
# triangulated_landmark = triangulatePoint3(poses,bundlerCal, measurements, rank_tol, optimize)
|
||||||
|
# self.gtsamAssertEquals(landmark, triangulated_landmark,1e-9)
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
unittest.main()
|
|
@ -15,8 +15,7 @@ import numpy as np
|
||||||
|
|
||||||
import gtsam
|
import gtsam
|
||||||
from gtsam import (Cal3_S2, Cal3Bundler, Cal3DS2, EssentialMatrix, Point2,
|
from gtsam import (Cal3_S2, Cal3Bundler, Cal3DS2, EssentialMatrix, Point2,
|
||||||
Point3, Pose2, Pose3, Rot2, Rot3, Unit3, Values,
|
Point3, Pose2, Pose3, Rot2, Rot3, Unit3, Values, imuBias)
|
||||||
imuBias_ConstantBias)
|
|
||||||
from gtsam.utils.test_case import GtsamTestCase
|
from gtsam.utils.test_case import GtsamTestCase
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,7 +36,7 @@ class TestValues(GtsamTestCase):
|
||||||
values.insert(7, Cal3DS2())
|
values.insert(7, Cal3DS2())
|
||||||
values.insert(8, Cal3Bundler())
|
values.insert(8, Cal3Bundler())
|
||||||
values.insert(9, E)
|
values.insert(9, E)
|
||||||
values.insert(10, imuBias_ConstantBias())
|
values.insert(10, imuBias.ConstantBias())
|
||||||
|
|
||||||
# Special cases for Vectors and Matrices
|
# Special cases for Vectors and Matrices
|
||||||
# Note that gtsam's Eigen Vectors and Matrices requires double-precision
|
# Note that gtsam's Eigen Vectors and Matrices requires double-precision
|
||||||
|
@ -70,8 +69,8 @@ class TestValues(GtsamTestCase):
|
||||||
self.gtsamAssertEquals(values.atCal3DS2(7), Cal3DS2(), tol)
|
self.gtsamAssertEquals(values.atCal3DS2(7), Cal3DS2(), tol)
|
||||||
self.gtsamAssertEquals(values.atCal3Bundler(8), Cal3Bundler(), tol)
|
self.gtsamAssertEquals(values.atCal3Bundler(8), Cal3Bundler(), tol)
|
||||||
self.gtsamAssertEquals(values.atEssentialMatrix(9), E, tol)
|
self.gtsamAssertEquals(values.atEssentialMatrix(9), E, tol)
|
||||||
self.gtsamAssertEquals(values.atimuBias_ConstantBias(
|
self.gtsamAssertEquals(values.atConstantBias(
|
||||||
10), imuBias_ConstantBias(), tol)
|
10), imuBias.ConstantBias(), tol)
|
||||||
|
|
||||||
# special cases for Vector and Matrix:
|
# special cases for Vector and Matrix:
|
||||||
actualVector = values.atVector(11)
|
actualVector = values.atVector(11)
|
||||||
|
|
|
@ -46,11 +46,11 @@ class TestVisualISAMExample(GtsamTestCase):
|
||||||
isam, result = visual_isam.step(data, isam, result, truth, currentPose)
|
isam, result = visual_isam.step(data, isam, result, truth, currentPose)
|
||||||
|
|
||||||
for i in range(len(truth.cameras)):
|
for i in range(len(truth.cameras)):
|
||||||
pose_i = result.atPose3(symbol(ord('x'), i))
|
pose_i = result.atPose3(symbol('x', i))
|
||||||
self.gtsamAssertEquals(pose_i, truth.cameras[i].pose(), 1e-5)
|
self.gtsamAssertEquals(pose_i, truth.cameras[i].pose(), 1e-5)
|
||||||
|
|
||||||
for j in range(len(truth.points)):
|
for j in range(len(truth.points)):
|
||||||
point_j = result.atPoint3(symbol(ord('l'), j))
|
point_j = result.atPoint3(symbol('l', j))
|
||||||
self.gtsamAssertEquals(point_j, truth.points[j], 1e-5)
|
self.gtsamAssertEquals(point_j, truth.points[j], 1e-5)
|
||||||
|
|
||||||
if __name__ == "__main__":
|
if __name__ == "__main__":
|
||||||
|
|
|
@ -15,7 +15,7 @@ from __future__ import print_function
|
||||||
import unittest
|
import unittest
|
||||||
|
|
||||||
import gtsam
|
import gtsam
|
||||||
from gtsam import BetweenFactorPose3, BetweenFactorPose3s
|
from gtsam import BetweenFactorPose3
|
||||||
from gtsam.utils.test_case import GtsamTestCase
|
from gtsam.utils.test_case import GtsamTestCase
|
||||||
|
|
||||||
|
|
||||||
|
@ -37,8 +37,8 @@ class TestDataset(GtsamTestCase):
|
||||||
def test_parse3Dfactors(self):
|
def test_parse3Dfactors(self):
|
||||||
"""Test parsing into data structure."""
|
"""Test parsing into data structure."""
|
||||||
factors = gtsam.parse3DFactors(self.pose3_example_g2o_file)
|
factors = gtsam.parse3DFactors(self.pose3_example_g2o_file)
|
||||||
self.assertEqual(factors.size(), 6)
|
self.assertEqual(len(factors), 6)
|
||||||
self.assertIsInstance(factors.at(0), BetweenFactorPose3)
|
self.assertIsInstance(factors[0], BetweenFactorPose3)
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -24,7 +24,7 @@ class TestValues(GtsamTestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
|
||||||
model = gtsam.noiseModel_Isotropic.Sigma(6, 0.1)
|
model = gtsam.noiseModel.Isotropic.Sigma(6, 0.1)
|
||||||
|
|
||||||
# We consider a small graph:
|
# We consider a small graph:
|
||||||
# symbolic FG
|
# symbolic FG
|
||||||
|
@ -64,7 +64,6 @@ class TestValues(GtsamTestCase):
|
||||||
|
|
||||||
def test_orientations(self):
|
def test_orientations(self):
|
||||||
pose3Graph = gtsam.InitializePose3.buildPose3graph(self.graph)
|
pose3Graph = gtsam.InitializePose3.buildPose3graph(self.graph)
|
||||||
|
|
||||||
initial = gtsam.InitializePose3.computeOrientationsChordal(pose3Graph)
|
initial = gtsam.InitializePose3.computeOrientationsChordal(pose3Graph)
|
||||||
|
|
||||||
# comparison is up to M_PI, that's why we add some multiples of 2*M_PI
|
# comparison is up to M_PI, that's why we add some multiples of 2*M_PI
|
||||||
|
@ -77,7 +76,7 @@ class TestValues(GtsamTestCase):
|
||||||
g2oFile = gtsam.findExampleDataFile("pose3example-grid")
|
g2oFile = gtsam.findExampleDataFile("pose3example-grid")
|
||||||
is3D = True
|
is3D = True
|
||||||
inputGraph, expectedValues = gtsam.readG2o(g2oFile, is3D)
|
inputGraph, expectedValues = gtsam.readG2o(g2oFile, is3D)
|
||||||
priorModel = gtsam.noiseModel_Unit.Create(6)
|
priorModel = gtsam.noiseModel.Unit.Create(6)
|
||||||
inputGraph.add(gtsam.PriorFactorPose3(0, Pose3(), priorModel))
|
inputGraph.add(gtsam.PriorFactorPose3(0, Pose3(), priorModel))
|
||||||
|
|
||||||
initial = gtsam.InitializePose3.initialize(inputGraph)
|
initial = gtsam.InitializePose3.initialize(inputGraph)
|
||||||
|
|
|
@ -21,7 +21,7 @@ from gtsam.utils.test_case import GtsamTestCase
|
||||||
from gtsam.utils.logging_optimizer import gtsam_optimize
|
from gtsam.utils.logging_optimizer import gtsam_optimize
|
||||||
|
|
||||||
KEY = 0
|
KEY = 0
|
||||||
MODEL = gtsam.noiseModel_Unit.Create(3)
|
MODEL = gtsam.noiseModel.Unit.Create(3)
|
||||||
|
|
||||||
|
|
||||||
class TestOptimizeComet(GtsamTestCase):
|
class TestOptimizeComet(GtsamTestCase):
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
import gtsam
|
import gtsam
|
||||||
|
import math
|
||||||
import numpy as np
|
import numpy as np
|
||||||
from math import pi, cos, sin
|
from math import pi
|
||||||
|
|
||||||
|
|
||||||
def circlePose3(numPoses=8, radius=1.0, symbolChar=0):
|
def circlePose3(numPoses=8, radius=1.0, symbolChar='\0'):
|
||||||
"""
|
"""
|
||||||
circlePose3 generates a set of poses in a circle. This function
|
circlePose3 generates a set of poses in a circle. This function
|
||||||
returns those poses inside a gtsam.Values object, with sequential
|
returns those poses inside a gtsam.Values object, with sequential
|
||||||
|
@ -18,10 +19,6 @@ def circlePose3(numPoses=8, radius=1.0, symbolChar=0):
|
||||||
Vehicle at p0 is looking towards y axis (X-axis points towards world y)
|
Vehicle at p0 is looking towards y axis (X-axis points towards world y)
|
||||||
"""
|
"""
|
||||||
|
|
||||||
# Force symbolChar to be a single character
|
|
||||||
if type(symbolChar) is str:
|
|
||||||
symbolChar = ord(symbolChar[0])
|
|
||||||
|
|
||||||
values = gtsam.Values()
|
values = gtsam.Values()
|
||||||
theta = 0.0
|
theta = 0.0
|
||||||
dtheta = 2 * pi / numPoses
|
dtheta = 2 * pi / numPoses
|
||||||
|
@ -29,7 +26,7 @@ def circlePose3(numPoses=8, radius=1.0, symbolChar=0):
|
||||||
np.array([[0., 1., 0.], [1., 0., 0.], [0., 0., -1.]], order='F'))
|
np.array([[0., 1., 0.], [1., 0., 0.], [0., 0., -1.]], order='F'))
|
||||||
for i in range(numPoses):
|
for i in range(numPoses):
|
||||||
key = gtsam.symbol(symbolChar, i)
|
key = gtsam.symbol(symbolChar, i)
|
||||||
gti = gtsam.Point3(radius * cos(theta), radius * sin(theta), 0)
|
gti = gtsam.Point3(radius * math.cos(theta), radius * math.sin(theta), 0)
|
||||||
oRi = gtsam.Rot3.Yaw(
|
oRi = gtsam.Rot3.Yaw(
|
||||||
-theta) # negative yaw goes counterclockwise, with Z down !
|
-theta) # negative yaw goes counterclockwise, with Z down !
|
||||||
gTi = gtsam.Pose3(gRo.compose(oRi), gti)
|
gTi = gtsam.Pose3(gRo.compose(oRi), gti)
|
||||||
|
|
|
@ -109,7 +109,7 @@ def plot_pose2_on_axes(axes, pose, axis_length=0.1, covariance=None):
|
||||||
# get rotation and translation (center)
|
# get rotation and translation (center)
|
||||||
gRp = pose.rotation().matrix() # rotation from pose to global
|
gRp = pose.rotation().matrix() # rotation from pose to global
|
||||||
t = pose.translation()
|
t = pose.translation()
|
||||||
origin = np.array([t.x(), t.y()])
|
origin = t
|
||||||
|
|
||||||
# draw the camera axes
|
# draw the camera axes
|
||||||
x_axis = origin + gRp[:, 0] * axis_length
|
x_axis = origin + gRp[:, 0] * axis_length
|
||||||
|
@ -169,9 +169,9 @@ def plot_point3_on_axes(axes, point, linespec, P=None):
|
||||||
linespec (string): String representing formatting options for Matplotlib.
|
linespec (string): String representing formatting options for Matplotlib.
|
||||||
P (numpy.ndarray): Marginal covariance matrix to plot the uncertainty of the estimation.
|
P (numpy.ndarray): Marginal covariance matrix to plot the uncertainty of the estimation.
|
||||||
"""
|
"""
|
||||||
axes.plot([point.x()], [point.y()], [point.z()], linespec)
|
axes.plot([point[0]], [point[1]], [point[2]], linespec)
|
||||||
if P is not None:
|
if P is not None:
|
||||||
plot_covariance_ellipse_3d(axes, point.vector(), P)
|
plot_covariance_ellipse_3d(axes, point, P)
|
||||||
|
|
||||||
|
|
||||||
def plot_point3(fignum, point, linespec, P=None,
|
def plot_point3(fignum, point, linespec, P=None,
|
||||||
|
@ -221,9 +221,8 @@ def plot_3d_points(fignum, values, linespec="g*", marginals=None,
|
||||||
keys = values.keys()
|
keys = values.keys()
|
||||||
|
|
||||||
# Plot points and covariance matrices
|
# Plot points and covariance matrices
|
||||||
for i in range(keys.size()):
|
for key in keys:
|
||||||
try:
|
try:
|
||||||
key = keys.at(i)
|
|
||||||
point = values.atPoint3(key)
|
point = values.atPoint3(key)
|
||||||
if marginals is not None:
|
if marginals is not None:
|
||||||
covariance = marginals.marginalCovariance(key)
|
covariance = marginals.marginalCovariance(key)
|
||||||
|
@ -253,7 +252,7 @@ def plot_pose3_on_axes(axes, pose, axis_length=0.1, P=None, scale=1):
|
||||||
"""
|
"""
|
||||||
# get rotation and translation (center)
|
# get rotation and translation (center)
|
||||||
gRp = pose.rotation().matrix() # rotation from pose to global
|
gRp = pose.rotation().matrix() # rotation from pose to global
|
||||||
origin = pose.translation().vector()
|
origin = pose.translation()
|
||||||
|
|
||||||
# draw the camera axes
|
# draw the camera axes
|
||||||
x_axis = origin + gRp[:, 0] * axis_length
|
x_axis = origin + gRp[:, 0] * axis_length
|
||||||
|
@ -319,19 +318,17 @@ def plot_trajectory(fignum, values, scale=1, marginals=None,
|
||||||
title (string): The title of the plot.
|
title (string): The title of the plot.
|
||||||
axis_labels (iterable[string]): List of axis labels to set.
|
axis_labels (iterable[string]): List of axis labels to set.
|
||||||
"""
|
"""
|
||||||
pose3Values = gtsam.utilities_allPose3s(values)
|
pose3Values = gtsam.utilities.allPose3s(values)
|
||||||
keys = gtsam.KeyVector(pose3Values.keys())
|
keys = gtsam.KeyVector(pose3Values.keys())
|
||||||
lastIndex = None
|
lastKey = None
|
||||||
|
|
||||||
for i in range(keys.size()):
|
for key in keys:
|
||||||
key = keys.at(i)
|
|
||||||
try:
|
try:
|
||||||
pose = pose3Values.atPose3(key)
|
pose = pose3Values.atPose3(key)
|
||||||
except:
|
except:
|
||||||
print("Warning: no Pose3 at key: {0}".format(key))
|
print("Warning: no Pose3 at key: {0}".format(key))
|
||||||
|
|
||||||
if lastIndex is not None:
|
if lastKey is not None:
|
||||||
lastKey = keys.at(lastIndex)
|
|
||||||
try:
|
try:
|
||||||
lastPose = pose3Values.atPose3(lastKey)
|
lastPose = pose3Values.atPose3(lastKey)
|
||||||
except:
|
except:
|
||||||
|
@ -346,11 +343,10 @@ def plot_trajectory(fignum, values, scale=1, marginals=None,
|
||||||
fig = plot_pose3(fignum, lastPose, P=covariance,
|
fig = plot_pose3(fignum, lastPose, P=covariance,
|
||||||
axis_length=scale, axis_labels=axis_labels)
|
axis_length=scale, axis_labels=axis_labels)
|
||||||
|
|
||||||
lastIndex = i
|
lastKey = key
|
||||||
|
|
||||||
# Draw final pose
|
# Draw final pose
|
||||||
if lastIndex is not None:
|
if lastKey is not None:
|
||||||
lastKey = keys.at(lastIndex)
|
|
||||||
try:
|
try:
|
||||||
lastPose = pose3Values.atPose3(lastKey)
|
lastPose = pose3Values.atPose3(lastKey)
|
||||||
if marginals:
|
if marginals:
|
||||||
|
@ -366,3 +362,40 @@ def plot_trajectory(fignum, values, scale=1, marginals=None,
|
||||||
|
|
||||||
fig.suptitle(title)
|
fig.suptitle(title)
|
||||||
fig.canvas.set_window_title(title.lower())
|
fig.canvas.set_window_title(title.lower())
|
||||||
|
|
||||||
|
|
||||||
|
def plot_incremental_trajectory(fignum, values, start=0,
|
||||||
|
scale=1, marginals=None,
|
||||||
|
time_interval=0.0):
|
||||||
|
"""
|
||||||
|
Incrementally plot a complete 3D trajectory using poses in `values`.
|
||||||
|
|
||||||
|
Args:
|
||||||
|
fignum (int): Integer representing the figure number to use for plotting.
|
||||||
|
values (gtsam.Values): Values dict containing the poses.
|
||||||
|
start (int): Starting index to start plotting from.
|
||||||
|
scale (float): Value to scale the poses by.
|
||||||
|
marginals (gtsam.Marginals): Marginalized probability values of the estimation.
|
||||||
|
Used to plot uncertainty bounds.
|
||||||
|
time_interval (float): Time in seconds to pause between each rendering.
|
||||||
|
Used to create animation effect.
|
||||||
|
"""
|
||||||
|
fig = plt.figure(fignum)
|
||||||
|
axes = fig.gca(projection='3d')
|
||||||
|
|
||||||
|
pose3Values = gtsam.utilities.allPose3s(values)
|
||||||
|
keys = gtsam.KeyVector(pose3Values.keys())
|
||||||
|
|
||||||
|
for key in keys[start:]:
|
||||||
|
if values.exists(key):
|
||||||
|
pose_i = values.atPose3(key)
|
||||||
|
plot_pose3(fignum, pose_i, scale)
|
||||||
|
|
||||||
|
# Update the plot space to encompass all plotted points
|
||||||
|
axes.autoscale()
|
||||||
|
|
||||||
|
# Set the 3 axes equal
|
||||||
|
set_axes_equal(fignum)
|
||||||
|
|
||||||
|
# Pause for a fixed amount of seconds
|
||||||
|
plt.pause(time_interval)
|
||||||
|
|
|
@ -21,6 +21,10 @@ class GtsamTestCase(unittest.TestCase):
|
||||||
Keyword Arguments:
|
Keyword Arguments:
|
||||||
tol {float} -- tolerance passed to 'equals', default 1e-9
|
tol {float} -- tolerance passed to 'equals', default 1e-9
|
||||||
"""
|
"""
|
||||||
|
import numpy
|
||||||
|
if isinstance(expected, numpy.ndarray):
|
||||||
|
equal = numpy.allclose(actual, expected, atol=tol)
|
||||||
|
else:
|
||||||
equal = actual.equals(expected, tol)
|
equal = actual.equals(expected, tol)
|
||||||
if not equal:
|
if not equal:
|
||||||
raise self.failureException(
|
raise self.failureException(
|
||||||
|
|
|
@ -1,9 +1,10 @@
|
||||||
from __future__ import print_function
|
from __future__ import print_function
|
||||||
|
|
||||||
import numpy as np
|
import numpy as np
|
||||||
|
import math
|
||||||
|
from math import pi
|
||||||
import gtsam
|
import gtsam
|
||||||
from gtsam import Cal3_S2, PinholeCameraCal3_S2, Point2, Point3, Pose3
|
from gtsam import Point3, Pose3, PinholeCameraCal3_S2, Cal3_S2
|
||||||
|
|
||||||
|
|
||||||
class Options:
|
class Options:
|
||||||
|
@ -30,8 +31,8 @@ class GroundTruth:
|
||||||
|
|
||||||
def __init__(self, K=Cal3_S2(), nrCameras=3, nrPoints=4):
|
def __init__(self, K=Cal3_S2(), nrCameras=3, nrPoints=4):
|
||||||
self.K = K
|
self.K = K
|
||||||
self.cameras = [gtsam.Pose3()] * nrCameras
|
self.cameras = [Pose3()] * nrCameras
|
||||||
self.points = [gtsam.Point3(0, 0, 0)] * nrPoints
|
self.points = [Point3(0, 0, 0)] * nrPoints
|
||||||
|
|
||||||
def print_(self, s=""):
|
def print_(self, s=""):
|
||||||
print(s)
|
print(s)
|
||||||
|
@ -55,20 +56,20 @@ class Data:
|
||||||
|
|
||||||
def __init__(self, K=Cal3_S2(), nrCameras=3, nrPoints=4):
|
def __init__(self, K=Cal3_S2(), nrCameras=3, nrPoints=4):
|
||||||
self.K = K
|
self.K = K
|
||||||
self.Z = [x[:] for x in [[Point2()] * nrPoints] * nrCameras]
|
self.Z = [x[:] for x in [[gtsam.Point2()] * nrPoints] * nrCameras]
|
||||||
self.J = [x[:] for x in [[0] * nrPoints] * nrCameras]
|
self.J = [x[:] for x in [[0] * nrPoints] * nrCameras]
|
||||||
self.odometry = [Pose3()] * nrCameras
|
self.odometry = [Pose3()] * nrCameras
|
||||||
|
|
||||||
# Set Noise parameters
|
# Set Noise parameters
|
||||||
self.noiseModels = Data.NoiseModels()
|
self.noiseModels = Data.NoiseModels()
|
||||||
self.noiseModels.posePrior = gtsam.noiseModel_Diagonal.Sigmas(
|
self.noiseModels.posePrior = gtsam.noiseModel.Diagonal.Sigmas(
|
||||||
np.array([0.001, 0.001, 0.001, 0.1, 0.1, 0.1]))
|
np.array([0.001, 0.001, 0.001, 0.1, 0.1, 0.1]))
|
||||||
# noiseModels.odometry = gtsam.noiseModel_Diagonal.Sigmas(
|
# noiseModels.odometry = gtsam.noiseModel.Diagonal.Sigmas(
|
||||||
# np.array([0.001,0.001,0.001,0.1,0.1,0.1]))
|
# np.array([0.001,0.001,0.001,0.1,0.1,0.1]))
|
||||||
self.noiseModels.odometry = gtsam.noiseModel_Diagonal.Sigmas(
|
self.noiseModels.odometry = gtsam.noiseModel.Diagonal.Sigmas(
|
||||||
np.array([0.05, 0.05, 0.05, 0.2, 0.2, 0.2]))
|
np.array([0.05, 0.05, 0.05, 0.2, 0.2, 0.2]))
|
||||||
self.noiseModels.pointPrior = gtsam.noiseModel_Isotropic.Sigma(3, 0.1)
|
self.noiseModels.pointPrior = gtsam.noiseModel.Isotropic.Sigma(3, 0.1)
|
||||||
self.noiseModels.measurement = gtsam.noiseModel_Isotropic.Sigma(2, 1.0)
|
self.noiseModels.measurement = gtsam.noiseModel.Isotropic.Sigma(2, 1.0)
|
||||||
|
|
||||||
|
|
||||||
def generate_data(options):
|
def generate_data(options):
|
||||||
|
@ -84,8 +85,8 @@ def generate_data(options):
|
||||||
if options.triangle: # Create a triangle target, just 3 points on a plane
|
if options.triangle: # Create a triangle target, just 3 points on a plane
|
||||||
r = 10
|
r = 10
|
||||||
for j in range(len(truth.points)):
|
for j in range(len(truth.points)):
|
||||||
theta = j * 2 * np.pi / nrPoints
|
theta = j * 2 * pi / nrPoints
|
||||||
truth.points[j] = Point3(r * np.cos(theta), r * np.sin(theta), 0)
|
truth.points[j] = Point3(r * math.cos(theta), r * math.sin(theta), 0)
|
||||||
else: # 3D landmarks as vertices of a cube
|
else: # 3D landmarks as vertices of a cube
|
||||||
truth.points = [
|
truth.points = [
|
||||||
Point3(10, 10, 10), Point3(-10, 10, 10),
|
Point3(10, 10, 10), Point3(-10, 10, 10),
|
||||||
|
@ -98,11 +99,11 @@ def generate_data(options):
|
||||||
height = 10
|
height = 10
|
||||||
r = 40
|
r = 40
|
||||||
for i in range(options.nrCameras):
|
for i in range(options.nrCameras):
|
||||||
theta = i * 2 * np.pi / options.nrCameras
|
theta = i * 2 * pi / options.nrCameras
|
||||||
t = gtsam.Point3(r * np.cos(theta), r * np.sin(theta), height)
|
t = Point3(r * math.cos(theta), r * math.sin(theta), height)
|
||||||
truth.cameras[i] = gtsam.SimpleCamera.Lookat(t,
|
truth.cameras[i] = PinholeCameraCal3_S2.Lookat(t,
|
||||||
gtsam.Point3(0, 0, 0),
|
Point3(0, 0, 0),
|
||||||
gtsam.Point3(0, 0, 1),
|
Point3(0, 0, 1),
|
||||||
truth.K)
|
truth.K)
|
||||||
# Create measurements
|
# Create measurements
|
||||||
for j in range(nrPoints):
|
for j in range(nrPoints):
|
||||||
|
|
|
@ -25,7 +25,7 @@ def initialize(data, truth, options):
|
||||||
newFactors = gtsam.NonlinearFactorGraph()
|
newFactors = gtsam.NonlinearFactorGraph()
|
||||||
initialEstimates = gtsam.Values()
|
initialEstimates = gtsam.Values()
|
||||||
for i in range(2):
|
for i in range(2):
|
||||||
ii = symbol(ord('x'), i)
|
ii = symbol('x', i)
|
||||||
if i == 0:
|
if i == 0:
|
||||||
if options.hardConstraint: # add hard constraint
|
if options.hardConstraint: # add hard constraint
|
||||||
newFactors.add(
|
newFactors.add(
|
||||||
|
@ -41,10 +41,10 @@ def initialize(data, truth, options):
|
||||||
# Add visual measurement factors from two first poses and initialize
|
# Add visual measurement factors from two first poses and initialize
|
||||||
# observed landmarks
|
# observed landmarks
|
||||||
for i in range(2):
|
for i in range(2):
|
||||||
ii = symbol(ord('x'), i)
|
ii = symbol('x', i)
|
||||||
for k in range(len(data.Z[i])):
|
for k in range(len(data.Z[i])):
|
||||||
j = data.J[i][k]
|
j = data.J[i][k]
|
||||||
jj = symbol(ord('l'), j)
|
jj = symbol('l', j)
|
||||||
newFactors.add(
|
newFactors.add(
|
||||||
gtsam.GenericProjectionFactorCal3_S2(data.Z[i][
|
gtsam.GenericProjectionFactorCal3_S2(data.Z[i][
|
||||||
k], data.noiseModels.measurement, ii, jj, data.K))
|
k], data.noiseModels.measurement, ii, jj, data.K))
|
||||||
|
@ -59,8 +59,8 @@ def initialize(data, truth, options):
|
||||||
# Add odometry between frames 0 and 1
|
# Add odometry between frames 0 and 1
|
||||||
newFactors.add(
|
newFactors.add(
|
||||||
gtsam.BetweenFactorPose3(
|
gtsam.BetweenFactorPose3(
|
||||||
symbol(ord('x'), 0),
|
symbol('x', 0),
|
||||||
symbol(ord('x'), 1), data.odometry[1], data.noiseModels.odometry))
|
symbol('x', 1), data.odometry[1], data.noiseModels.odometry))
|
||||||
|
|
||||||
# Update ISAM
|
# Update ISAM
|
||||||
if options.batchInitialization: # Do a full optimize for first two poses
|
if options.batchInitialization: # Do a full optimize for first two poses
|
||||||
|
@ -98,28 +98,28 @@ def step(data, isam, result, truth, currPoseIndex):
|
||||||
odometry = data.odometry[prevPoseIndex]
|
odometry = data.odometry[prevPoseIndex]
|
||||||
newFactors.add(
|
newFactors.add(
|
||||||
gtsam.BetweenFactorPose3(
|
gtsam.BetweenFactorPose3(
|
||||||
symbol(ord('x'), prevPoseIndex),
|
symbol('x', prevPoseIndex),
|
||||||
symbol(ord('x'), currPoseIndex), odometry,
|
symbol('x', currPoseIndex), odometry,
|
||||||
data.noiseModels.odometry))
|
data.noiseModels.odometry))
|
||||||
|
|
||||||
# Add visual measurement factors and initializations as necessary
|
# Add visual measurement factors and initializations as necessary
|
||||||
for k in range(len(data.Z[currPoseIndex])):
|
for k in range(len(data.Z[currPoseIndex])):
|
||||||
zij = data.Z[currPoseIndex][k]
|
zij = data.Z[currPoseIndex][k]
|
||||||
j = data.J[currPoseIndex][k]
|
j = data.J[currPoseIndex][k]
|
||||||
jj = symbol(ord('l'), j)
|
jj = symbol('l', j)
|
||||||
newFactors.add(
|
newFactors.add(
|
||||||
gtsam.GenericProjectionFactorCal3_S2(
|
gtsam.GenericProjectionFactorCal3_S2(
|
||||||
zij, data.noiseModels.measurement,
|
zij, data.noiseModels.measurement,
|
||||||
symbol(ord('x'), currPoseIndex), jj, data.K))
|
symbol('x', currPoseIndex), jj, data.K))
|
||||||
# TODO: initialize with something other than truth
|
# TODO: initialize with something other than truth
|
||||||
if not result.exists(jj) and not initialEstimates.exists(jj):
|
if not result.exists(jj) and not initialEstimates.exists(jj):
|
||||||
lmInit = truth.points[j]
|
lmInit = truth.points[j]
|
||||||
initialEstimates.insert(jj, lmInit)
|
initialEstimates.insert(jj, lmInit)
|
||||||
|
|
||||||
# Initial estimates for the new pose.
|
# Initial estimates for the new pose.
|
||||||
prevPose = result.atPose3(symbol(ord('x'), prevPoseIndex))
|
prevPose = result.atPose3(symbol('x', prevPoseIndex))
|
||||||
initialEstimates.insert(
|
initialEstimates.insert(
|
||||||
symbol(ord('x'), currPoseIndex), prevPose.compose(odometry))
|
symbol('x', currPoseIndex), prevPose.compose(odometry))
|
||||||
|
|
||||||
# Update ISAM
|
# Update ISAM
|
||||||
# figure(1)tic
|
# figure(1)tic
|
||||||
|
|
|
@ -16,16 +16,6 @@ import numpy as np
|
||||||
import gtsam
|
import gtsam
|
||||||
import gtsam_unstable
|
import gtsam_unstable
|
||||||
|
|
||||||
|
|
||||||
def _timestamp_key_value(key, value):
|
|
||||||
"""
|
|
||||||
|
|
||||||
"""
|
|
||||||
return gtsam_unstable.FixedLagSmootherKeyTimestampMapValue(
|
|
||||||
key, value
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def BatchFixedLagSmootherExample():
|
def BatchFixedLagSmootherExample():
|
||||||
"""
|
"""
|
||||||
Runs a batch fixed smoother on an agent with two odometry
|
Runs a batch fixed smoother on an agent with two odometry
|
||||||
|
@ -45,21 +35,21 @@ def BatchFixedLagSmootherExample():
|
||||||
|
|
||||||
# Create a prior on the first pose, placing it at the origin
|
# Create a prior on the first pose, placing it at the origin
|
||||||
prior_mean = gtsam.Pose2(0, 0, 0)
|
prior_mean = gtsam.Pose2(0, 0, 0)
|
||||||
prior_noise = gtsam.noiseModel_Diagonal.Sigmas(np.array([0.3, 0.3, 0.1]))
|
prior_noise = gtsam.noiseModel.Diagonal.Sigmas(np.array([0.3, 0.3, 0.1]))
|
||||||
X1 = 0
|
X1 = 0
|
||||||
new_factors.push_back(gtsam.PriorFactorPose2(X1, prior_mean, prior_noise))
|
new_factors.push_back(gtsam.PriorFactorPose2(X1, prior_mean, prior_noise))
|
||||||
new_values.insert(X1, prior_mean)
|
new_values.insert(X1, prior_mean)
|
||||||
new_timestamps.insert(_timestamp_key_value(X1, 0.0))
|
new_timestamps.insert((X1, 0.0))
|
||||||
|
|
||||||
delta_time = 0.25
|
delta_time = 0.25
|
||||||
time = 0.25
|
time = 0.25
|
||||||
|
|
||||||
while time <= 3.0:
|
while time <= 3.0:
|
||||||
previous_key = 1000 * (time - delta_time)
|
previous_key = int(1000 * (time - delta_time))
|
||||||
current_key = 1000 * time
|
current_key = int(1000 * time)
|
||||||
|
|
||||||
# assign current key to the current timestamp
|
# assign current key to the current timestamp
|
||||||
new_timestamps.insert(_timestamp_key_value(current_key, time))
|
new_timestamps.insert((current_key, time))
|
||||||
|
|
||||||
# Add a guess for this pose to the new values
|
# Add a guess for this pose to the new values
|
||||||
# Assume that the robot moves at 2 m/s. Position is time[s] * 2[m/s]
|
# Assume that the robot moves at 2 m/s. Position is time[s] * 2[m/s]
|
||||||
|
@ -69,14 +59,14 @@ def BatchFixedLagSmootherExample():
|
||||||
# Add odometry factors from two different sources with different error
|
# Add odometry factors from two different sources with different error
|
||||||
# stats
|
# stats
|
||||||
odometry_measurement_1 = gtsam.Pose2(0.61, -0.08, 0.02)
|
odometry_measurement_1 = gtsam.Pose2(0.61, -0.08, 0.02)
|
||||||
odometry_noise_1 = gtsam.noiseModel_Diagonal.Sigmas(
|
odometry_noise_1 = gtsam.noiseModel.Diagonal.Sigmas(
|
||||||
np.array([0.1, 0.1, 0.05]))
|
np.array([0.1, 0.1, 0.05]))
|
||||||
new_factors.push_back(gtsam.BetweenFactorPose2(
|
new_factors.push_back(gtsam.BetweenFactorPose2(
|
||||||
previous_key, current_key, odometry_measurement_1, odometry_noise_1
|
previous_key, current_key, odometry_measurement_1, odometry_noise_1
|
||||||
))
|
))
|
||||||
|
|
||||||
odometry_measurement_2 = gtsam.Pose2(0.47, 0.03, 0.01)
|
odometry_measurement_2 = gtsam.Pose2(0.47, 0.03, 0.01)
|
||||||
odometry_noise_2 = gtsam.noiseModel_Diagonal.Sigmas(
|
odometry_noise_2 = gtsam.noiseModel.Diagonal.Sigmas(
|
||||||
np.array([0.05, 0.05, 0.05]))
|
np.array([0.05, 0.05, 0.05]))
|
||||||
new_factors.push_back(gtsam.BetweenFactorPose2(
|
new_factors.push_back(gtsam.BetweenFactorPose2(
|
||||||
previous_key, current_key, odometry_measurement_2, odometry_noise_2
|
previous_key, current_key, odometry_measurement_2, odometry_noise_2
|
||||||
|
|
|
@ -12,7 +12,7 @@ Author: Frank Dellaert
|
||||||
# pylint: disable=invalid-name, no-name-in-module
|
# pylint: disable=invalid-name, no-name-in-module
|
||||||
|
|
||||||
from gtsam import (LevenbergMarquardtOptimizer, LevenbergMarquardtParams,
|
from gtsam import (LevenbergMarquardtOptimizer, LevenbergMarquardtParams,
|
||||||
NonlinearFactorGraph, Point3, Values, noiseModel_Isotropic)
|
NonlinearFactorGraph, Point3, Values, noiseModel)
|
||||||
from gtsam_unstable import Event, TimeOfArrival, TOAFactor
|
from gtsam_unstable import Event, TimeOfArrival, TOAFactor
|
||||||
|
|
||||||
# units
|
# units
|
||||||
|
@ -64,7 +64,7 @@ def create_graph(microphones, simulatedTOA):
|
||||||
graph = NonlinearFactorGraph()
|
graph = NonlinearFactorGraph()
|
||||||
|
|
||||||
# Create a noise model for the TOA error
|
# Create a noise model for the TOA error
|
||||||
model = noiseModel_Isotropic.Sigma(1, 0.5 * MS)
|
model = noiseModel.Isotropic.Sigma(1, 0.5 * MS)
|
||||||
|
|
||||||
K = len(microphones)
|
K = len(microphones)
|
||||||
key = 0
|
key = 0
|
||||||
|
|
|
@ -16,13 +16,6 @@ import gtsam
|
||||||
import gtsam_unstable
|
import gtsam_unstable
|
||||||
from gtsam.utils.test_case import GtsamTestCase
|
from gtsam.utils.test_case import GtsamTestCase
|
||||||
|
|
||||||
|
|
||||||
def _timestamp_key_value(key, value):
|
|
||||||
return gtsam_unstable.FixedLagSmootherKeyTimestampMapValue(
|
|
||||||
key, value
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
class TestFixedLagSmootherExample(GtsamTestCase):
|
class TestFixedLagSmootherExample(GtsamTestCase):
|
||||||
'''
|
'''
|
||||||
Tests the fixed lag smoother wrapper
|
Tests the fixed lag smoother wrapper
|
||||||
|
@ -47,14 +40,14 @@ class TestFixedLagSmootherExample(GtsamTestCase):
|
||||||
|
|
||||||
# Create a prior on the first pose, placing it at the origin
|
# Create a prior on the first pose, placing it at the origin
|
||||||
prior_mean = gtsam.Pose2(0, 0, 0)
|
prior_mean = gtsam.Pose2(0, 0, 0)
|
||||||
prior_noise = gtsam.noiseModel_Diagonal.Sigmas(
|
prior_noise = gtsam.noiseModel.Diagonal.Sigmas(
|
||||||
np.array([0.3, 0.3, 0.1]))
|
np.array([0.3, 0.3, 0.1]))
|
||||||
X1 = 0
|
X1 = 0
|
||||||
new_factors.push_back(
|
new_factors.push_back(
|
||||||
gtsam.PriorFactorPose2(
|
gtsam.PriorFactorPose2(
|
||||||
X1, prior_mean, prior_noise))
|
X1, prior_mean, prior_noise))
|
||||||
new_values.insert(X1, prior_mean)
|
new_values.insert(X1, prior_mean)
|
||||||
new_timestamps.insert(_timestamp_key_value(X1, 0.0))
|
new_timestamps.insert((X1, 0.0))
|
||||||
|
|
||||||
delta_time = 0.25
|
delta_time = 0.25
|
||||||
time = 0.25
|
time = 0.25
|
||||||
|
@ -80,11 +73,11 @@ class TestFixedLagSmootherExample(GtsamTestCase):
|
||||||
# and its two odometers measure the change. The smoothed
|
# and its two odometers measure the change. The smoothed
|
||||||
# result is then compared to the ground truth
|
# result is then compared to the ground truth
|
||||||
while time <= 3.0:
|
while time <= 3.0:
|
||||||
previous_key = 1000 * (time - delta_time)
|
previous_key = int(1000 * (time - delta_time))
|
||||||
current_key = 1000 * time
|
current_key = int(1000 * time)
|
||||||
|
|
||||||
# assign current key to the current timestamp
|
# assign current key to the current timestamp
|
||||||
new_timestamps.insert(_timestamp_key_value(current_key, time))
|
new_timestamps.insert((current_key, time))
|
||||||
|
|
||||||
# Add a guess for this pose to the new values
|
# Add a guess for this pose to the new values
|
||||||
# Assume that the robot moves at 2 m/s. Position is time[s] *
|
# Assume that the robot moves at 2 m/s. Position is time[s] *
|
||||||
|
@ -95,7 +88,7 @@ class TestFixedLagSmootherExample(GtsamTestCase):
|
||||||
# Add odometry factors from two different sources with different
|
# Add odometry factors from two different sources with different
|
||||||
# error stats
|
# error stats
|
||||||
odometry_measurement_1 = gtsam.Pose2(0.61, -0.08, 0.02)
|
odometry_measurement_1 = gtsam.Pose2(0.61, -0.08, 0.02)
|
||||||
odometry_noise_1 = gtsam.noiseModel_Diagonal.Sigmas(
|
odometry_noise_1 = gtsam.noiseModel.Diagonal.Sigmas(
|
||||||
np.array([0.1, 0.1, 0.05]))
|
np.array([0.1, 0.1, 0.05]))
|
||||||
new_factors.push_back(
|
new_factors.push_back(
|
||||||
gtsam.BetweenFactorPose2(
|
gtsam.BetweenFactorPose2(
|
||||||
|
@ -105,7 +98,7 @@ class TestFixedLagSmootherExample(GtsamTestCase):
|
||||||
odometry_noise_1))
|
odometry_noise_1))
|
||||||
|
|
||||||
odometry_measurement_2 = gtsam.Pose2(0.47, 0.03, 0.01)
|
odometry_measurement_2 = gtsam.Pose2(0.47, 0.03, 0.01)
|
||||||
odometry_noise_2 = gtsam.noiseModel_Diagonal.Sigmas(
|
odometry_noise_2 = gtsam.noiseModel.Diagonal.Sigmas(
|
||||||
np.array([0.05, 0.05, 0.05]))
|
np.array([0.05, 0.05, 0.05]))
|
||||||
new_factors.push_back(
|
new_factors.push_back(
|
||||||
gtsam.BetweenFactorPose2(
|
gtsam.BetweenFactorPose2(
|
||||||
|
|
Loading…
Reference in New Issue