示例#1
0
def run(args: Namespace) -> None:
    """Run LAGO on input data stored in g2o file."""
    g2oFile = gtsam.findExampleDataFile(
        "noisyToyGraph.txt") if args.input is None else args.input

    graph = gtsam.NonlinearFactorGraph()
    graph, initial = gtsam.readG2o(g2oFile)

    # Add prior on the pose having index (key) = 0
    priorModel = gtsam.noiseModel.Diagonal.Variances(Point3(1e-6, 1e-6, 1e-8))
    graph.add(PriorFactorPose2(0, Pose2(), priorModel))
    print(graph)

    print("Computing LAGO estimate")
    estimateLago: Values = gtsam.lago.initialize(graph)
    print("done!")

    if args.output is None:
        estimateLago.print("estimateLago")
    else:
        outputFile = args.output
        print("Writing results to file: ", outputFile)
        graphNoKernel = gtsam.NonlinearFactorGraph()
        graphNoKernel, initial2 = gtsam.readG2o(g2oFile)
        gtsam.writeG2o(graphNoKernel, estimateLago, outputFile)
        print("Done! ")
示例#2
0
    def test_insertProjectionFactors(self):
        """Test insertProjectionFactors."""
        graph = gtsam.NonlinearFactorGraph()
        gtsam.utilities.insertProjectionFactors(
            graph, 0, [0, 1], np.asarray([[20, 30], [20, 30]]),
            gtsam.noiseModel.Isotropic.Sigma(2, 0.1), gtsam.Cal3_S2())
        self.assertEqual(graph.size(), 2)

        graph = gtsam.NonlinearFactorGraph()
        gtsam.utilities.insertProjectionFactors(
            graph, 0, [0, 1], np.asarray([[20, 30], [20, 30]]),
            gtsam.noiseModel.Isotropic.Sigma(2, 0.1), gtsam.Cal3_S2(),
            gtsam.Pose3(gtsam.Rot3(), gtsam.Point3(1, 0, 0)))
        self.assertEqual(graph.size(), 2)
示例#3
0
def main():
    """Main runner."""
    # Create an empty nonlinear factor graph
    graph = gtsam.NonlinearFactorGraph()

    # Add a prior on the first point, setting it to the origin
    # A prior factor consists of a mean and a noise model (covariance matrix)
    priorMean = gtsam.Pose3()  # prior at origin
    graph.add(gtsam.PriorFactorPose3(1, priorMean, PRIOR_NOISE))

    # Add GPS factors
    gps = gtsam.Point3(lat0, lon0, h0)
    graph.add(gtsam.GPSFactor(1, gps, GPS_NOISE))
    print("\nFactor Graph:\n{}".format(graph))

    # Create the data structure to hold the initialEstimate estimate to the solution
    # For illustrative purposes, these have been deliberately set to incorrect values
    initial = gtsam.Values()
    initial.insert(1, gtsam.Pose3())
    print("\nInitial Estimate:\n{}".format(initial))

    # optimize using Levenberg-Marquardt optimization
    params = gtsam.LevenbergMarquardtParams()
    optimizer = gtsam.LevenbergMarquardtOptimizer(graph, initial, params)
    result = optimizer.optimize()
    print("\nFinal Result:\n{}".format(result))
示例#4
0
    def setUp(self):
        """Set up a small Karcher mean optimization example."""
        # Grabbed from KarcherMeanFactor unit tests.
        R = Rot3.Expmap(np.array([0.1, 0, 0]))
        rotations = {R, R.inverse()}  # mean is the identity
        self.expected = Rot3()

        def check(actual):
            # Check that optimizing yields the identity
            self.gtsamAssertEquals(actual.atRot3(KEY), self.expected, tol=1e-6)
            # Check that logging output prints out 3 lines (exact intermediate values differ by OS)
            self.assertEqual(self.capturedOutput.getvalue().count('\n'), 3)
            # reset stdout catcher
            self.capturedOutput.truncate(0)

        self.check = check

        self.graph = gtsam.NonlinearFactorGraph()
        for R in rotations:
            self.graph.add(gtsam.PriorFactorRot3(KEY, R, MODEL))
        self.initial = gtsam.Values()
        self.initial.insert(KEY, R)

        # setup output capture
        self.capturedOutput = StringIO()
        sys.stdout = self.capturedOutput
def init_smoother(request):
    """
    Runs a batch fixed smoother on an agent with two odometry
    sensors that is simply moving along the x axis in constant
    speed.
    """
    global SMOOTHER_BATCH

    # Define a batch fixed lag smoother, which uses
    # Levenberg-Marquardt to perform the nonlinear optimization
    lag = request.lag
    smoother_batch = gtsam_unstable.BatchFixedLagSmoother(lag)

    new_factors = gtsam.NonlinearFactorGraph()
    new_values = gtsam.Values()
    new_timestamps = gtsam_unstable.FixedLagSmootherKeyTimestampMap()

    prior_mean = request.prior_mean
    prior_noise = request.prior_noise
    X1 = 0
    new_factors.push_back(gtsam.PriorFactorPose2(X1, prior_mean, prior_noise))
    new_values.insert(X1, prior_mean)
    new_timestamps.insert(_timestamp_key_value(X1, 0.0))

    SMOOTHER_BATCH = smoother_batch
    SMOOTHER_BATCH.update(new_factors, new_values, new_timestamps)

    return X1
