// Symbols
using Pose2_ = Expression<Pose2>;
Pose2_ a1(1), b(2), a3(3), b4(4), a5(5);
Pose2_ extrinsic_a_, extrinsic_b_;
// Pose2 extrinsic_a_, extrinsic_b_; // Value instead of symbol, if known transform
// Between Constraints for stream A
noiseModel::Diagonal::shared_ptr model = noiseModel::Diagonal::Sigmas(Vector3(0.01, 0.01, 0.01));
graph.addExpressionFactor(between_with_extrinsic(a1, a3, extrinsic_a_), pose_1_3, model);
graph.addExpressionFactor(between_with_extrinsic(a3, a5, extrinsic_a_), pose_3_5, model);
// Between Constraints for stream B
graph.addExpressionFactor(between_with_extrinsic(b2, b4, extrinsic_a_), pose_2_4, model);
// Set smoothing term (equality constraint, covariance scaled on dt)
// Pretend 1.0s between each pose measurement
double dt = 1.0;
noiseModel::Diagonal::shared_ptr smoothing = noiseModel::Diagonal::Sigmas(Vector3(0.1, 0.1, 0.1) * dt);
graph.addExpressionFactor(between(a1, b2), Pose2(0, 0, 0), smoothing);
graph.addExpressionFactor(between(b2, a3), Pose2(0, 0, 0), smoothing);
graph.addExpressionFactor(between(a3, b4), Pose2(0, 0, 0), smoothing);
graph.addExpressionFactor(between(b4, a5), Pose2(0, 0, 0), smoothing);
// Expression:
Pose2_ between_with_extrinsic(const Pose2_& a, const Pose2_& b, const Pose2_& extrinsic)
{
return between(compose(a, extrinsic), compose(b, extrinsic));
}