示例#1
0
    def _compute_frame_to_frame_motion(self, ref_frame, track_frame):
        # Get feature matches
        self.matcher.pushBack(ref_frame.im_left, ref_frame.im_right)
        self.matcher.pushBack(track_frame.im_left, track_frame.im_right)
        self.matcher.matchFeatures(self.matcher_mode)
        matches = self.matcher.getMatches()
        # print('libviso2 matched {} features.'.format(matches.size()))

        # Stereo observations (uvd)
        self.obs_0 = [np.array([m.u1p, m.v1p, m.u1p - m.u2p]) for m in matches]
        self.obs_1 = [np.array([m.u1c, m.v1c, m.u1c - m.u2c]) for m in matches]

        # Prune all observations with disparity <= 0
        keep_mask = (self.obs_0[:, 2] > 0) & (self.obs_1[:, 2] > 0)
        self.obs_0 = self.obs_0[keep_mask, :]
        self.obs_1 = self.obs_1[keep_mask, :]
        # print('Matches after pruning: {} '.format(len(self.obs_0)))

        # RANSAC
        self.ransac.set_obs(self.obs_0, self.obs_1)
        T_1_0_guess, obs_0_inliers, obs_1_inliers, _ = self.ransac.perform_ransac()

        # Optimize with inliers
        residual = ReprojectionMotionOnlyBatchResidual(
            self.camera, obs_0_inliers, obs_1_inliers, self.reprojection_stiffness)

        problem = Problem(self.motion_options)
        problem.add_residual_block(residual, ['T_1_0'], loss=self.loss)

        params = {'T_1_0': T_1_0_guess}
        problem.initialize_params(params)
        params = problem.solve()

        return params['T_1_0']
示例#2
0
    def test_se3(self, options):
        from liegroups import SE3
        from pyslam.residuals import PoseResidual, PoseToPoseResidual

        problem = Problem(options)

        odom = SE3.exp(0.1 * np.ones(6))

        odom_stiffness = invsqrt(1e-3 * np.eye(SE3.dof))
        T0_stiffness = invsqrt(1e-6 * np.eye(SE3.dof))

        odom_covar = np.linalg.inv(np.dot(odom_stiffness, odom_stiffness))
        T0_covar = np.linalg.inv(np.dot(T0_stiffness, T0_stiffness))

        residual0 = PoseResidual(SE3.identity(), T0_stiffness)
        residual1 = PoseToPoseResidual(odom, odom_stiffness)

        params_init = {'T0': SE3.identity(), 'T1': SE3.identity()}

        problem.add_residual_block(residual0, 'T0')
        problem.add_residual_block(residual1, ['T0', 'T1'])
        problem.initialize_params(params_init)
        problem.solve()
        problem.compute_covariance()
        estimated_covar = problem.get_covariance_block('T1', 'T1')
        expected_covar = odom_covar + odom.adjoint().dot(T0_covar.dot(odom.adjoint().T))

        assert np.allclose(estimated_covar, expected_covar)
示例#3
0
 def test_residual_blocks(self):
     from pyslam.residuals import QuadraticResidual
     problem = Problem()
     param_keys = ['a', 'b', 'c']
     problem.add_residual_block(QuadraticResidual(2., 4., 1.),
                                param_keys)
     assert param_keys == problem.block_param_keys[0]
示例#4
0
 def test_loop_closure(self, options, residuals, residual_params,
                       poses_init, poses_true):
     from liegroups import SE2
     problem = Problem(options)
     for i in range(0, 7):
         problem.add_residual_block(residuals[i], residual_params[i])
     problem.initialize_params(poses_init)
     poses_final = problem.solve()
     for key in poses_true.keys():
         assert np.linalg.norm(
             SE2.log(poses_final[key].inv().dot(poses_true[key]))) < 1e-4
示例#5
0
 def test_first_pose_constant(self, options, residuals, residual_params,
                              poses_init, poses_true):
     from liegroups import SE2
     problem = Problem(options)
     for i in range(1, 6):
         problem.add_residual_block(residuals[i], residual_params[i])
     problem.set_parameters_constant('T_0_w')
     problem.initialize_params(poses_init)
     poses_final = problem.solve()
     for key in poses_true.keys():
         assert np.linalg.norm(
             SE2.log(poses_final[key].inv().dot(poses_true[key]))) < 1e-4