示例#6
0
    def test_Pose2SLAMExample(self):
        # Assumptions
        #  - All values are axis aligned
        #  - Robot poses are facing along the X axis (horizontal, to the right in images)
        #  - We have full odometry for measurements
        #  - The robot is on a grid, moving 2 meters each step

        # Create graph container and add factors to it
        graph = gtsam.NonlinearFactorGraph()

        # Add prior
        # gaussian for prior
        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]))
        # add directly to graph
        graph.add(gtsam.PriorFactorPose2(1, priorMean, priorNoise))

        # Add odometry
        # general noisemodel for odometry
        odometryNoise = gtsam.noiseModel.Diagonal.Sigmas(
            np.array([0.2, 0.2, 0.1]))
        graph.add(
            gtsam.BetweenFactorPose2(1, 2, gtsam.Pose2(2.0, 0.0, 0.0),
                                     odometryNoise))
        graph.add(
            gtsam.BetweenFactorPose2(2, 3, gtsam.Pose2(2.0, 0.0, pi / 2),
                                     odometryNoise))
        graph.add(
            gtsam.BetweenFactorPose2(3, 4, gtsam.Pose2(2.0, 0.0, pi / 2),
                                     odometryNoise))
        graph.add(
            gtsam.BetweenFactorPose2(4, 5, gtsam.Pose2(2.0, 0.0, pi / 2),
                                     odometryNoise))

        # Add pose constraint
        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))

        # Initialize to noisy points
        initialEstimate = gtsam.Values()
        initialEstimate.insert(1, gtsam.Pose2(0.5, 0.0, 0.2))
        initialEstimate.insert(2, gtsam.Pose2(2.3, 0.1, -0.2))
        initialEstimate.insert(3, gtsam.Pose2(4.1, 0.1, pi / 2))
        initialEstimate.insert(4, gtsam.Pose2(4.0, 2.0, pi))
        initialEstimate.insert(5, gtsam.Pose2(2.1, 2.1, -pi / 2))

        # Optimize using Levenberg-Marquardt optimization with an ordering from
        # colamd
        optimizer = gtsam.LevenbergMarquardtOptimizer(graph, initialEstimate)
        result = optimizer.optimizeSafely()

        # Plot Covariance Ellipses
        marginals = gtsam.Marginals(graph, result)
        P = marginals.marginalCovariance(1)

        pose_1 = result.atPose2(1)
        self.gtsamAssertEquals(pose_1, gtsam.Pose2(), 1e-4)
示例#7
0
    def __init__(self, initial_state, covariance, alphas, beta):
        self._initial_state = gtsam.Pose2(initial_state[0], initial_state[1], initial_state[2])
        self._prior_noise = gtsam.noiseModel_Diagonal.Sigmas(np.array([covariance, covariance, covariance]))
        # self.observation_noise = gtsam.noiseModel_Diagonal.Sigmas(np.array([beta[0] ** 2, np.deg2rad(beta[1]) ** 2]))
        #self.observation_noise = gtsam.noiseModel_Diagonal.Sigmas(np.array([beta[0] ** 2, np.deg2rad(beta[1]) ** 2]))
        self.observation_noise = gtsam.noiseModel_Diagonal.Sigmas(
            np.array(([np.deg2rad(beta[1]) ** 2, (beta[0] / 100) ** 2])))
        self.beta = beta
        self.alphas = alphas ** 2
        self.pose_num = 0
        self.observation_num = 1000
        self.landmark_indexes = list()
        self.states_new = np.array([[]])
        self.observation_new = np.array([[]])

        self.graph = gtsam.NonlinearFactorGraph()
        self.estimations = gtsam.Values()
        self.result = gtsam.Values()
        self.parameters = gtsam.ISAM2Params()
        self.parameters.setRelinearizeThreshold(1e-4)
        self.parameters.setRelinearizeSkip(1)
        self.slam = gtsam.ISAM2(self.parameters)

        self.graph.add(gtsam.PriorFactorPose2(self.pose_num, self._initial_state, self._prior_noise))
        self.estimations.insert(self.pose_num, self._initial_state)
示例#8
0
    def test_jacobian(self):
        """Evaluate jacobian at optical axis"""
        obj_point_on_axis = np.array([0, 0, 1])
        img_point = np.array([0.0, 0.0])
        pose = gtsam.Pose3()
        camera = gtsam.Cal3Unified()
        state = gtsam.Values()
        camera_key, pose_key, landmark_key = K(0), P(0), L(0)
        state.insert_cal3unified(camera_key, camera)
        state.insert_point3(landmark_key, obj_point_on_axis)
        state.insert_pose3(pose_key, pose)
        g = gtsam.NonlinearFactorGraph()
        noise_model = gtsam.noiseModel.Unit.Create(2)
        factor = gtsam.GeneralSFMFactor2Cal3Unified(img_point, noise_model,
                                                    pose_key, landmark_key,
                                                    camera_key)
        g.add(factor)
        f = g.error(state)
        gaussian_factor_graph = g.linearize(state)
        H, z = gaussian_factor_graph.jacobian()
        self.assertAlmostEqual(f, 0)
        self.gtsamAssertEquals(z, np.zeros(2))
        self.gtsamAssertEquals(H @ H.T, 4 * np.eye(2))

        Dcal = np.zeros((2, 10), order='F')
        Dp = np.zeros((2, 2), order='F')
        camera.calibrate(img_point, Dcal, Dp)

        self.gtsamAssertEquals(
            Dcal,
            np.array([[0., 0., 0., -1., 0., 0., 0., 0., 0., 0.],
                      [0., 0., 0., 0., -1., 0., 0., 0., 0., 0.]]))
        self.gtsamAssertEquals(Dp, np.array([[1., -0.], [-0., 1.]]))
示例#9
0
    def step5_add_odometry_and_landmark_observations():
        # Create an empty nonlinear factor graph.
        graph = gtsam.NonlinearFactorGraph()

        # Create keys for the involved variables.
        X2 = X(2)
        X3 = X(3)
        L2 = L(2)

        # Update the list with the new variable keys.
        pose_variables.append(X3)
        landmark_variables.append(L2)

        # Add the odometry measurement.
        odometry_noise = gtsam.noiseModel.Diagonal.Sigmas(
            np.array([0.1, 0.1, 0.1]))
        graph.add(
            gtsam.BetweenFactorPose2(X2, X3, gtsam.Pose2(2.0, 0.0, 0.0),
                                     odometry_noise))

        # Add the landmark observation.
        measurement_noise = gtsam.noiseModel.Diagonal.Sigmas(
            np.array([0.05, 0.1]))
        graph.add(
            gtsam.BearingRangeFactor2D(X3, L2, gtsam.Rot2.fromDegrees(90), 2.0,
                                       measurement_noise))

        # Set initial estimates only for the new variables.
        initial_estimate = gtsam.Values()
        initial_estimate.insert(X3, gtsam.Pose2(4.10, 0.10, 0.10))
        initial_estimate.insert(L2, gtsam.Point2(4.10, 1.80))

        # Update ISAM2 with the new factor graph.
        isam.update(graph, initial_estimate)
示例#10
0
    def __init__(self, relinearizeThreshold=0.01, relinearizeSkip=1):
        """ priorMean and priorCov should be in 1 dimensional array
        """

        # init the graph
        self.graph = gtsam.NonlinearFactorGraph()

        # init the iSam2 solver
        parameters = gtsam.ISAM2Params()
        parameters.setRelinearizeThreshold(relinearizeThreshold)
        parameters.setRelinearizeSkip(relinearizeSkip)

        self.isam = gtsam.ISAM2(parameters)

        # init container for initial values
        self.initialValues = gtsam.Values()

        # setting the current position
        self.currentKey = 1

        # current estimate
        self.currentEst = False

        self.currentPose = [0, 0, 0]

        return
示例#11
0
    def test_factor(self):
        """Check that the InnerConstraint factor leaves the mean unchanged."""
        # Make a graph with two variables, one between, and one InnerConstraint
        # The optimal result should satisfy the between, while moving the other
        # variable to make the mean the same as before.
        # Mean of R and R' is identity. Let's make a BetweenFactor making R21 =
        # R*R*R, i.e. geodesic length is 3 rather than 2.
        graph = gtsam.NonlinearFactorGraph()
        R12 = R.compose(R.compose(R))
        graph.add(gtsam.BetweenFactorRot3(1, 2, R12, MODEL))
        keys = gtsam.KeyVector()
        keys.append(1)
        keys.append(2)
        graph.add(gtsam.KarcherMeanFactorRot3(keys))

        initial = gtsam.Values()
        initial.insert(1, R.inverse())
        initial.insert(2, R)
        expected = Rot3()

        result = gtsam.GaussNewtonOptimizer(graph, initial).optimize()
        actual = gtsam.FindKarcherMean(
            gtsam.Rot3Vector([result.atRot3(1), result.atRot3(2)]))
        self.gtsamAssertEquals(expected, actual)
        self.gtsamAssertEquals(
            R12, result.atRot3(1).between(result.atRot3(2)))
示例#12
0
    def __init__(self,
                 p,
                 q,
                 r,
                 alphas=np.array([0.001, 0.0001]),
                 sensor_offset=np.zeros(2)):

        # Add noise models
        self.odometry_noise = gtsam.noiseModel.Diagonal.Sigmas(q)
        self.measurement_noise = gtsam.noiseModel.Diagonal.Sigmas(r)

        self.alphas = alphas
        self.sensor_offset = sensor_offset

        # Create graph and initilize newest pose
        self.graph = gtsam.NonlinearFactorGraph()
        self.poses = gtsam.Values()

        # To enumerate all poses and landmarks
        self.kx = 1
        self.kl = 1

        self.landmarks = np.empty(0)

        # Initilize graph with prior
        prior_noise = gtsam.noiseModel.Diagonal.Sigmas(p)
        self.graph.add(
            gtsam.PriorFactorPose2(X(self.kx), gtsam.Pose2(0.0, 0.0, 0.0),
                                   prior_noise))
示例#13
0
 def __init__(self, IMU_PARAMS=None, BIAS_COVARIANCE=None):
     """
     Define factor graph parameters (e.g. noise, camera calibrations, etc) here
     """
     self.graph = gtsam.NonlinearFactorGraph()
     self.initial_estimate = gtsam.Values()
     self.IMU_PARAMS = IMU_PARAMS
     self.BIAS_COVARIANCE = BIAS_COVARIANCE
    def add_mr_object_measurement(self,
                                  stack,
                                  class_realization,
                                  new_input_object_prior=None,
                                  new_input_object_covariance=None):
        graph_add = gtsam.NonlinearFactorGraph()
        initial_add = gtsam.Values()

        idx = 0
        for obj in stack:

            cov_noise_model = stack[obj]['covariance']
            exp_gtsam = gtsam.Pose3(
                gtsam.Rot3.Ypr(stack[obj]['expectation'][2],
                               stack[obj]['expectation'][1],
                               stack[obj]['expectation'][0]),
                gtsam.Point3(stack[obj]['expectation'][3],
                             stack[obj]['expectation'][4],
                             stack[obj]['expectation'][5]))

            pose_rotation_matrix = exp_gtsam.rotation().matrix()
            cov_noise_model_rotated = self.rotate_cov_6x6(
                cov_noise_model, np.transpose(pose_rotation_matrix))
            cov_noise_model_rotated = gtsam.noiseModel.Gaussian.Covariance(
                cov_noise_model_rotated)
            #updating the graph
            self.graph.add(
                gtsam.PriorFactorPose3(self.XO(obj), exp_gtsam,
                                       cov_noise_model_rotated))
            graph_add.add(
                gtsam.PriorFactorPose3(self.XO(obj), exp_gtsam,
                                       cov_noise_model_rotated))

            self.prop_belief.add(
                gtsam.PriorFactorPose3(self.XO(obj), exp_gtsam,
                                       cov_noise_model_rotated))

            if self.prop_initial.exists(self.XO(obj)) is False:
                self.prop_initial.insert(
                    self.XO(obj), gtsam.Pose3(gtsam.Pose2(0.0, 0.0, 0.0)))

            # if obj in new_input_object_prior and obj not in self.classRealization:
            #     self.graph.add(gtsam.PriorFactorPose3(self.XO(obj), new_input_object_prior[obj],
            #                                           new_input_object_covariance[obj]))
            #     self.prop_belief.add(gtsam.PriorFactorPose3(self.XO(obj), new_input_object_prior[obj],
            #                                                 new_input_object_covariance[obj]))
            self.classRealization[obj] = class_realization[obj]

            if self.isam.value_exists(self.XO(obj)) is False:
                initial_add.insert(self.XO(obj),
                                   gtsam.Pose3(gtsam.Pose2(0.0, 0.0, 0.0)))

            idx += 1

            if stack[obj]['weight'] > -322:
                self.logWeight += stack[obj]['weight']  # + 150
            else:
                self.logWeight = -math.inf
示例#15
0
    def estimate_global(self):
        np.random.seed(2)
        n0 = 0.000001
        n03 = np.array([n0, n0, n0])
        nNoiseFactor3 = np.array(
            [0.2, 0.2,
             0.2])  # TODO: something about floats and major row? check cython

        # Create an empty nonlinear factor graph
        graph = gtsam.NonlinearFactorGraph()

        # Add a prior on the first pose, setting it to the origin
        priorMean = self.odom_global[0]
        priorNoise = gtsam.noiseModel_Diagonal.Sigmas(n03)
        graph.add(gtsam.PriorFactorPose2(self.X(1), priorMean, priorNoise))

        # Add odometry factors
        odometryNoise = gtsam.noiseModel_Diagonal.Sigmas(nNoiseFactor3)
        for i, pose in enumerate(self.odom_relative):
            graph.add(
                gtsam.BetweenFactorPose2(self.X(i + 1), self.X(i + 2), pose,
                                         odometryNoise))

        # Add visual factors
        visualNoise = gtsam.noiseModel_Diagonal.Sigmas(nNoiseFactor3)
        for i, pose in enumerate(self.visual_relative):
            graph.add(
                gtsam.BetweenFactorPose2(self.X(i + 1), self.X(i + 2), pose,
                                         visualNoise))

        # set initial guess to odometry estimates
        initialEstimate = gtsam.Values()
        for i, pose in enumerate(self.odom_global):
            initialEstimate.insert(self.X(i + 1), pose)

        # optimize using Levenberg-Marquardt optimization
        params = gtsam.LevenbergMarquardtParams()
        params.setVerbosityLM("SUMMARY")
        # gtsam_quadrics.setMaxIterations(params, iter)
        # gtsam_quadrics.setRelativeErrorTol(params, 1e-8)
        # gtsam_quadrics.setAbsoluteErrorTol(params, 1e-8)

        # graph.print_('graph')
        # initialEstimate.print_('initialEstimate ')
        optimizer = gtsam.LevenbergMarquardtOptimizer(graph, initialEstimate,
                                                      params)

        # parameters = gtsam.GaussNewtonParams()
        # parameters.relativeErrorTol = 1e-8
        # parameters.maxIterations = 300
        # optimizer = gtsam.GaussNewtonOptimizer(graph, initialEstimate, parameters)

        result = optimizer.optimize()

        # result.print_('result ')
        # self.draw_trajectories([self.odom_global, self.visual_global], ['b', 'r'], 2)

        return self.unwrap_results(result)
示例#16
0
    def __init__(self):
        self.gtsam_graph = gtsam.NonlinearFactorGraph()
        self.factor_edges = {}  # adjacency list (dict)

        # Variables
        self.values = gtsam.Values()
        self.vars = {}

        self.n_variables = 0
示例#17
0
    def bundle_adjustment(self):
        """
        Parameters:
            calibration - gtsam.Cal3_S2, camera calibration
            landmark_map - list, A map of landmarks and their correspondence
        """
        # Initialize factor Graph
        graph = gtsam.NonlinearFactorGraph()

        initial_estimate = self.create_initial_estimate()

        # Create Projection Factors
        # """
        #   Measurement noise for bundle adjustment:
        #   sigma = 1.0
        #   measurement_noise = gtsam.noiseModel_Isotropic.Sigma(2, sigma)
        # """
        for landmark_idx, observation_list in enumerate(self._landmark_map):
            for obersvation in observation_list:
                pose_idx = obersvation[0]
                key_point = obersvation[1]
                # To test indeterminate system
                # if(landmark_idx == 2 or landmark_idx == 480):
                #     continue
                # if(pose_idx == 6):
                #     print("yes2")
                #     continue
                graph.add(
                    gtsam.GenericProjectionFactorCal3_S2(
                        key_point, self._measurement_noise, X(pose_idx),
                        P(landmark_idx), self._calibration))

        # Create priors for first two poses
        # """
        #   Pose prior noise:
        #   rotation_sigma = np.radians(60)
        #   translation_sigma = 1
        #   pose_noise_sigmas = np.array([rotation_sigma, rotation_sigma, rotation_sigma,
        #                             translation_sigma, translation_sigma, translation_sigma])
        # """
        for idx in (0, 1):
            pose_i = initial_estimate.atPose3(X(idx))
            graph.add(
                gtsam.PriorFactorPose3(X(idx), pose_i, self._pose_prior_noise))

        # Optimization
        # Using QR rather than Cholesky decomposition
        # params = gtsam.LevenbergMarquardtParams()
        # params.setLinearSolverType("MULTIFRONTAL_QR")
        # optimizer = gtsam.LevenbergMarquardtOptimizer(graph, initial_estimate, params)
        optimizer = gtsam.LevenbergMarquardtOptimizer(graph, initial_estimate)

        sfm_result = optimizer.optimize()
        # Check if factor covariances are under constrain
        marginals = gtsam.Marginals(  # pylint: disable=unused-variable
            graph, sfm_result)
        return sfm_result
示例#18
0
    def test_SFMExample(self):
        options = generator.Options()
        options.triangle = False
        options.nrCameras = 10

        [data, truth] = generator.generate_data(options)

        measurementNoiseSigma = 1.0
        pointNoiseSigma = 0.1
        poseNoiseSigmas = np.array([0.001, 0.001, 0.001, 0.1, 0.1, 0.1])

        graph = gtsam.NonlinearFactorGraph()

        # Add factors for all measurements
        measurementNoise = Isotropic.Sigma(2, measurementNoiseSigma)
        for i in range(len(data.Z)):
            for k in range(len(data.Z[i])):
                j = data.J[i][k]
                graph.add(gtsam.GenericProjectionFactorCal3_S2(
                    data.Z[i][k], measurementNoise,
                    X(i), P(j), data.K))

        posePriorNoise = Diagonal.Sigmas(poseNoiseSigmas)
        graph.add(gtsam.PriorFactorPose3(X(0),
                                   truth.cameras[0].pose(), posePriorNoise))
        pointPriorNoise = Isotropic.Sigma(3, pointNoiseSigma)
        graph.add(gtsam.PriorFactorPoint3(P(0),
                                    truth.points[0], pointPriorNoise))

        # Initial estimate
        initialEstimate = gtsam.Values()
        for i in range(len(truth.cameras)):
            pose_i = truth.cameras[i].pose()
            initialEstimate.insert(X(i), pose_i)
        for j in range(len(truth.points)):
            point_j = truth.points[j]
            initialEstimate.insert(P(j), point_j)

        # Optimization
        optimizer = gtsam.LevenbergMarquardtOptimizer(graph, initialEstimate)
        for i in range(5):
            optimizer.iterate()
        result = optimizer.values()

        # Marginalization
        marginals = gtsam.Marginals(graph, result)
        marginals.marginalCovariance(P(0))
        marginals.marginalCovariance(X(0))

        # Check optimized results, should be equal to ground truth
        for i in range(len(truth.cameras)):
            pose_i = result.atPose3(X(i))
            self.gtsamAssertEquals(pose_i, truth.cameras[i].pose(), 1e-5)

        for j in range(len(truth.points)):
            point_j = result.atPoint3(P(j))
            self.gtsamAssertEquals(point_j, truth.points[j], 1e-5)
def build_graph():

    print("build_graph !!!")
    # Create noise models
    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]))

    # Create an empty nonlinear factor graph
    graph = gtsam.NonlinearFactorGraph()

    # Add a prior on the first pose, setting it to the origin
    # A prior factor consists of a mean and a noise model (covariance matrix)
    priorMean = gtsam.Pose2(0.0, 0.0, 0.0)  # prior at origin
    graph.add(gtsam.PriorFactorPose2(1, priorMean, PRIOR_NOISE))

    # Add odometry factors
    odometry = gtsam.Pose2(2.0, 0.0, 0.0)
    odometry1 = gtsam.Pose2(edge_list[0].position.x, edge_list[0].position.y,
                            edge_list[0].position.z)
    odometry2 = gtsam.Pose2(edge_list[1].position.x, edge_list[1].position.y,
                            edge_list[1].position.z)

    # For simplicity, we will use the same noise model for each odometry factor
    # Create odometry (Between) factors between consecutive poses
    graph.add(gtsam.BetweenFactorPose2(1, 2, odometry1, ODOMETRY_NOISE))
    graph.add(gtsam.BetweenFactorPose2(2, 3, odometry2, ODOMETRY_NOISE))
    print("\nFactor Graph:\n{}".format(graph))

    # Create the data structure to hold the initialEstimate estimate to the solution
    # For illustrative purposes, these have been deliberately set to incorrect values
    initial = gtsam.Values()
    initial.insert(1, gtsam.Pose2(0.5, 0.0, 0.2))
    initial.insert(2, gtsam.Pose2(2.3, 0.1, -0.2))
    initial.insert(3, gtsam.Pose2(4.1, 0.1, 0.1))
    print("\nInitial Estimate:\n{}".format(initial))

    # optimize using Levenberg-Marquardt optimization
    params = gtsam.LevenbergMarquardtParams()
    optimizer = gtsam.LevenbergMarquardtOptimizer(graph, initial, params)
    result = optimizer.optimize()
    print("\nFinal Result:\n{}".format(result))

    # 5. Calculate and print marginal covariances for all variables
    marginals = gtsam.Marginals(graph, result)
    for i in range(1, 4):
        print("X{} covariance:\n{}\n".format(i,
                                             marginals.marginalCovariance(i)))

    fig = plt.figure(0)
    for i in range(1, 4):
        gtsam_plot.plot_pose2(0, result.atPose2(i), 0.5,
                              marginals.marginalCovariance(i))
    plt.axis('equal')
    plt.show()
示例#20
0
def find_Karcher_mean_Rot3(rotations):
    """Find the Karcher mean of given values."""
    # Cost function C(R) = \sum PriorFactor(R_i)::error(R)
    # No closed form solution.
    graph = gtsam.NonlinearFactorGraph()
    for R in rotations:
        graph.add(gtsam.PriorFactorRot3(KEY, R, MODEL))
    initial = gtsam.Values()
    initial.insert(KEY, gtsam.Rot3())
    result = gtsam.GaussNewtonOptimizer(graph, initial).optimize()
    return result.atRot3(KEY)
    def __init__(self,
                 geo_model,
                 da_model,
                 lambda_model,
                 prior_mean,
                 prior_noise,
                 lambda_prior_mean=(0., 0.),
                 lambda_prior_noise=((0.5, 0.), (0., 0.5)),
                 cls_enable=True):

        # Symbol initialization
        self.X = lambda i: X(i)
        self.XO = lambda j: O(j)
        self.Lam = lambda k: L(k)

        # Enable Lambda inference
        self.cls_enable = cls_enable

        # Camera pose prior
        self.graph = gtsam.NonlinearFactorGraph()
        self.graph.add(
            gtsam.PriorFactorPose3(self.X(0), prior_mean, prior_noise))

        # Setting initial values
        self.initial = gtsam.Values()
        self.initial.insert(self.X(0), prior_mean)
        self.prev_step_camera_pose = prior_mean
        self.daRealization = list()

        # Setting up models
        self.geoModel = geo_model
        self.daModel = da_model
        self.lambdaModel = lambda_model

        # Setting up ISAM2
        params2 = gtsam.ISAM2Params()
        #params2.relinearize_threshold = 0.01
        #params2.relinearize_skip = 1
        self.isam = gtsam.ISAM2(params2)
        self.isam.update(self.graph, self.initial)

        # Set custom lambda
        if type(lambda_prior_mean) is np.ndarray:
            self.lambda_prior_mean = lambda_prior_mean
        else:
            self.lambda_prior_mean = np.array(lambda_prior_mean)
        self.lambda_prior_cov = gtsam.noiseModel.Gaussian.Covariance(
            np.matrix(lambda_prior_noise))

        self.num_cls = len(self.lambda_prior_mean) + 1

        # Initialize object last lambda database
        self.object_lambda_dict = dict()
示例#22
0
    def __init__(self, odom_global, odom_relative, visual_global,
                 visual_relative):
        self.odom_global = odom_global
        self.odom_relative = odom_relative
        self.visual_global = visual_global
        self.visual_relative = visual_relative

        # shorthand symbols
        self.X = lambda i: int(gtsam.symbol(ord('x'), i))

        # Create an empty nonlinear factor graph
        self.graph = gtsam.NonlinearFactorGraph()
示例#23
0
 def setUp(cls):
   test_clouds = read_ply(*scans_fnames)[:6]
   PRIOR_NOISE = gtsam.noiseModel_Diagonal.Sigmas(np.array([1e-6, 1e-6, 1e-6, 1e-4, 1e-4, 1e-4]))
   ICP_NOISE = gtsam.noiseModel_Diagonal.Sigmas(np.array([1e-6, 1e-6, 1e-6, 1e-4, 1e-4, 1e-4]))
   test_graph = gtsam.NonlinearFactorGraph()
   test_initial_estimates = gtsam.Values()
   initial_pose = gtsam.Pose3(gtsam.Rot3(0.9982740, -0.0572837,  0.0129474, 0.0575611,  0.9980955, -0.0221840, -0.0116519,  0.0228910,  0.9996701),
                       gtsam.Point3(-263.9464864482589, 2467.3015467381383, -19.374652610889633))
   test_graph.add(gtsam.PriorFactorPose3(0, initial_pose, PRIOR_NOISE))
   test_initial_estimates.insert(0, initial_pose)
   test_graph, test_initial_estimates = populate_factor_graph(test_graph, test_initial_estimates, initial_pose, test_clouds)
   cls.graph = test_graph
   cls.initial_estimates = test_initial_estimates
示例#24
0
    def setUp(self):
        self.graph = gtsam.NonlinearFactorGraph()

        odometry = gtsam.Pose2(2.0, 0.0, 0.0)
        odometryNoise = gtsam.noiseModel.Diagonal.Sigmas(
            np.array([0.2, 0.2, 0.1]))
        self.graph.add(gtsam.BetweenFactorPose2(0, 1, odometry, odometryNoise))
        self.graph.add(gtsam.BetweenFactorPose2(1, 2, odometry, odometryNoise))

        self.values = gtsam.Values()
        self.values.insert_pose2(0, gtsam.Pose2(0., 0., 0.))
        self.values.insert_pose2(1, gtsam.Pose2(2., 0., 0.))
        self.values.insert_pose2(2, gtsam.Pose2(4., 0., 0.))
示例#25
0
    def trajectory_estimator(self, features, visible_map):
        """ Estimate current pose with matched features through GTSAM and update the trajectory
        Parameters:
            features: A Feature Object. Stores all matched Superpoint features.
            visible_map: A Map Object. Stores all matched Landmark points.
            pose: gtsam.pose3 Object. The pose at the last state from the atrium map trajectory.
        Returns:
            current_pose: gtsam.pose3 Object. The current estimate pose.

        Use input matched features as the projection factors of the graph.  
        Use input visible_map (match landmark points of the map) as the landmark priors of the graph.
        Use the last time step pose from the trajectory as the initial estimate value of the current pose
        """
        assert len(self.atrium_map.trajectory) != 0, "Trajectory is empty."
        pose = self.atrium_map.trajectory[len(self.atrium_map.trajectory)-1]

        # Initialize factor graph
        graph = gtsam.NonlinearFactorGraph()
        initialEstimate = gtsam.Values()

        # Add projection factors with matched feature points for all measurements
        measurementNoiseSigma = 1.0
        measurementNoise = gtsam.noiseModel_Isotropic.Sigma(
            2, measurementNoiseSigma)
        for i, feature in enumerate(features.key_point_list):
            graph.add(gtsam.GenericProjectionFactorCal3_S2(
                feature, measurementNoise,
                X(0), P(i), self.calibration))

        # Create initial estimate for the pose
        # Because the robot moves slowly, we can use the previous pose as an initial estimation of the current pose.
        initialEstimate.insert(X(0), pose)

        # Create priors for visual
        # Because the map is known, we use the landmarks from the visible map with nearly zero error as priors.
        pointPriorNoise = gtsam.noiseModel_Isotropic.Sigma(3, 0.01)
        for i, landmark in enumerate(visible_map.landmark_list):
            
            graph.add(gtsam.PriorFactorPoint3(P(i),
                                              landmark, pointPriorNoise))
            initialEstimate.insert(P(i), landmark)

        # Optimization
        optimizer = gtsam.LevenbergMarquardtOptimizer(graph, initialEstimate)
        result = optimizer.optimize()

        # Add current pose to the trajectory
        current_pose = result.atPose3(symbol(ord('x'), 0))
        self.atrium_map.append_trajectory(current_pose)

        return current_pose
示例#26
0
 def test_reprojectionErrors(self):
     """Test reprojectionErrors."""
     pixels = np.asarray([[20, 30], [20, 30]])
     I = [1, 2]
     K = gtsam.Cal3_S2()
     graph = gtsam.NonlinearFactorGraph()
     gtsam.utilities.insertProjectionFactors(
         graph, 0, I, pixels, gtsam.noiseModel.Isotropic.Sigma(2, 0.1), K)
     values = gtsam.Values()
     values.insert(0, gtsam.Pose3())
     cam = gtsam.PinholeCameraCal3_S2(gtsam.Pose3(), K)
     gtsam.utilities.insertBackprojections(values, cam, I, pixels, 10)
     errors = gtsam.utilities.reprojectionErrors(graph, values)
     np.testing.assert_allclose(errors, np.zeros((2, 2)))
示例#27
0
    def action_step(self, action, action_noise):

        graph_add = gtsam.NonlinearFactorGraph()
        initial_add = gtsam.Values()

        # Setting path and initiating DA realization.
        path_length = len(self.daRealization)
        self.daRealization.append(0)

        # Advancing the belief by camera
        self.graph.add(
            gtsam.BetweenFactorPose3(self.X(path_length),
                                     self.X(path_length + 1), action,
                                     action_noise))
        graph_add.add(
            gtsam.BetweenFactorPose3(self.X(path_length),
                                     self.X(path_length + 1), action,
                                     action_noise))

        # Setting initial values, save an initial value vector for the propagated pose, need it later
        if self.initial.exists(self.X(path_length + 1)) is False:
            self.initial.insert(
                self.X(path_length + 1),
                self.initial.atPose3(self.X(path_length)).compose(action))
            # self.initial.insert(self.X(path_length + 1), gtsam.Pose3(gtsam.Pose2(0.0, 0.0, 0.0)))
        if initial_add.exists(self.X(path_length + 1)) is False:
            initial_add.insert(
                self.X(path_length + 1),
                self.initial.atPose3(self.X(path_length)).compose(action))
            # initial_add.insert(self.X(path_length + 1), gtsam.Pose3(gtsam.Pose2(0.0, 0.0, 0.0)))

        # Setting propagated belief object for weight computation
        self.prop_belief = self.graph.clone()
        self.prop_initial = gtsam.Values()
        for key in list(self.initial.keys()):
            self.prop_initial.insert(key, self.initial.atPose3(key))

        # self.optimize() #TODO: SEE IF WORKS
        #print(initial_add.exists(self.X(2)))
        self.isam.update(graph_add, initial_add)
        self.optimize()

        # non-existent object issue is resolved.
        self.marginals = gtsam.Marginals(self.prop_belief, self.result)

        # Setting resultsFlag to false to require optimization
        self.resultsFlag = False

        # Multi robot flag for twin measurements
        self.sim_measurement_flag = list()
示例#28
0
    def test_initialize(self) -> None:
        """Smokescreen to ensure LAGO can be imported and run on toy data stored in a g2o file."""
        g2oFile = gtsam.findExampleDataFile("noisyToyGraph.txt")

        graph = gtsam.NonlinearFactorGraph()
        graph, initial = gtsam.readG2o(g2oFile)

        # Add prior on the pose having index (key) = 0
        priorModel = gtsam.noiseModel.Diagonal.Variances(
            Point3(1e-6, 1e-6, 1e-8))
        graph.add(PriorFactorPose2(0, Pose2(), priorModel))

        estimateLago: Values = gtsam.lago.initialize(graph)
        assert isinstance(estimateLago, Values)
示例#29
0
    def __init__(self,
                 class_probability_prior,
                 geo_model,
                 da_model,
                 cls_model,
                 prior_mean,
                 prior_noise,
                 cls_enable=True):

        # Symbol initialization
        self.X = lambda i: X(i)
        self.XO = lambda j: O(j)

        # Camera pose prior
        self.graph = gtsam.NonlinearFactorGraph()
        self.graph.add(
            gtsam.PriorFactorPose3(self.X(0), prior_mean, prior_noise))

        # Class realization and prior probabilities. if one of the class probabilities is 0 it will
        # set the logWeight to -inf
        self.cls_enable = cls_enable

        # Setting initial values
        self.initial = gtsam.Values()
        self.initial.insert(self.X(0), prior_mean)
        self.prev_step_camera_pose = prior_mean
        self.daRealization = list()

        # self.initial.print()

        # Setting up models
        self.geoModel = geo_model
        self.daModel = da_model
        self.clsModel = cls_model
        # self.classifierModel = classifierModel

        # Setting up ISAM2 TODO: make ISAM2 work. As of now, it doesn't take the initial values at optimize_isam2 method
        params2 = gtsam.ISAM2Params()
        # params2.relinearize_threshold = 0.01
        # params2.relinearize_skip = 1
        self.isam = gtsam.ISAM2(params2)
        self.isam.update(self.graph, self.initial)

        # Setting up weight memory
        self.weight_memory = list()
        self.normalized_weight = 0

        # Setting up class realization
        self.classRealization = dict()
        self.classProbabilityPrior = class_probability_prior
示例#30
0
 def test_generic_factor(self):
     """Evaluate residual using pose and point as state variables"""
     graph = gtsam.NonlinearFactorGraph()
     state = gtsam.Values()
     measured = self.img_point
     noise_model = gtsam.noiseModel.Isotropic.Sigma(2, 1)
     pose_key, point_key = P(0), L(0)
     k = self.stereographic
     state.insert_pose3(pose_key, gtsam.Pose3())
     state.insert_point3(point_key, self.obj_point)
     factor = gtsam.GenericProjectionFactorCal3Unified(measured, noise_model, pose_key, point_key, k)
     graph.add(factor)
     score = graph.error(state)
     self.assertAlmostEqual(score, 0)