Trajectory Estimation example
parent
880d5b57af
commit
22ddab7921
|
|
@ -48,11 +48,18 @@ gps_model = gtsam.noiseModel.Isotropic.Sigma(1, sigma_gps)
|
||||||
|
|
||||||
|
|
||||||
def error_gps(this: gtsam.CustomFactor, values, jacobians: Optional[List[np.ndarray]], measurement: np.ndarray):
|
def error_gps(this: gtsam.CustomFactor, values, jacobians: Optional[List[np.ndarray]], measurement: np.ndarray):
|
||||||
|
"""GPS Factor error function
|
||||||
|
:param this: gtsam.CustomFactor handle
|
||||||
|
:param values: gtsam.Values
|
||||||
|
:param jacobians: Optional list of Jacobians
|
||||||
|
:param measurement: GPS measurement, to be filled with `partial`
|
||||||
|
:return: the unwhitened error
|
||||||
|
"""
|
||||||
key = this.keys()[0]
|
key = this.keys()[0]
|
||||||
estimate = values.atVector(key)
|
estimate = values.atVector(key)
|
||||||
error = measurement - estimate
|
error = estimate - measurement
|
||||||
if jacobians is not None:
|
if jacobians is not None:
|
||||||
jacobians[0] = -I
|
jacobians[0] = I
|
||||||
|
|
||||||
return error
|
return error
|
||||||
|
|
||||||
|
|
@ -65,11 +72,83 @@ v = gtsam.Values()
|
||||||
for i in range(5):
|
for i in range(5):
|
||||||
v.insert(unknown[i], np.array([0.0]))
|
v.insert(unknown[i], np.array([0.0]))
|
||||||
|
|
||||||
linearized: gtsam.GaussianFactorGraph = factor_graph.linearize(v)
|
params = gtsam.GaussNewtonParams()
|
||||||
print(linearized.at(1))
|
optimizer = gtsam.GaussNewtonOptimizer(factor_graph, v, params)
|
||||||
|
|
||||||
|
result = optimizer.optimize()
|
||||||
|
|
||||||
|
error = np.array([(result.atVector(unknown[k]) - x[k])[0] for k in range(5)])
|
||||||
|
|
||||||
|
print("Result with only GPS")
|
||||||
|
print(result, np.round(error, 2), f"\nJ(X)={0.5 * np.sum(np.square(error))}")
|
||||||
|
|
||||||
|
# Adding odometry will improve things a lot
|
||||||
|
odo_model = gtsam.noiseModel.Isotropic.Sigma(1, sigma_odo)
|
||||||
|
|
||||||
|
|
||||||
|
def error_odom(this: gtsam.CustomFactor, values, jacobians: Optional[List[np.ndarray]], measurement: np.ndarray):
|
||||||
|
"""Odometry Factor error function
|
||||||
|
:param this: gtsam.CustomFactor handle
|
||||||
|
:param values: gtsam.Values
|
||||||
|
:param jacobians: Optional list of Jacobians
|
||||||
|
:param measurement: Odometry measurement, to be filled with `partial`
|
||||||
|
:return: the unwhitened error
|
||||||
|
"""
|
||||||
|
key1 = this.keys()[0]
|
||||||
|
key2 = this.keys()[1]
|
||||||
|
pos1, pos2 = values.atVector(key1), values.atVector(key2)
|
||||||
|
error = measurement - (pos1 - pos2)
|
||||||
|
if jacobians is not None:
|
||||||
|
jacobians[0] = I
|
||||||
|
jacobians[1] = -I
|
||||||
|
|
||||||
|
return error
|
||||||
|
|
||||||
|
|
||||||
|
for k in range(4):
|
||||||
|
factor_graph.add(
|
||||||
|
gtsam.CustomFactor(odo_model, [unknown[k], unknown[k + 1]], partial(error_odom, measurement=np.array([o[k]]))))
|
||||||
|
|
||||||
params = gtsam.GaussNewtonParams()
|
params = gtsam.GaussNewtonParams()
|
||||||
optimizer = gtsam.GaussNewtonOptimizer(factor_graph, v, params)
|
optimizer = gtsam.GaussNewtonOptimizer(factor_graph, v, params)
|
||||||
|
|
||||||
result = optimizer.optimize()
|
result = optimizer.optimize()
|
||||||
print(result)
|
|
||||||
|
error = np.array([(result.atVector(unknown[k]) - x[k])[0] for k in range(5)])
|
||||||
|
|
||||||
|
print("Result with GPS+Odometry")
|
||||||
|
print(result, np.round(error, 2), f"\nJ(X)={0.5 * np.sum(np.square(error))}")
|
||||||
|
|
||||||
|
# This is great, but GPS noise is still apparent, so now we add the two landmarks
|
||||||
|
lm_model = gtsam.noiseModel.Isotropic.Sigma(1, sigma_lm)
|
||||||
|
|
||||||
|
|
||||||
|
def error_lm(this: gtsam.CustomFactor, values, jacobians: Optional[List[np.ndarray]], measurement: np.ndarray):
|
||||||
|
"""Landmark Factor error function
|
||||||
|
:param this: gtsam.CustomFactor handle
|
||||||
|
:param values: gtsam.Values
|
||||||
|
:param jacobians: Optional list of Jacobians
|
||||||
|
:param measurement: Landmark measurement, to be filled with `partial`
|
||||||
|
:return: the unwhitened error
|
||||||
|
"""
|
||||||
|
key = this.keys()[0]
|
||||||
|
pos = values.atVector(key)
|
||||||
|
error = pos - measurement
|
||||||
|
if jacobians is not None:
|
||||||
|
jacobians[0] = I
|
||||||
|
|
||||||
|
return error
|
||||||
|
|
||||||
|
|
||||||
|
factor_graph.add(gtsam.CustomFactor(lm_model, [unknown[0]], partial(error_lm, measurement=np.array([lm_0 + z_0]))))
|
||||||
|
factor_graph.add(gtsam.CustomFactor(lm_model, [unknown[3]], partial(error_lm, measurement=np.array([lm_3 + z_3]))))
|
||||||
|
|
||||||
|
params = gtsam.GaussNewtonParams()
|
||||||
|
optimizer = gtsam.GaussNewtonOptimizer(factor_graph, v, params)
|
||||||
|
|
||||||
|
result = optimizer.optimize()
|
||||||
|
|
||||||
|
error = np.array([(result.atVector(unknown[k]) - x[k])[0] for k in range(5)])
|
||||||
|
|
||||||
|
print("Result with GPS+Odometry+Landmark")
|
||||||
|
print(result, np.round(error, 2), f"\nJ(X)={0.5 * np.sum(np.square(error))}")
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue