Пример #1
0
def look_at_matrix(camera_position: np.ndarray, camera_target: np.ndarray,
                   camera_up: np.ndarray):
    z_axis = Utils.normalize(np.array(camera_position - camera_target))
    x_axis = Utils.normalize(np.cross(camera_up, z_axis))
    y_axis = np.cross(z_axis, x_axis)

    translation_x = -np.dot(x_axis, camera_position)
    translation_y = -np.dot(y_axis, camera_position)
    translation_z = -np.dot(z_axis, camera_position)
    translation = np.array([translation_x, translation_y,
                            translation_z]).reshape((3, 1))

    x_axis = x_axis.reshape((3, 1))
    y_axis = y_axis.reshape((3, 1))
    z_axis = z_axis.reshape((3, 1))
    translation = translation.reshape((3, 1))

    #TODO: Make this more efficient
    mat = np.append(np.append(np.append(x_axis, y_axis, axis=1),
                              z_axis,
                              axis=1),
                    translation,
                    axis=1)

    return np.append(mat, Utils.homogenous_for_SE3(), axis=0)
Пример #2
0
def lie_ackermann_correction(gradient_step, motion_cov_inv, ackermann_twist,
                             vo_twist, twist_size):
    # ack_prior = np.multiply(Gradient_step_manager.current_alpha,ackermann_pose_prior)
    ack_prior = ackermann_twist

    #ack_prior = np.matmul(motion_cov_inv, ack_prior) # 1
    #ack_prior = np.multiply(gradient_step, ack_prior) # 2

    R_w, t_w = exp(vo_twist, twist_size)
    R_ack, t_ack = exp(ack_prior, twist_size)

    SE_3_w = np.append(np.append(R_w, t_w, axis=1),
                       Utils.homogenous_for_SE3(),
                       axis=0)
    SE_3_ack = np.append(np.append(R_ack, t_ack, axis=1),
                         Utils.homogenous_for_SE3(),
                         axis=0)

    SE3_w_ack = SE3.pose_pose_composition_inverse(SE_3_w, SE_3_ack)

    w_inc = ln(SE3.extract_rotation(SE3_w_ack),
               SE3.extract_translation(SE3_w_ack), twist_size)

    w_inc = np.multiply(gradient_step, np.matmul(motion_cov_inv, w_inc))  # 1
    #w_inc = np.matmul(motion_cov_inv, w_inc) # 2
    #w_inc = np.multiply(gradient_step, w_inc)

    return w_inc
Пример #3
0
 def intersections(self,ray : Ray ):
     center_to_ray = ray.origin - self.origin
     # A is always 1 since vectors are normalized
     B = 2.0 * Utils.fast_dot(center_to_ray, ray.direction)
     center_to_ray_dot = Utils.fast_dot(center_to_ray, center_to_ray)
     C = center_to_ray_dot - self.radius**2.0
     discriminant = (B**2.0) - 4.0*C
     if discriminant < 0:
         return (False,0,0)
     elif round(discriminant,3) == 0:
         return False, -B / 2.0 , sys.float_info.min
     else:
         return True, (-B + sqrt(discriminant))/2.0, (-B - sqrt(discriminant))/2.0
Пример #4
0
def exp(w, twist_size):
    w_angle = w[3:twist_size]
    w_angle_transpose = np.transpose(w_angle)
    w_x = Utils.skew_symmetric(w[3], w[4], w[5])
    w_x_squared = np.matmul(w_x, w_x)

    # closed form solution for exponential map
    theta_sqred = np.matmul(w_angle_transpose, w_angle)[0][0]
    theta = math.sqrt(theta_sqred)

    A = 0
    B = 0
    C = 0

    # TODO use Taylor Expansion when theta_sqred is small
    if not theta == 0:
        A = math.sin(theta) / theta

    if not theta_sqred == 0:
        B = (1 - math.cos(theta)) / theta_sqred
        C = (1 - A) / theta_sqred

    u = np.array([w[0], w[1], w[2]]).reshape((3, 1))

    R_new = I_3 + np.multiply(A, w_x) + np.multiply(B, w_x_squared)
    V = I_3 + np.multiply(B, w_x) + np.multiply(C, w_x_squared)

    t_new = np.matmul(V, u)

    return R_new, t_new
Пример #5
0
def generate_random_se3(trans_min,trans_max,sigma,yaw_range,pitch_rangle,roll_range):

    t = np.reshape(np.random.uniform(trans_min,trans_max,3),(3,1))

    yaw = np.random.normal(yaw_range, sigma) #around z
    pitch = np.random.normal(pitch_rangle, sigma)# around y
    roll = np.random.normal(roll_range, sigma) # around x

    R_z = np.array([[cos(yaw), -sin(yaw), 0],
           [sin(yaw), cos(yaw), 0],
           [0, 0, 1]])

    R_y = np.array([[cos(pitch), 0, sin(pitch)],
           [0, 1, 0],
           [-sin(pitch), 0, cos(pitch)]])

    R_x = np.array([[1, 0, 0],
           [0, cos(roll), -sin(roll)],
           [0, sin(roll), cos(roll)]])

    R = np.matmul(np.matmul(R_z,R_y),R_x)

    SE3 = np.append(np.append(R,t,axis=1), Utils.homogenous_for_SE3(), axis=0)

    return SE3
Пример #6
0
def ln(R, t, twist_size):
    w = np.zeros((twist_size, 1), dtype=matrix_data_type)

    trace = np.trace(R)
    theta = math.acos((trace - 1.0) / 2.0)
    theta_sqred = math.pow(theta, 2.0)

    R_transpose = np.transpose(R)
    ln_R = I_3

    # TODO use Taylor Expansion when theta is small
    if not theta == 0:
        ln_R = (theta / (2 * math.sin(theta))) * (R - R_transpose)

    w[3] = ln_R[2, 1]
    w[4] = ln_R[0, 2]
    w[5] = ln_R[1, 0]

    w_x = Utils.skew_symmetric(w[3], w[4], w[5])
    w_x_squared = np.matmul(w_x, w_x)

    A = 0
    B = 0
    coeff = 0

    # TODO use Taylor Expansion when theta_sqred is small
    if not theta == 0:
        A = math.sin(theta) / theta

    if not theta_sqred == 0:
        B = (1 - math.cos(theta)) / theta_sqred

    if not (theta == 0 or theta_sqred == 0):
        coeff = (1.0 / (theta_sqred)) * (1.0 - (A / (2.0 * B)))

    V_inv = I_3 + np.multiply(0.5, w_x) + np.multiply(coeff, w_x_squared)

    u = np.matmul(V_inv, t)

    w[0] = u[0]
    w[1] = u[1]
    w[2] = u[2]

    return w
Пример #7
0
 def render(self):
     (height, width) = self.resolution
     for x in range(0, width):
         for y in range(0, height):
             ray_direction_camera_space = self.camera.camera_ray_direction_camera_space(
                 x, y, width, height, self.fov)
             camera_to_world = self.camera.se3_inv
             rot = SE3.extract_rotation(camera_to_world)
             ray_world_space = Utils.normalize(
                 np.matmul(rot, ray_direction_camera_space))
             ray = Geometry.Ray(self.camera.origin_ws[0:3], ray_world_space)
             (b, t, sphere) = self.find_closest_intersection(ray)
             if sphere.is_intersection_acceptable(b, t):
                 intersection_point = Geometry.point_for_ray(ray, t)
                 normal = sphere.normal_for_point(intersection_point)
                 depth = intersection_point[2]
                 self.depth_buffer[y, x] = fabs(depth)
                 self.frame_buffer[y, x] = phong_shading(
                     self.light_ws, intersection_point, normal)
Пример #8
0
def phong_shading(light_ws, position_ws, normal):
    view = Utils.normalize(light_ws - position_ws)
    return Utils.fast_dot(view, normal)
Пример #9
0
def solve_SE3(X, Y, max_its, eps):
    # init
    # array for twist values x, y, z, roll, pitch, yaw
    t_est = np.array([0, 0, 0], dtype=matrix_data_type).reshape((3, 1))
    R_est = np.array([[1, 0, 0], [0, 1, 0], [0, 0, 1]], dtype=matrix_data_type)
    I_3 = np.identity(3, dtype=matrix_data_type)
    (position_vector_size, N) = X.shape
    twist_size = 6
    stacked_obs_size = position_vector_size * N
    homogeneous_se3_padding = Utils.homogenous_for_SE3()
    L_mean = -1
    it = -1
    # Step Factor
    alpha = 0.125

    SE_3_est = np.append(np.append(R_est, t_est, axis=1),
                         Utils.homogenous_for_SE3(),
                         axis=0)

    generator_x = Lie.generator_x()
    generator_y = Lie.generator_y()
    generator_z = Lie.generator_z()
    generator_roll = Lie.generator_roll()
    generator_pitch = Lie.generator_pitch()
    generator_yaw = Lie.generator_yaw()

    for it in range(0, max_its, 1):
        # accumulators
        J_v = np.zeros((twist_size, 1))
        normal_matrix = np.zeros((twist_size, twist_size))

        Y_est = np.matmul(SE_3_est, X)
        v = Y_est - Y

        L = np.sum(np.square(v), axis=0)
        L_mean = np.mean(L)

        if L_mean < eps:
            print('done')
            break

        Js = JacobianGenerator.get_jacobians_lie(generator_x,
                                                 generator_y,
                                                 generator_z,
                                                 generator_yaw,
                                                 generator_pitch,
                                                 generator_roll,
                                                 Y_est,
                                                 N,
                                                 stacked_obs_size,
                                                 coefficient=2.0)

        for i in range(0, N, 1):
            J = Js[i]
            J_t = np.transpose(J)
            error_vector = np.reshape(v[:, i], (position_vector_size, 1))
            J_v += np.matmul(-J_t, error_vector)
            normal_matrix += np.matmul(J_t, J)

        ##########################################################

        # TODO: Investigate faster inversion with QR
        try:
            pseudo_inv = linalg.inv(normal_matrix)
            # (Q,R) = linalg.qr(normal_matrix_2)
        except:
            print('Cant invert')
            return SE_3_est
        w = np.matmul(pseudo_inv, J_v)
        # Apply Step Factor
        w = alpha * w

        w_transpose = np.transpose(w)
        w_x = Utils.skew_symmetric(w[3], w[4], w[5])
        w_x_squared = np.matmul(w_x, w_x)

        # closed form solution for exponential map
        theta = math.sqrt(np.matmul(w_transpose, w))
        theta_sqred = math.pow(theta, 2)
        # TODO use Taylor Expansion when theta_sqred is small
        try:
            A = math.sin(theta) / theta
            B = (1 - math.cos(theta)) / theta_sqred
            C = (1 - A) / theta_sqred
        except:
            print('bad theta')
            return SE_3_est

        u = np.array([w[0], w[1], w[2]]).reshape((3, 1))

        R_new = I_3 + np.multiply(A, w_x) + np.multiply(B, w_x_squared)
        V = I_3 + np.multiply(B, w_x) + np.multiply(C, w_x_squared)

        t_est += +np.matmul(V, u)
        R_est = np.matmul(R_new, R_est)

        SE_3_est = np.append(np.append(R_est, t_est, axis=1),
                             homogeneous_se3_padding,
                             axis=0)
        print('Runtime mean error:', L_mean)

    print('mean error:', L_mean, 'iteration: ', it)
    return SE_3_est
Пример #10
0
def solve_photometric(frame_reference,
                      frame_target,
                      max_its,
                      eps,
                      alpha_step,
                      use_ndc=False,
                      debug=False):
    # init
    # array for twist values x, y, z, roll, pitch, yaw
    t_est = np.array([0, 0, 0], dtype=matrix_data_type).reshape((3, 1))
    #R_est = np.array([[0.0, -1.0, 0],
    #                  [1.0, 0.0, 0],
    #                  [0, 0, 1]], dtype=matrix_data_type)
    R_est = np.identity(3, dtype=matrix_data_type)
    I_3 = np.identity(3, dtype=matrix_data_type)

    (height, width) = frame_target.pixel_image.shape
    N = height * width
    position_vector_size = 3
    twist_size = 6
    stacked_obs_size = position_vector_size * N
    homogeneous_se3_padding = Utils.homogenous_for_SE3()
    # Step Factor
    #alpha = 0.125
    Gradient_step_manager = GradientStepManager.GradientStepManager(
        alpha_start=alpha_step,
        alpha_min=-0.7,
        alpha_step=-0.01,
        alpha_change_rate=0,
        gradient_monitoring_window_start=3,
        gradient_monitoring_window_size=0)
    v_mean = -10000
    v_mean_abs = -10000
    it = -1
    std = math.sqrt(0.4)
    image_range_offset = 10
    #depth_factor = 1.0
    #depth_factor = 1000 # 0.001 # ZR300

    SE_3_est = np.append(np.append(R_est, t_est, axis=1),
                         Utils.homogenous_for_SE3(),
                         axis=0)
    SE_3_est_orig = np.append(np.append(R_est, t_est, axis=1),
                              Utils.homogenous_for_SE3(),
                              axis=0)
    SE_3_est_last_valid = np.append(np.append(R_est, t_est, axis=1),
                                    Utils.homogenous_for_SE3(),
                                    axis=0)

    generator_x = Lie.generator_x_3_4()
    generator_y = Lie.generator_y_3_4()
    generator_z = Lie.generator_z_3_4()
    generator_roll = Lie.generator_roll_3_4()
    generator_pitch = Lie.generator_pitch_3_4()
    generator_yaw = Lie.generator_yaw_3_4()

    X_back_projection = np.ones((4, N), Utils.matrix_data_type)
    X_back_projection_last_valid = np.ones((4, N), Utils.matrix_data_type)
    valid_measurements_reference = np.full(N, False)
    valid_measurements_last = np.full(N, False)
    valid_measurements_target = np.full(N, False)
    valid_measurements = valid_measurements_reference

    # Precompute back projection of pixels
    GaussNewtonRoutines.back_project_image(width, height, image_range_offset,
                                           frame_reference.camera,
                                           frame_reference.pixel_depth,
                                           X_back_projection,
                                           valid_measurements, use_ndc)

    if debug:
        Plot3D.save_projection_of_back_projected(height, width,
                                                 frame_reference,
                                                 X_back_projection)

    # Precompute the Jacobian of SE3 around the identity
    J_lie = JacobianGenerator.get_jacobians_lie(generator_x,
                                                generator_y,
                                                generator_z,
                                                generator_yaw,
                                                generator_pitch,
                                                generator_roll,
                                                X_back_projection,
                                                N,
                                                stacked_obs_size,
                                                coefficient=2.0)

    # Precompute the Jacobian of the projection function
    J_pi = JacobianGenerator.get_jacobian_camera_model(
        frame_reference.camera.intrinsic, X_back_projection)

    # count the number of true
    #valid_measurements_total = np.logical_and(valid_measurements_reference,valid_measurements_target)

    #number_of_valid_reference = np.sum(valid_measurements_reference)
    #number_of_valid_total = np.sum(valid_measurements_total)
    #number_of_valid_measurements = number_of_valid_reference

    for it in range(0, max_its, 1):
        start = time.time()
        # accumulators
        #TODO: investigate preallocate and clear in a for loop
        J_v = np.zeros((twist_size, 1))
        normal_matrix = np.zeros((twist_size, twist_size))

        # Warp with the current SE3 estimate
        Y_est = np.matmul(SE_3_est, X_back_projection)
        v = np.zeros((N, 1), dtype=matrix_data_type, order='F')

        target_index_projections = frame_target.camera.apply_perspective_pipeline(
            Y_est)

        v_sum = GaussNewtonRoutines.compute_residual(
            width, height, target_index_projections, valid_measurements,
            frame_target.pixel_image, frame_reference.pixel_image, v,
            image_range_offset)

        number_of_valid_measurements = np.sum(valid_measurements_reference)

        Gradient_step_manager.save_previous_mean_error(v_mean_abs, it)

        v_mean = v_sum / number_of_valid_measurements
        valid_pixel_ratio = number_of_valid_measurements / N
        #v_mean_abs = np.abs(v_mean)
        #v_mean_abs = v_mean

        # TODO put this in gradient step manager
        #if valid_pixel_ratio< 0.8:
        #    print('Too many pixels are marked invalid')
        #    Gradient_step_manager.current_alpha+=0.1
        #    SE_3_est = SE_3_est_last_valid
        #    valid_measurements = valid_measurements_last
        #else:
        #    SE_3_est_last_valid = SE_3_est
        #    valid_measurements_last = valid_measurements

        Gradient_step_manager.track_gradient(v_mean_abs, it)

        if v_mean < eps:
            print('done, mean error:', v_mean)
            break

        Gradient_step_manager.analyze_gradient_history(it)
        #Gradient_step_manager.analyze_gradient_history_instantly(v_mean_abs)

        # See Kerl et al. ensures error decreases ( For pyramid levels )
        #if(v_mean > Gradient_step_manager.last_error_mean_abs):
        #continue

        GaussNewtonRoutines.gauss_newton_step(width, height,
                                              valid_measurements, J_pi, J_lie,
                                              frame_target.grad_x,
                                              frame_target.grad_y, v, J_v,
                                              normal_matrix,
                                              image_range_offset)

        # TODO: Investigate faster inversion with QR
        try:
            pseudo_inv = linalg.inv(normal_matrix)
            #(Q,R) = linalg.qr(normal_matrix)
            #Q_t = np.transpose(Q)
            #R_inv = linalg.inv(R)
            #pseudo_inv = np.multiply(R_inv,Q_t)
        except:
            print('Cant invert')
            return SE_3_est

        w = np.matmul(pseudo_inv, J_v)
        # Apply Step Factor
        w = Gradient_step_manager.current_alpha * w

        w_transpose = np.transpose(w)
        w_x = Utils.skew_symmetric(w[3], w[4], w[5])
        w_x_squared = np.matmul(w_x, w_x)

        # closed form solution for exponential map
        theta = math.sqrt(np.matmul(w_transpose, w))
        theta_sqred = math.pow(theta, 2)
        # TODO use Taylor Expansion when theta_sqred is small
        try:
            A = math.sin(theta) / theta
            B = (1 - math.cos(theta)) / theta_sqred
            C = (1 - A) / theta_sqred
        except:
            print('bad theta')
            return SE_3_est

        u = np.array([w[0], w[1], w[2]]).reshape((3, 1))

        R_new = I_3 + np.multiply(A, w_x) + np.multiply(B, w_x_squared)
        V = I_3 + np.multiply(B, w_x) + np.multiply(C, w_x_squared)

        t_est += +np.matmul(V, u)
        R_est = np.matmul(R_new, R_est)

        SE_3_est = np.append(np.append(R_est, t_est, axis=1),
                             homogeneous_se3_padding,
                             axis=0)
        end = time.time()
        print('mean error:', v_mean, 'iteration: ', it, 'valid pixel ratio: ',
              valid_pixel_ratio, 'runtime: ', end - start)

    return SE_3_est
Пример #11
0
def adjoint_se3(R, t):
    t_x = Utils.skew_symmetric(t[0], t[1], t[2])
    top = np.append(R, np.matmul(t_x, R), axis=1)
    bottom = np.append(np.identity(3), R, axis=1)
    return np.append(top, bottom, axis=0)
Пример #12
0
    def __init__(self,
                 ground_truth_list=None,
                 plot_steering=False,
                 title=None,
                 plot_trajectory=True,
                 plot_rmse=True):
        self.ground_truth_list = []
        if ground_truth_list is not None:
            self.ground_truth_list = ground_truth_list
        self.figure = plt.figure()
        self.plot_steering = plot_steering
        self.plot_trajectory = plot_trajectory
        self.plot_rmse = plot_rmse

        if title:
            plt.title(title)
        if not plot_trajectory and not plot_rmse:
            if not self.plot_steering:
                self.x_graph = self.figure.add_subplot(131)
                self.y_graph = self.figure.add_subplot(132)
                self.z_graph = self.figure.add_subplot(133)
            else:
                self.x_graph = self.figure.add_subplot(231)
                self.y_graph = self.figure.add_subplot(232)
                self.z_graph = self.figure.add_subplot(233)
                self.rev = self.figure.add_subplot(223)
                self.steer = self.figure.add_subplot(224)

        elif not plot_steering:
            if plot_trajectory:
                self.se3_graph = self.figure.add_subplot(311, projection='3d')
            self.x_graph = self.figure.add_subplot(334)
            self.y_graph = self.figure.add_subplot(335)
            self.z_graph = self.figure.add_subplot(336)
            if self.plot_rmse:
                self.rmse_graph = self.figure.add_subplot(313)
        else:
            if plot_trajectory:
                self.se3_graph = self.figure.add_subplot(411, projection='3d')
            self.x_graph = self.figure.add_subplot(434)
            self.y_graph = self.figure.add_subplot(435)
            self.z_graph = self.figure.add_subplot(436)
            if self.plot_rmse:
                self.rmse_graph = self.figure.add_subplot(413)
            self.rev = self.figure.add_subplot(427)
            self.steer = self.figure.add_subplot(428)

        if plot_steering:
            self.rev.set_title("rev cmd")
            self.steer.set_title("str cmd")

            self.rev.set_xlabel("frame")
            self.steer.set_xlabel("frame")

            self.rev.set_ylabel("input level")
            self.steer.set_ylabel("input level")

        #self.se3_graph.set_aspect('equal')
        if self.plot_trajectory:
            self.se3_graph.set_title("relative pose estimate")
        self.x_graph.set_title("X")
        self.x_graph.set_title("X")
        self.y_graph.set_title("Y")
        self.z_graph.set_title("Z")

        self.x_graph.set_xlabel("frame")
        self.y_graph.set_xlabel("frame")
        self.z_graph.set_xlabel("frame")

        self.x_graph.set_ylabel("meters")

        if self.plot_rmse:
            self.rmse_graph.set_title("drift per frame (pose error)")

        # These points will be plotted with incomming se3 matricies
        X, Y, Z = [0, 0], [0, 0], [0, -1]
        #X, Y, Z = [0, 0], [0, 0], [0, 1]
        H = np.repeat(1, 2)

        self.point_pair = Utils.to_homogeneous_positions(X, Y, Z, H)

        if self.plot_steering:
            plt.subplots_adjust(left=0.07)
        else:
            plt.subplots_adjust(left=0.05)
Пример #13
0
 def normal_for_point(self,point_on_shpere):
     return Utils.normalize(point_on_shpere - self.origin)
Пример #14
0
from MotionModels import Ackermann, SteeringCommand, MotionDeltaRobot, Pose
import numpy as np
from Numerics import Utils, SE3
import matplotlib.pyplot as plt
from Visualization import Plot3D

X, Y, Z = [0,0], [0,0], [0,-1]
H = np.repeat(1,2)

origin = Utils.to_homogeneous_positions(X, Y, Z, H)

dt = 1.0
pose = Pose.Pose()
steering_command_straight = SteeringCommand.SteeringCommands(1.0, 0.0)

ackermann_motion = Ackermann.Ackermann()

new_motion_delta = ackermann_motion.ackermann_dead_reckoning_delta(steering_command_straight)
pose.apply_motion(new_motion_delta,dt)

#TODO investigate which theta to use
# this might actually be better since we are interested in the uncertainty only in this timestep
theta = new_motion_delta.delta_theta
# traditional uses accumulated theta
#theta = pose.theta

motion_cov_small = ackermann_motion.covariance_dead_reckoning(steering_command_straight,theta,dt)

se3 = SE3.generate_se3_from_motion_delta(new_motion_delta)
origin_transformed = np.matmul(se3, origin)
Пример #15
0
import matplotlib.pyplot as plt
from Visualization import Plot3D
from Numerics import Generator, Utils
import numpy as np
import math

#X, Y, Z = [0,0,10,10] , [0,0,10,10] , [0,-1,0,-1]
X, Y, Z = [0, 0], [0, 0], [0, -1]
H = np.repeat(1, 2)

pair = Utils.to_homogeneous_positions(X, Y, Z, H)

se3 = Generator.generate_random_se3(2, 2, math.pi, math.pi / 2, 0, 0)
se3_2 = Generator.generate_random_se3(2, 2, math.pi, math.pi / 2, 0, 0)

pair_transformed = np.matmul(se3, pair)
pair_transformed_2 = np.matmul(se3_2, pair)

points = np.append(pair, pair_transformed, axis=1)
points_xyz = points[0:3, :]

fig = plt.figure()
ax = fig.add_subplot(111, projection='3d')

Plot3D.plot_array_lines(points_xyz, ax)
pair_transformed = np.matmul(se3, pair)
import Numerics.Generator as Generator
import Visualization.Plot3D as Plot3D
import numpy as np
import Numerics.Utils as NumUtils

(X, Y, Z) = Generator.generate_3d_plane(1, 1, -30, 20, 4)
H = np.repeat(1, 20)

points = np.transpose(
    np.array(list(map(lambda x: list(x), list(zip(X, Y, Z, H))))))

SE3 = Generator.generate_random_se3(-1, 1, 4)

rotated_points = np.matmul(SE3, points)

(X_new, Y_new, Z_new) = list(NumUtils.points_into_components(rotated_points))

#Plot3D.scatter_plot(X_new,Y_new,Z_new)
Plot3D.scatter_plot([(X, Y, Z), (X_new, Y_new, Z_new)],
                    ['original', 'perturbed'])
Пример #17
0
N = 20

(X, Y, Z) = Generator.generate_3d_plane(1, 1, -30, N, 4)
H = np.repeat(1, N)

points = np.transpose(
    np.array(list(map(lambda x: list(x), list(zip(X, Y, Z, H))))))

SE3 = Generator.generate_random_se3(-5, 5, pi / 18, pi / 10, 0, pi / 10)

perturbed_points_gt = np.matmul(SE3, points)

camera = Camera.normalized_camera()

points_persp = camera.apply_perspective_pipeline(points)

#SE3_est = Solver.solve_SE3(points,perturbed_points_gt,20000,0.01)

#perturbed_points_est = np.matmul(SE3_est,points)

(X_orig, Y_orig, Z_orig) = list(Utils.points_into_components(points))
(X_new, Y_new, Z_new) = list(Utils.points_into_components(perturbed_points_gt))
#(X_est,Y_est,Z_est) = list(Utils.points_into_components(perturbed_points_est))
(X_persp, Y_persp, Z_persp) = list(Utils.points_into_components(points_persp))

#Plot3D.scatter_plot([(X_orig,Y_orig,Z_orig),(X_new,Y_new,Z_new),(X_est,Y_est,Z_est)],['original','perturbed','estimate'])
Plot3D.scatter_plot_sub([(X_orig, Y_orig, Z_orig)],
                        [(X_persp, Y_persp, Z_persp)], ['original'],
                        ['projected'])
Пример #18
0
import Numerics.Generator as Generator
import Visualization.Plot3D as Plot3D
import numpy as np
import Numerics.Utils as NumUtils
import VisualOdometry.Solver as Solver
from math import pi

N = 100
(X, Y, Z) = Generator.generate_3d_plane(1, 1, -10, N, 4)
H = np.repeat(1, N)

points = np.transpose(
    np.array(list(map(lambda x: list(x), list(zip(X, Y, Z, H))))))

SE3 = Generator.generate_random_se3(-10, 10, 4, pi / 2, 0, pi / 2)

rotated_points_gt = np.matmul(SE3, points)

(X_gt, Y_gt, Z_gt) = list(NumUtils.points_into_components(rotated_points_gt))

SE3_est = Solver.solve_SE3(points, rotated_points_gt, 20000, 0.01)

rotated_points_est = np.matmul(SE3_est, points)

(X_est, Y_est,
 Z_est) = list(NumUtils.points_into_components(rotated_points_est))

Plot3D.scatter_plot([(X, Y, Z), (X_gt, Y_gt, Z_gt), (X_est, Y_est, Z_est)],
                    ['original', 'ground truth', 'estimate'])
Пример #19
0
image_height = 320

points = np.transpose(
    np.array(list(map(lambda x: list(x), list(zip(X, Y, Z, H))))))

spheres = Geometry.generate_spheres(points)

camera = Camera.normalized_camera(0, 0, image_width / 2, image_height / 2)
camera_translated = Camera.normalized_camera(5, 0, image_width / 2,
                                             image_height / 2)

##############

points_persp = camera.apply_perspective_pipeline(points)

(X_orig, Y_orig, Z_orig) = list(Utils.points_into_components(points))
(X_persp, Y_persp, Z_persp) = list(Utils.points_into_components(points_persp))

##############

scene = Scene.Scene(image_width, image_height, spheres, camera)

scene.render()

frame_buffer_image = ImageProcessing.normalize_to_image_space(
    scene.frame_buffer)
depth_buffer_image = scene.depth_buffer

cv2.imwrite("framebuffer.png", frame_buffer_image)
cv2.imwrite("depthbuffer.png", depth_buffer_image)
Пример #20
0
 def camera_ray_direction_camera_space(self, pixel_x, pixel_y, width,
                                       height, fov):
     (camera_x, camera_y) = self.pixel_to_camera(pixel_x, pixel_y, width,
                                                 height, fov)
     ray_cs = np.array([camera_x, camera_y, -1]).reshape(3, 1)
     return Utils.normalize(ray_cs)
Пример #21
0
from MotionModels import Ackermann, SteeringCommand, MotionDeltaRobot, Pose
from Numerics import Utils, SE3
import matplotlib.pyplot as plt
from Visualization import Plot3D
import numpy as np
import math

X, Y, Z = [0,0], [0,0], [0,-1]
H = np.repeat(1,2)

origin = Utils.to_homogeneous_positions(X, Y, Z, H)

dt = 1.0
pose = Pose.Pose()
steering_command_straight = SteeringCommand.SteeringCommands(1.5, 0.0)

ackermann_motion = Ackermann.Ackermann()

new_motion_delta = ackermann_motion.ackermann_dead_reckoning_delta(steering_command_straight)
pose.apply_motion(new_motion_delta,dt)
pose.apply_motion(new_motion_delta,dt)
pose.apply_motion(new_motion_delta,dt)

#TODO investigate which theta to use
# this might actually be better since we are interested in the uncertainty only in this timestep
#theta = new_motion_delta.delta_theta
# traditional uses accumulated theta
theta = pose.theta

motion_cov_small = ackermann_motion.covariance_dead_reckoning(steering_command_straight,theta,dt)
Пример #22
0
def twist_to_SE3(twist):
    R, t = Lie.exp(twist, 6)
    SE3 = np.append(np.append(R, t, axis=1),
                    Utils.homogenous_for_SE3(),
                    axis=0)
    return SE3
Пример #23
0
# We only need the gradients of the target frame
frame_reference = Frame.Frame(im_greyscale_reference, depth_reference,
                              camera_reference, False)
frame_target = Frame.Frame(im_greyscale_target, depth_target, camera_target,
                           True)

#visualizer = Visualizer.Visualizer(photometric_solver)

SE3_est = Solver.solve_photometric(frame_reference,
                                   frame_target,
                                   threadLock=None,
                                   pose_estimate_list=None,
                                   max_its=20000,
                                   eps=0.001,
                                   alpha_step=1.0,
                                   gradient_monitoring_window_start=5.0,
                                   image_range_offset_start=0,
                                   twist_prior=None,
                                   hessian_prior=None,
                                   use_ndc=use_ndc,
                                   use_robust=True,
                                   track_pose_estimates=False,
                                   debug=False)
euler_angles_XYZ = SE3.rotationMatrixToEulerAngles(
    SE3.extract_rotation(SE3_est))

print(SE3_est)
print(Utils.radians_to_degrees(euler_angles_XYZ[0]),
      Utils.radians_to_degrees(euler_angles_XYZ[1]),
      Utils.radians_to_degrees(euler_angles_XYZ[2]))
Пример #24
0
def get_standard_deviation_factors_from_covaraince_list(cov_list):
    evd_list = Utils.covariance_eigen_decomp_for_list(cov_list)
    eigen_value_list = Utils.eigen_values_from_evd_list(evd_list)
    return get_standard_deviation_factors_for_projection_for_list(
        eigen_value_list)