示例#6
0
    def _compute_frame_to_frame_motion(self,
                                       ref_frame,
                                       track_frame,
                                       guess=SE3.identity()):
        # params = {'T_1_0': guess}
        params = {'R_1_0': guess.rot, 't_1_0_1': guess.trans}

        for (pyrlevel, pyr_camera) in zip(self.pyrlevel_sequence,
                                          self.pyr_cameras):
            pyrfactor = 2**-pyrlevel

            im_jacobian = ref_frame.jacobian[pyrlevel]
            # ESM
            # im_jacobian = 0.5 * (ref_frame.jacobian[pyrlevel] +
            #                      track_frame.jacobian[pyrlevel])

            if self.depth_map_type is 'disparity':
                depth_ref = ref_frame.disparity[pyrlevel]
                # Disparity is in pixels, so we need to scale it according to the pyramid level
                depth_stiffness = self.depth_stiffness / pyrfactor
            else:
                depth_ref = ref_frame.depth[pyrlevel]
                depth_stiffness = self.depth_stiffness

            residual = PhotometricResidualSE3(
                pyr_camera, ref_frame.im_pyr[pyrlevel], depth_ref,
                track_frame.im_pyr[pyrlevel], im_jacobian,
                self.intensity_stiffness, depth_stiffness, self.min_grad)

            problem = Problem(self.motion_options)
            # problem.add_residual_block(residual, ['T_1_0'], loss=self.loss)
            problem.add_residual_block(residual, ['R_1_0', 't_1_0_1'],
                                       loss=self.loss)
            problem.initialize_params(params)

            if pyrlevel > 2:
                problem.set_parameters_constant('t_1_0_1')
            # else:
            # problem.set_parameters_constant('R_1_0')

            params = problem.solve()
            # print(problem.summary(format='brief'))

            # # DEBUG: Store residuals for later
            # try:
            #     self.residuals = np.hstack(
            #         [self.residuals, residual.evaluate([guess])])
            # except AttributeError:
            #     self.residuals = residual.evaluate([guess])

        # return params['T_1_0']
        return SE3(params['R_1_0'], params['t_1_0_1'])
示例#7
0
 def test_eval_cost(self):
     from pyslam.residuals import QuadraticResidual
     problem = Problem()
     good_params = {'a': 1., 'b': 2., 'c': 1.}
     bad_params = {'a': 1., 'b': 0., 'c': 0.}
     residual1 = QuadraticResidual(1., 4., 0.5)
     residual2 = QuadraticResidual(0., 1., 2.)
     problem.add_residual_block(residual1, ['a', 'b', 'c'])
     problem.add_residual_block(residual2, ['a', 'b', 'c'])
     problem.initialize_params(good_params)
     assert problem.eval_cost() == 0.
     assert problem.eval_cost(bad_params) == 0.5 * ((0.5 * 0.5 * 3. * 3.)
                                                    + (2. * 2. * 1. * 1.))
示例#8
0
    def test_bundle_adjust(self, options, camera, points, poses, observations):
        from liegroups import SE3
        from pyslam.residuals import ReprojectionResidual

        problem = Problem(options)

        obs_var = [1, 1, 2]  # [u,v,d]
        obs_stiffness = invsqrt(np.diagflat(obs_var))

        for i, this_pose_obs in enumerate(observations):
            for j, o in enumerate(this_pose_obs):
                residual = ReprojectionResidual(camera, o, obs_stiffness)
                problem.add_residual_block(
                    residual, ['T_cam{}_w'.format(i), 'pt{}_w'.format(j)])

        params_true = {}
        params_init = {}

        for i, pt in enumerate(points):
            pid = 'pt{}_w'.format(i)
            params_true.update({pid: pt})
            params_init.update({pid: camera.triangulate(
                observations[0][i] + 10. * np.random.rand(3))})

        for i, pose in enumerate(poses):
            pid = 'T_cam{}_w'.format(i)
            params_true.update({pid: pose})
            params_init.update({pid: SE3.identity()})

        problem.initialize_params(params_init)
        problem.set_parameters_constant('T_cam0_w')

        params_final = problem.solve()

        for key in params_true.keys():
            p_est = params_final[key]
            p_true = params_true[key]

            if isinstance(p_est, SE3):
                err = SE3.log(p_est.inv().dot(p_true))
            else:
                err = p_est - p_true

            assert np.linalg.norm(err) < 1e-4
示例#9
0
    def test_fit_quadratic(self):
        from pyslam.residuals import QuadraticResidual

        params_true = {'a': 1., 'b': -2., 'c': 3.}
        params_init = {'a': -20., 'b': 10., 'c': -30.}

        x_data = np.linspace(-5, 5, 10)
        y_data = params_true['a'] * x_data * x_data \
            + params_true['b'] * x_data + params_true['c']

        problem = Problem()
        problem.options.num_threads = 1
        for x, y in zip(x_data, y_data):
            problem.add_residual_block(QuadraticResidual(
                x, y, 1.), ['a', 'b', 'c'])

        problem.initialize_params(params_init)
        params_final = problem.solve()

        for key in params_true.keys():
            assert(np.allclose(params_final[key], params_true[key]))
示例#10
0
    residual = PhotometricResidualSE3(camera, im_ref, disp_ref, im_track,
                                      jac_ref, 1., 1.)

    # Timing debug
    # niters = 100
    # start = time.perf_counter()
    # for _ in range(niters):
    #     cost.evaluate([params_init['T_1_0']])
    # end = time.perf_counter()
    # print('cost.evaluate avg {} s', (end - start) / niters)

    # start = time.perf_counter()
    # for _ in range(niters):
    #     cost.evaluate([params_init['T_1_0']], [True])
    # end = time.perf_counter()
    # print('cost.evaluate w jac avg {} s', (end - start) / niters)

    # Optimize
    # start = time.perf_counter()

    problem = Problem(options)
    problem.add_residual_block(residual, ['T_1_0'])
    problem.initialize_params(params)
    params = problem.solve()

    # end = time.perf_counter()
    # print('Elapsed time: {} s'.format(end - start))

print('Error in T_1_w: {}'.format(
    SE3.log(T_1_w.dot((params['T_1_0'].dot(T_0_w)).inv()))))
示例#11
0
residual4 = PoseToPoseResidual(T_5_4_obs, odom_stiffness)
residual4_params = ['T_4_0', 'T_5_0']

residual5 = PoseToPoseResidual(T_6_5_obs, odom_stiffness)
residual5_params = ['T_5_0', 'T_6_0']

residual6 = PoseToPoseResidual(T_6_2_obs, loop_stiffness)
residual6_params = ['T_2_0', 'T_6_0']

options = Options()
options.allow_nondecreasing_steps = True
options.max_nondecreasing_steps = 3

problem = Problem(options)
problem.add_residual_block(residual0, residual0_params)
problem.add_residual_block(residual1, residual1_params)
problem.add_residual_block(residual2, residual2_params)
problem.add_residual_block(residual3, residual3_params)
problem.add_residual_block(residual4, residual4_params)
problem.add_residual_block(residual5, residual5_params)
problem.add_residual_block(residual6, residual6_params)

# problem.set_parameters_constant(residual0_params)
# problem.set_parameters_constant(residual1_params)

params_init = {
    'T_1_0': T_1_0_init,
    'T_2_0': T_2_0_init,
    'T_3_0': T_3_0_init,
    'T_4_0': T_4_0_init,
示例#12
0
obs_var = [1, 1, 2]  # [u,v,d]
obs_stiffness = invsqrt(np.diagflat(obs_var))

obs = [[camera.project(T.dot(p))
        for p in pts_w_GT] for T in T_cam_w_GT]

# Optimize
options = Options()
options.allow_nondecreasing_steps = True
options.max_nondecreasing_steps = 3

problem = Problem(options)
for i, this_pose_obs in enumerate(obs):
    for j, o in enumerate(this_pose_obs):
        residual = ReprojectionResidual(camera, o, obs_stiffness)
        problem.add_residual_block(
            residual, ['T_cam{}_w'.format(i), 'pt{}_w'.format(j)])

params_true = {}
params_init = {}

for i, pt in enumerate(pts_w_GT):
    pid = 'pt{}_w'.format(i)
    params_true.update({pid: pt})
    params_init.update({pid: camera.triangulate(
        obs[0][i] + 10. * np.random.rand(3))})

for i, pose in enumerate(T_cam_w_GT):
    pid = 'T_cam{}_w'.format(i)
    params_true.update({pid: pose})
    params_init.update({pid: SE3.identity()})
options = Options()
options.allow_nondecreasing_steps = True
options.max_nondecreasing_steps = 3

problem = Problem(options)

# Collect observations in pairs of poses (i.e. 0-1, 1-2, 2-3) and add
# residuals to problem
for i in range(len(obs) - 1):
    pose_1_obs = obs[i]
    pose_2_obs = obs[i + 1]
    for j, o_1 in enumerate(pose_1_obs):
        o_2 = pose_2_obs[j]
        residual = ReprojectionResidualFrameToFrame(camera, o_1, o_2,
                                                    obs_stiffness)
        problem.add_residual_block(residual,
                                   ['T_cam{}_cam{}'.format(i + 1, i)])

params_true = OrderedDict({})
params_init = OrderedDict({})

# Initialize the relative SE(3) transforms
for i in range(len(obs) - 1):
    T_c1_w = T_cam_w_GT[i]
    T_c2_w = T_cam_w_GT[i + 1]
    pid = 'T_cam{}_cam{}'.format(i + 1, i)
    params_true.update({pid: T_c2_w * T_c1_w.inv()})
    params_init.update({pid: SE3.identity()})

problem.initialize_params(params_init)
params_final = problem.solve()