Пример #25
0
def solve_photometric(frame_reference,
                      frame_target,
                      threadLock,
                      pose_estimate_list,
                      max_its,
                      eps,
                      alpha_step,
                      gradient_monitoring_window_start,
                      image_range_offset_start,
                      max_depth,
                      twist_prior=None,
                      motion_cov_inv_in=None,
                      use_ndc=False,
                      use_robust=False,
                      track_pose_estimates=False,
                      use_motion_prior=False,
                      ackermann_pose_prior=None,
                      use_ackermann=False,
                      debug=False):

    if track_pose_estimates and (threadLock == None
                                 or pose_estimate_list == None):
        raise RuntimeError(
            'Visualization Flag is set, but no list and lock are supplied')

    # init
    # array for twist values x, y, z, roll, pitch, yaw
    t_est = np.array([0, 0, 0], dtype=matrix_data_type).reshape((3, 1))
    #R_est = np.array([[0.0, -1.0, 0],
    #                  [1.0, 0.0, 0],
    #                  [0, 0, 1]], dtype=matrix_data_type)
    R_est = np.identity(3, dtype=matrix_data_type)
    I_3 = np.identity(3, dtype=matrix_data_type)
    I_4 = np.identity(4, dtype=matrix_data_type)
    I_6 = np.identity(6, dtype=matrix_data_type)
    zero_cov = np.zeros((6, 6), dtype=matrix_data_type)
    #SE3_best = np.identity(4,dtype=matrix_data_type)
    (height, width) = frame_target.pixel_image.shape
    N = height * width
    position_vector_size = 3
    twist_size = 6
    stacked_obs_size = position_vector_size * N
    homogeneous_se3_padding = Utils.homogenous_for_SE3()
    variance = -1
    v_mean = maxsize
    image_range_offset = image_range_offset_start
    degrees_of_freedom = 5.0  # empirically derived: see paper
    normal_matrix_ret = np.identity(6, dtype=Utils.matrix_data_type)
    motion_cov_inv = motion_cov_inv_in
    #motion_cov_inv = np.linalg.inv(motion_cov_inv_in)
    w = np.zeros((twist_size, 1), dtype=Utils.matrix_data_type)
    w_empty = np.zeros((twist_size, 1), dtype=Utils.matrix_data_type)
    w_prev = np.zeros((twist_size, 1), dtype=Utils.matrix_data_type)
    w_acc = np.zeros((twist_size, 1), dtype=Utils.matrix_data_type)
    v_id = np.zeros((N, 1), dtype=matrix_data_type, order='F')
    pseudo_inv = np.identity(twist_size, dtype=matrix_data_type)
    not_better = False
    valid_pixel_ratio = 1.0
    motion_cov_inv_norm = Utils.norm_covariance_row(motion_cov_inv_in)

    fx = frame_reference.camera.intrinsic.extract_fx()
    fy = frame_reference.camera.intrinsic.extract_fy()

    depth_factor = np.sign(fx)
    #depth_factor = -np.sign(fx)

    Gradient_step_manager = GradientStepManager.GradientStepManager(
        alpha_start=alpha_step,
        alpha_min=-0.7,
        alpha_step=-0.01,
        alpha_change_rate=0,
        gradient_monitoring_window_start=gradient_monitoring_window_start,
        gradient_monitoring_window_size=0)

    SE_3_est = np.append(np.append(R_est, t_est, axis=1),
                         Utils.homogenous_for_SE3(),
                         axis=0)
    SE_3_prev = np.append(np.append(R_est, t_est, axis=1),
                          Utils.homogenous_for_SE3(),
                          axis=0)
    #SE_3_est_orig = np.append(np.append(R_est, t_est, axis=1), Utils.homogenous_for_SE3(), axis=0)
    #SE_3_est_last_valid = np.append(np.append(R_est, t_est, axis=1), Utils.homogenous_for_SE3(), axis=0)

    generator_x = Lie.generator_x_3_4()
    #generator_x = Lie.generator_x_3_4_neg()
    generator_y = Lie.generator_y_3_4()
    #generator_y = Lie.generator_y_3_4_neg()
    #generator_z = Lie.generator_z_3_4()
    generator_z = Lie.generator_z_3_4_neg()

    # Depth factor of -1.0 leads to inverted roll and pitch when displaying
    # Why?: Generator defines the direction of increase (My thoughts)
    generator_roll = Lie.generator_roll_3_4()
    #generator_roll = Lie.generator_roll_3_4_neg()
    #generator_pitch = Lie.generator_pitch_3_4()
    generator_pitch = Lie.generator_pitch_3_4_neg()
    generator_yaw = Lie.generator_yaw_3_4()
    #generator_yaw = Lie.generator_yaw_3_4_neg()

    X_back_projection = depth_factor * np.ones((4, N), Utils.matrix_data_type)
    X_back_projection[3, :] = 1.0
    #X_back_projection_last_valid = np.ones((4, N), Utils.matrix_data_type)
    valid_measurements_reference = np.full(N, False)
    valid_measurements_target = np.full(N, False)
    #valid_measurements_last = np.full(N,False)
    #valid_measurements_target = np.full(N,False)
    valid_measurements = valid_measurements_reference
    number_of_valid_measurements = N
    #v = np.zeros((N, 1), dtype=matrix_data_type, order='F')

    # Precompute back projection of pixels
    GaussNewtonRoutines.back_project_image(
        width, height, image_range_offset, frame_reference.camera,
        frame_reference.pixel_depth, frame_target.pixel_depth,
        X_back_projection, valid_measurements, valid_measurements_target,
        use_ndc, depth_factor, max_depth)

    count = np.sum(valid_measurements)
    count_target = np.sum(valid_measurements_target)

    z_rot = SE3.makeS03(0, 0, math.pi)
    se3_rot = np.identity(4, dtype=matrix_data_type)
    se3_rot[0:3, 0:3] = z_rot
    #X_back_projection = np.matmul(se3_rot,X_back_projection)

    if debug:
        Plot3D.save_projection_of_back_projected(height, width,
                                                 frame_reference,
                                                 X_back_projection)

    # Precompute the Jacobian of SE3 around the identity
    J_lie = JacobianGenerator.get_jacobians_lie(generator_x,
                                                generator_y,
                                                generator_z,
                                                generator_yaw,
                                                generator_pitch,
                                                generator_roll,
                                                X_back_projection,
                                                N,
                                                stacked_obs_size,
                                                coefficient=1.0)

    # Precompute the Jacobian of the projection function
    J_pi = JacobianGenerator.get_jacobian_camera_model(
        frame_reference.camera.intrinsic, X_back_projection)

    # count the number of true
    #valid_measurements_total = np.logical_and(valid_measurements_reference,valid_measurements_target)

    #number_of_valid_reference = np.sum(valid_measurements_reference)
    #number_of_valid_total = np.sum(valid_measurements_total)
    #number_of_valid_measurements = number_of_valid_reference

    #target_index_projections_id = frame_target.camera.apply_perspective_pipeline(I_4)

    target_index_projections = frame_target.camera.apply_perspective_pipeline(
        X_back_projection, use_ndc, width, height)

    GaussNewtonRoutines.compute_residual(
        width, height, target_index_projections, valid_measurements,
        valid_measurements_target, frame_target.pixel_image,
        frame_reference.pixel_image, frame_target.pixel_depth,
        frame_reference.pixel_depth, v_id, image_range_offset)

    v = np.copy(v_id)
    W = np.ones((1, N), dtype=matrix_data_type, order='F')

    for it in range(0, max_its, 1):
        start = time.time()
        # accumulators
        #TODO: investigate preallocate and clear in a for loop
        g = np.zeros((twist_size, 1))
        normal_matrix = np.identity(twist_size, dtype=matrix_data_type)

        # TODO investigate performance impact
        if track_pose_estimates:
            threadLock.acquire()
            pose_estimate_list.append(SE_3_est)
            threadLock.release()

        #v_diff = math.fabs(Gradient_step_manager.last_error_mean_abs - v_mean)
        #v_diff = Gradient_step_manager.last_error_mean_abs - v_mean

        #Gradient_step_manager.track_gradient(v_mean,it)

        # TODO investigate absolute error threshold aswel?
        #if ((v_diff <= eps)) and Gradient_step_manager.check_iteration(it) :
        #    print('done, mean error:', v_mean, 'diff: ', v_diff, 'pixel ratio:', valid_pixel_ratio)
        #    break

        # no if statement means solver 2
        #if v_mean <= Gradient_step_manager.last_error_mean_abs:
        not_better = False
        prior_empty = False
        if twist_prior[0] == 0 and twist_prior[1] == 0 and twist_prior[2] == 0 and twist_prior[3] == 0 and \
                twist_prior[4] == 0 and twist_prior[5] == 0:
            prior_empty = True

        if use_motion_prior:
            converged = GaussNewtonRoutines.gauss_newton_step_motion_prior(
                width, height, valid_measurements, valid_measurements_target,
                W, J_pi, J_lie, frame_target.grad_x, frame_target.grad_y, v, g,
                normal_matrix, motion_cov_inv, twist_prior, w,
                image_range_offset)
        else:
            converged = GaussNewtonRoutines.gauss_newton_step(
                width, height, valid_measurements, valid_measurements_target,
                W, J_pi, J_lie, frame_target.grad_x, frame_target.grad_y, v, g,
                normal_matrix, image_range_offset)
        normal_matrix_ret = normal_matrix

        #try:
        #    pseudo_inv = linalg.inv(normal_matrix)
        #except:
        #    print('Cant invert')
        #    return SE_3_est

        #w_new = np.matmul(pseudo_inv, g)

        try:
            w_new = linalg.solve(normal_matrix, g)
        except:
            print('Cant solve')
            return SE_3_est

        # initial step with empty motion prior seems to be quite large
        #if use_motion_prior and prior_empty:
        #    w_new = np.multiply(Gradient_step_manager.current_alpha/2.0, w_new)
        #else:
        w_new = np.multiply(Gradient_step_manager.current_alpha, w_new)

        # For using ackermann motion
        if use_ackermann:
            # V1
            # inc = ackermann_pose_prior - w
            # w_new += np.matmul(motion_cov_inv,inc)
            # w_new += inc

            # V2
            #factor = 0.1*Gradient_step_manager.current_alpha
            factor = 0.1
            #factor = math.pow(Gradient_step_manager.current_alpha,it)
            # ack_prior = np.multiply(Gradient_step_manager.current_alpha,ackermann_pose_prior)
            ack_prior = ackermann_pose_prior

            w_new += Lie.lie_ackermann_correction(factor, motion_cov_inv,
                                                  ack_prior, w, twist_size)

        #else:
        #    not_better = True
        #    w_new = w_empty

        R_cur, t_cur = Lie.exp(w, twist_size)
        R_new, t_new = Lie.exp(w_new, twist_size)

        # C_new . C_cur
        #t_est = np.add(np.matmul(R_new, t_cur), t_new)
        #R_est = np.matmul(R_new, R_cur)

        # C_Cur . C_new
        t_est = np.add(np.matmul(R_cur, t_new), t_cur)
        R_est = np.matmul(R_cur, R_new)

        w = Lie.ln(R_est, t_est, twist_size)

        #SE_3_current = np.append(np.append(R_cur, t_cur, axis=1), homogeneous_se3_padding, axis=0)
        SE_3_est = np.append(np.append(R_est, t_est, axis=1),
                             homogeneous_se3_padding,
                             axis=0)

        #debug_list  = [i for i, x in enumerate(valid_measurements) if x]

        Y_est = np.matmul(SE_3_est, X_back_projection)

        target_index_projections = frame_target.camera.apply_perspective_pipeline(
            Y_est, use_ndc, width, height)
        #target_index_projections[2,:] -= depth_factor*1

        v = GaussNewtonRoutines.compute_residual(
            width, height, target_index_projections, valid_measurements,
            valid_measurements_target, frame_target.pixel_image,
            frame_reference.pixel_image, frame_target.pixel_depth,
            frame_reference.pixel_depth, v, image_range_offset)

        number_of_valid_measurements = np.sum(valid_measurements)
        valid_pixel_ratio = number_of_valid_measurements / N

        if number_of_valid_measurements <= 0 and Gradient_step_manager.check_iteration(
                it):
            print('pixel ratio break')
            print('done, mean error:', v_mean, 'diff: ', v_diff,
                  'pixel ratio:', valid_pixel_ratio)
            #SE_3_est = SE3_best
            break

        if use_robust:
            variance = GaussNewtonRoutines.compute_t_dist_variance(
                v,
                degrees_of_freedom,
                N,
                valid_measurements,
                valid_measurements_target,
                number_of_valid_measurements,
                variance_min=1000,
                eps=0.001)
            if variance > 0.0:
                # clear old weights
                for i in range(0, N):
                    W[0, i] = 1
                GaussNewtonRoutines.generate_weight_matrix(
                    W, v, variance, degrees_of_freedom, N)

        v_weighted = np.copy(v)
        GaussNewtonRoutines.multiply_v_by_diagonal_matrix(
            W, v_weighted, N, valid_measurements)

        v_sum = np.matmul(np.transpose(v), v_weighted)[0][0]

        end = time.time()

        #if v_mean < Gradient_step_manager.last_error_mean_abs:
        #    SE3_best = np.copy(SE_3_est)
        #if not not_better: # solver 6
        Gradient_step_manager.save_previous_mean_error(v_mean)

        if number_of_valid_measurements > 0:
            v_mean = v_sum / number_of_valid_measurements
        else:
            v_mean = maxsize

        v_diff = math.fabs(Gradient_step_manager.last_error_mean_abs - v_mean)
        print('mean error:', v_mean, 'error diff: ', v_diff, 'iteration: ', it,
              'valid pixel ratio: ', valid_pixel_ratio, 'runtime: ',
              end - start, 'variance: ', variance)
        #v_diff = Gradient_step_manager.last_error_mean_abs - v_mean

        #Gradient_step_manager.track_gradient(v_mean,it)

        # TODO investigate absolute error threshold aswel?
        if ((v_diff <= eps)) and Gradient_step_manager.check_iteration(it):
            print('done, mean error:', v_mean, 'diff: ', v_diff,
                  'pixel ratio:', valid_pixel_ratio)
            break

    motion_cov_inv = normal_matrix_ret

    return SE_3_est, w, motion_cov_inv