Esempio n. 1
0
    def __init__(self):
        super(CostFunction, self).__init__()
        moveit_commander.roscpp_initialize(sys.argv)
        self.collision_threshold = 0.07
        self.robot_state = moveit_commander.RobotCommander()
        self.scene = moveit_commander.PlanningSceneInterface()
        self.franka_k = FrankaKinematics()

        def show_objects(self):
            for k, v in self.scene.get_objects().items():
                print "Pos:", v.primitive_poses[0].position.x, v.primitive_poses[0].position.y,\
                    v.primitive_poses[0].position.z
                print "Ori:", v.primitive_poses[0].orientation.x, v.primitive_poses[0].orientation.y,\
                    v.primitive_poses[0].orientation.z, v.primitive_poses[0].orientation.w
                print "Size:", v.primitives[0].dimensions
Esempio n. 2
0
    def __init__(
        self,
        nDoF,
        obstacle_list=None,
        ini_jv=None,
        des_jv=None,
    ):
        super(TrajectoryOptimize, self).__init__()
        self.initial_joint_values = ini_jv
        self.desired_joint_values = des_jv
        self.scene = moveit_commander.PlanningSceneInterface()
        # if obstacle_list is None:
        #     self.obstacle_list = np.array([[0.25, 0.21, 0.71, 0.1], [-0.15, 0.21, 0.51, 0.05]])  # for two spheres
        # else:
        #     self.obstacle_list = obstacle_list
        self.obstacle_list = obstacle_list
        self.nDoF = nDoF
        self.franka_kin = FrankaKinematics()
        self.workspace_dim = (-0.5, -0.5, 0.2, 1.5, 0.5, 1.9)
        # self.obstacle_list = np.array([[0.25, 0.21, 0.71, 0.1]])  # for one sphere (x,y,z, radius)

        # self.obstacle_list = np.array([[0.25, 0.21, 0.71, 0.1],
        #                              [-0.15, 0.21, 0.51, 0.05],
        #                              [0.15, 0.61, 0.51, 0.05],
        #                              [-0.15, -0.61, 0.51, 0.05],
        #                              [-0.65, 0.31, 0.21, 0.05],
        #                              [-0.55, 0.71, 0.71, 0.06],
        #                              [-0.95, -0.51, 0.41, 0.07],
        #                              [-0.85, 0.27, 0.61, 0.08],
        #                              [-0.25, -0.31, 0.11, 0.04],
        #                              [-0.75, 0.71, 0.91, 0.09],
        #                              [-0.35, 0.51, 0.81, 0.02],
        #                              [-0.95, -0.81, 0.61, 0.03],
        #                              [-0.75, 0.11, 0.41, 0.02],
        #                              [-0.55, -0.61, 0.21, 0.06],
        #                              [0.25, 0.31, 0.71, 0.07],
        #                              [-0.35, -0.41, 0.41, 0.02],
        #                              [-0.25, -0.51, 0.61, 0.08],
        #                              ])  # for 15 spheres
        # self.obstacle_list1 = self.populate_obstacles()
        self.optCurve, self.costs = [], []
        self.step_size = 0.06
        self.debug = False

        self.lamda_smooth, self.lamda_obs = 10.0, 20.0
 def __init__(self, nDoF):
     self.nDoF = nDoF
     self.scene = moveit_commander.PlanningSceneInterface()
     self.group = moveit_commander.MoveGroupCommander("panda_arm")
     self.robot_state = moveit_commander.RobotCommander()
     self.workspace_dim = (-2, -0.2, 0.2, 1, 1, 1.5)
     self.group.set_workspace(
         self.workspace_dim
     )  # specify the workspace bounding box (static scene)
     self.franka_kin = FrankaKinematics()
     self.collision_threshold = 0.07
     self.object_list = np.array([
         [0.25, 0.21, 0.71, 0.1],
         [-0.15, 0.21, 0.51, 0.05],
         [0.15, 0.61, 0.51, 0.05],
         [-0.15, -0.61, 0.51, 0.05],
         [-0.65, 0.31, 0.21, 0.05],
         [-0.55, 0.71, 0.71, 0.06],
         [-0.95, -0.51, 0.41, 0.07],
         [-0.85, 0.27, 0.61, 0.08],
         [-0.25, -0.31, 0.11, 0.04],
         [-0.75, 0.71, 0.91, 0.09],
         [-0.35, 0.51, 0.81, 0.02],
         [-0.95, -0.81, 0.61, 0.03],
         [-0.75, 0.11, 0.41, 0.02],
         [-0.55, -0.61, 0.21, 0.06],
         [0.25, 0.31, 0.71, 0.07],
         [-0.35, -0.41, 0.41, 0.02],
         [-0.25, -0.51, 0.61, 0.08],
     ])  # for two spheres
     # self.object_list = np.array([[0.25, 0.21, 0.71, 0.1], [-0.15, 0.21, 0.51, 0.05]])  # for two spheres
     # self.object_list = np.array([[0.25, 0.21, 0.71, 0.1]])  # for one sphere (x,y,z, radius)
     # self.object_list = []
     # self.object_list = self.populate_obstacles()
     self.initial_joint_values = np.zeros(7)  # + 0.01 * np.random.random(7)
     self.ang_deg = 60
     self.desired_joint_values = np.array([
         np.pi * self.ang_deg / 180, np.pi / 3, 0.0, np.pi / 6, np.pi / 6,
         np.pi / 6, np.pi / 6
     ])
     self.optCurve = []
     self.step_size = 0.09
Esempio n. 4
0
    def promp_planner(self, mu_x, sig_x, mu_quat, sig_quat, obstacle_list, Qlists, timeLists, PromP_Planner=True):
        time_normalised = np.linspace(0, 1, 35)
        nDoF, nBf = 7, 5
        cur_jv = self.group.get_current_joint_values()
        weight_space_optim = optim_weight_space(time_normalised, nDoF, nBf, mu_x, sig_x, mu_quat, sig_quat,
                                                obstacle_list, curr_jvs=cur_jv, QLists=Qlists, timeLists=timeLists)
        weights = np.random.multivariate_normal(weight_space_optim.mean_cond_weight,
                                                weight_space_optim.covMat_cond_weight)

        if not PromP_Planner:
            ################ Trajectory space optimization: CHOMP

            franka_kin = FrankaKinematics()
            des_jv = weight_space_optim.post_mean_q
            n = np.linalg.norm((des_jv - cur_jv)) / (len(time_normalised) - 1)

            traj2optimise = self.discretize(cur_jv, des_jv, step_size=n)
            traj2optimise = np.insert(traj2optimise, len(traj2optimise), des_jv,
                                           axis=0)  # inserting goal state at the end of discretized
            traj2optimise = np.insert(traj2optimise, 0, cur_jv, axis=0)
            print 'chomp n', n, traj2optimise.shape[0]
            save_path = '/home/automato/Ash/MPlib/src/ProMPlib/with_obstacles/CHOMP/'
            uniq_name = str(time.time())

            traj_opt = TrajectoryOptimize(7, obstacle_list)
            start = time.time()
            optimised_trajectory = traj_opt.optimise(traj2optimise, withGrad=True)
            np.savetxt(save_path + 'traj_CHOMP_%s.out' % uniq_name, optimised_trajectory, delimiter=',')
            total_time = time.time() - start
            print total_time
            T, _ = franka_kin.fwd_kin(optimised_trajectory[-1])
            quat = np.array(tf_tran.quaternion_from_matrix(T))
            print 'quat_diff = ', quat - mu_quat
            print '#########'
            print 'pos_diff = ', T[:3, 3] - mu_x

            vel, accel, tme = self.create_q_v_a(optimised_trajectory)
            rt = self.create_trajectory(optimised_trajectory, vel, accel, tme)
            rt_back = self.create_trajectory(np.flipud(optimised_trajectory), np.flipud(vel), np.flipud(accel), tme)
            smooth_cost_promp = 0.0
            return optimised_trajectory, total_time, rt, rt_back, smooth_cost_promp

        ##################################
        else:
            # Weight space optimization:

            start = time.time()
            optimised_trajectory, opt_weights = weight_space_optim.optimise(weights, withGrad=True)
            smooth_cost_promp = weight_space_optim.smoothness_cost(opt_weights)
            total_time = time.time() - start
            print total_time
            save_path = '/home/automato/Ash/MPlib/src/ProMPlib/with_obstacles/ProMP/'
            uniq_name = str(time.time())

            np.savetxt(save_path+'traj_promp_%s.out' % uniq_name, optimised_trajectory, delimiter=',')
            np.savetxt(save_path+'weights_promp_%s.out' % uniq_name, opt_weights, delimiter=',')

            franka_kin = FrankaKinematics()
            T, _ = franka_kin.fwd_kin(optimised_trajectory[-1])
            quat = np.array(tf_tran.quaternion_from_matrix(T))
            print 'quat_diff = ', quat - mu_quat
            print '#########'
            print 'pos_diff = ', T[:3, 3] - mu_x
            vel, accel, tme = self.create_q_v_a(optimised_trajectory)
            rt = self.create_trajectory(optimised_trajectory, vel, accel, tme)
            rt_back = self.create_trajectory(np.flipud(optimised_trajectory), np.flipud(vel), np.flipud(accel), tme)

            return optimised_trajectory, total_time, rt, rt_back, smooth_cost_promp
Esempio n. 5
0
class TrajectoryOptimize(object):
    def __init__(
        self,
        nDoF,
        obstacle_list=None,
        ini_jv=None,
        des_jv=None,
    ):
        super(TrajectoryOptimize, self).__init__()
        self.initial_joint_values = ini_jv
        self.desired_joint_values = des_jv
        self.scene = moveit_commander.PlanningSceneInterface()
        # if obstacle_list is None:
        #     self.obstacle_list = np.array([[0.25, 0.21, 0.71, 0.1], [-0.15, 0.21, 0.51, 0.05]])  # for two spheres
        # else:
        #     self.obstacle_list = obstacle_list
        self.obstacle_list = obstacle_list
        self.nDoF = nDoF
        self.franka_kin = FrankaKinematics()
        self.workspace_dim = (-0.5, -0.5, 0.2, 1.5, 0.5, 1.9)
        # self.obstacle_list = np.array([[0.25, 0.21, 0.71, 0.1]])  # for one sphere (x,y,z, radius)

        # self.obstacle_list = np.array([[0.25, 0.21, 0.71, 0.1],
        #                              [-0.15, 0.21, 0.51, 0.05],
        #                              [0.15, 0.61, 0.51, 0.05],
        #                              [-0.15, -0.61, 0.51, 0.05],
        #                              [-0.65, 0.31, 0.21, 0.05],
        #                              [-0.55, 0.71, 0.71, 0.06],
        #                              [-0.95, -0.51, 0.41, 0.07],
        #                              [-0.85, 0.27, 0.61, 0.08],
        #                              [-0.25, -0.31, 0.11, 0.04],
        #                              [-0.75, 0.71, 0.91, 0.09],
        #                              [-0.35, 0.51, 0.81, 0.02],
        #                              [-0.95, -0.81, 0.61, 0.03],
        #                              [-0.75, 0.11, 0.41, 0.02],
        #                              [-0.55, -0.61, 0.21, 0.06],
        #                              [0.25, 0.31, 0.71, 0.07],
        #                              [-0.35, -0.41, 0.41, 0.02],
        #                              [-0.25, -0.51, 0.61, 0.08],
        #                              ])  # for 15 spheres
        # self.obstacle_list1 = self.populate_obstacles()
        self.optCurve, self.costs = [], []
        self.step_size = 0.06
        self.debug = False

        self.lamda_smooth, self.lamda_obs = 10.0, 20.0

    def populate_obstacles(self, ):
        # if the obstacle is within robot workspace, then consider those as obstacles
        obs = []
        x_min, x_max = self.workspace_dim[0], self.workspace_dim[3]
        y_min, y_max = self.workspace_dim[1], self.workspace_dim[4]
        z_min, z_max = self.workspace_dim[2], self.workspace_dim[5]

        for k, v in self.scene.get_objects().items():
            px, py, pz = v.primitive_poses[0].position.x, v.primitive_poses[
                0].position.y, v.primitive_poses[0].position.z
            if px >= x_min and px <= x_max:
                if py >= y_min and py <= y_max:
                    if pz >= z_min and pz <= z_max:
                        obs.append([px, py, pz, 0.05])
        return np.array(obs)

    def sphere(self, ax, radius, centre):
        u = np.linspace(0, 2 * np.pi, 13)
        v = np.linspace(0, np.pi, 7)
        x = centre[0] + radius * np.outer(np.cos(u), np.sin(v))
        y = centre[1] + radius * np.outer(np.sin(u), np.sin(v))
        z = centre[2] + radius * np.outer(np.ones(np.size(u)), np.cos(v))
        xdata = scipy.ndimage.zoom(x, 3)
        ydata = scipy.ndimage.zoom(y, 3)
        zdata = scipy.ndimage.zoom(z, 3)
        ax.plot_surface(xdata,
                        ydata,
                        zdata,
                        rstride=3,
                        cstride=3,
                        color='w',
                        shade=0)

    def optimise(self, trajectory, withGrad=True):
        self.initial_joint_values = trajectory[0]
        self.desired_joint_values = trajectory[-1]
        self.trajectory_to_optimise = trajectory[1:-1]
        trajectory_flat = self.trajectory_to_optimise.T.reshape((-1))

        if withGrad:
            ################### With Gradient #########################
            now = time.time()

            opti_traj = opt.minimize(self.calculate_total_cost,
                                     trajectory_flat,
                                     method='BFGS',
                                     jac=self.cost_gradient_analytic,
                                     options={
                                         'maxiter': 150,
                                         'disp': True
                                     },
                                     callback=self.optim_callback)

            cur = time.time()
            print 'CHOMP time with gradient:', cur - now

            opti_trajec = np.transpose(opti_traj.x.reshape((self.nDoF, -1)))
            opti_trajec = np.insert(opti_trajec,
                                    0,
                                    self.initial_joint_values,
                                    axis=0)
            opti_trajec = np.insert(opti_trajec,
                                    len(opti_trajec),
                                    self.desired_joint_values,
                                    axis=0)
            # #
        else:
            # ###################### Without Gradient ############################
            now = time.time()
            opti_traj = opt.minimize(self.calculate_total_cost,
                                     trajectory_flat,
                                     method='BFGS',
                                     options={
                                         'maxiter': 150,
                                         'disp': True
                                     },
                                     callback=self.optim_callback)
            cur = time.time()
            print 'CHOMP time without gradient:', cur - now
            opti_trajec = np.transpose(opti_traj.x.reshape((self.nDoF, -1)))

            opti_trajec = np.insert(opti_trajec,
                                    0,
                                    self.initial_joint_values,
                                    axis=0)
            opti_trajec = np.insert(opti_trajec,
                                    len(opti_trajec),
                                    self.desired_joint_values,
                                    axis=0)

        return opti_trajec, self.costs, opti_traj.success

    def calculate_total_cost(self, trajectoryFlat):
        F_smooth = self.smoothness_objective(
            trajectoryFlat)  # smoothness of trajectory is captured here
        if self.obstacle_list is not None:
            obstacle_cost = self.obstacle_cost(trajectoryFlat,
                                               self.obstacle_list)
        else:
            obstacle_cost = 0.0
        return self.lamda_smooth * F_smooth + self.lamda_obs * obstacle_cost  # for with gradient
        # return 10 * F_smooth + 1.5 * obstacle_cost   #  for without gradient

    def smoothness_objective(self, trajectoryFlat):
        trajectoryFlat = np.squeeze(trajectoryFlat)
        trajectory = trajectoryFlat.reshape((self.nDoF, -1)).T
        dim = np.multiply(*trajectory.shape)
        fd_matrix, b = self.finite_diff_matrix(trajectory)
        trajectory = trajectory.T.reshape((dim, 1))
        F_smooth = 0.5 * (np.dot(trajectory.T, np.dot(fd_matrix, trajectory)) +
                          np.dot(trajectory.T, b) + 0.25 * np.dot(b.T, b))
        return F_smooth

    def finite_diff_matrix(self, trajectory):
        rows, columns = trajectory.shape  # columns = nDoF
        A = 2 * np.eye(rows)
        A[0, 1] = -1
        A[rows - 1, rows - 2] = -1
        for ik in range(0, rows - 2):
            A[ik + 1, ik] = -1
            A[ik + 1, ik + 2] = -1

        dim = rows * columns
        fd_matrix = np.zeros((dim, dim))
        b = np.zeros((dim, 1))
        i, j = 0, 0
        while i < dim:
            fd_matrix[i:i + len(A), i:i + len(A)] = A
            b[i] = -2 * self.initial_joint_values[j]
            b[i + len(A) - 1] = -2 * self.desired_joint_values[j]
            i = i + len(A)
            j = j + 1
        return fd_matrix, b

    def obstacle_cost(
        self,
        trajectoryFlat,
        obstacle_list,
    ):
        trajectoryFlat = np.squeeze(trajectoryFlat)
        trajectory = (trajectoryFlat.reshape(
            (self.nDoF, trajectoryFlat.shape[0] / self.nDoF))).T
        robot_body_points = self.calculate_robot_body_points(trajectory)
        vel_normalised, vel_mag, vel = self.calculate_normalised_workspace_velocity(
            robot_body_points)
        dist = self.compute_minimum_distance_to_objects(
            robot_body_points[:-1], obstacle_list)
        obstacle_cost_potential = np.array(self.cost_potential(dist))
        return np.sum(np.multiply(obstacle_cost_potential, vel_mag))

    def cost_potential(self, D, collision_threshold=0.07):
        c = np.zeros(D.shape)
        return np.where(
            D < 0, -D + 0.5 * collision_threshold,
            np.where(D <= collision_threshold,
                     (0.5 *
                      (D - collision_threshold)**2) / collision_threshold, c))

    def compute_minimum_distance_to_objects(self,
                                            robot_body_points,
                                            obstacle_list,
                                            body_sphere_size=0.12):
        rbp_shape = robot_body_points.shape
        return np.min(
            distance.cdist(robot_body_points.reshape(-1, 3, order='A'),
                           obstacle_list[:, :3]) - obstacle_list[:, 3] -
            body_sphere_size,
            axis=1).reshape(rbp_shape[:2])

    def calculate_smoothness_gradient(self, trajectoryFlat):
        trajectory = np.squeeze(trajectoryFlat).reshape((self.nDoF, -1)).T
        dim = np.multiply(*trajectory.shape)
        fd_matrix, b = self.finite_diff_matrix(trajectory)
        trajectory = trajectory.T.reshape((dim, 1))
        return 0.5 * b + fd_matrix.dot(trajectory)

    def get_robot_discretised_points(self, fwd_k_j_positions, step_size=0.2):
        discretised = list()
        j_index = list()
        # self.get_robot_discretised_joint_index(fwd_k_j_positions, step_size=0.2)
        for j in range(len(fwd_k_j_positions) - 1):
            w = fwd_k_j_positions[j + 1] - fwd_k_j_positions[j]
            if len(w[w != 0.]):
                step = step_size * w / np.linalg.norm(w)
                n = int(np.linalg.norm(w) / np.linalg.norm(step)) + 1
                discretised.extend(
                    np.outer(np.arange(1, n), step) + fwd_k_j_positions[j])
            j_index.append(len(discretised))
        self.j_index = j_index
        return np.array(discretised)

    def get_robot_joint_positions(self, joint_values):
        _, t_joints = self.franka_kin.fwd_kin(joint_values)
        return np.vstack(([0., 0., 0.], t_joints[:, :3, 3]))

    def calculate_robot_body_points(self, trajectory):
        trajectory = np.vstack((trajectory, self.desired_joint_values))
        return np.array([
            self.get_robot_discretised_points(
                self.get_robot_joint_positions(joint_values),
                self.step_size,
            ) for joint_values in trajectory
        ])

    def calculate_normalised_workspace_velocity(self, robot_body_points):
        velocity = np.diff(robot_body_points, axis=0)
        vel_magnitude = np.linalg.norm(velocity, axis=2)
        vel_normalised = np.divide(velocity,
                                   vel_magnitude[:, :, None],
                                   out=np.zeros_like(velocity),
                                   where=vel_magnitude[:, :, None] != 0)
        return vel_normalised, vel_magnitude, velocity

    def extract_block_diag(self, A, M=3, k=0):
        ny, nx = A.shape
        ndiags = min(map(lambda x: x // M, A.shape))
        offsets = (nx * M + M, nx, 1)
        strides = map(lambda x: x * A.itemsize, offsets)
        if k > 0:
            B = A[:, k * M]
            ndiags = min(nx // M - k, ny // M)
        else:
            k = -k
            B = A[k * M]
            ndiags = min(nx // M, ny // M - k)
        return as_strided(B,
                          shape=(ndiags, M, M),
                          strides=((nx * M + M) * A.itemsize, nx * A.itemsize,
                                   A.itemsize))

    def calculate_curvature(self, vel_normalised, vel_magnitude, velocity):
        s = vel_normalised.shape
        acceleration = np.gradient(velocity, axis=0).reshape(-1, 3)
        ttm = vel_normalised.reshape(-1, 1).dot(vel_normalised.reshape(1, -1))
        orthogonal_projector = self.extract_block_diag(
            (np.eye(ttm.shape[0]) - ttm), 3)
        temp = np.array([
            orthogonal_projector[i, :, :].dot(acceleration[i, :])
            for i in range(orthogonal_projector.shape[0])
        ])
        curvature = np.divide(temp,
                              vel_magnitude.reshape(-1, 1)**2,
                              out=np.zeros_like(temp),
                              where=vel_magnitude.reshape(-1, 1) != 0)
        return curvature.reshape(s), orthogonal_projector.reshape(
            (s[0], s[1], s[2], s[2]))

    def fun(self, points):
        dist = self.compute_minimum_distance_to_objects(
            points.reshape((1, 1, 3)), self.obstacle_list)
        return np.array(self.cost_potential(dist))

    def gradient_cost_potential(self, robot_discretised_points):
        gradient_cost_potential = np.zeros(
            robot_discretised_points.reshape(-1, 3).shape)
        for i, points in enumerate(robot_discretised_points.reshape((-1, 3))):
            gradient_cost_potential[i, :] = opt.approx_fprime(
                points, self.fun, [1e-06, 1e-06, 1e-06])
        return np.array(gradient_cost_potential).reshape(
            robot_discretised_points.shape[0], -1, 3)

    def calculate_jacobian2(self,
                            robot_body_points,
                            joint_index,
                            trajectories=None):
        # Body Points: time X body points X 3
        # joint index: number of body points between joints as array
        # trajectory: time X number of joints
        joint_idxs = np.arange(self.nDoF)
        p_map = np.tril(np.ones((self.nDoF, self.nDoF), dtype=np.float32))
        t_joints = np.array(
            zip(*[
                self.franka_kin.fwd_kin(trajectory)
                for trajectory in trajectories
            ])[1])
        joint_axis = t_joints[:, :, :3, 2]
        joint_positions = t_joints[:, :7, :3,
                                   -1]  # Excluding the fixed joint at the end
        jacobian = np.zeros((robot_body_points.shape[0],
                             robot_body_points.shape[1], 3, self.nDoF))

        # s = robot_body_points.shape
        # robot_body_points = robot_body_points.reshape(-1, 3)
        for ti in range(trajectories.shape[0]):
            for i, points in enumerate(
                    np.split(robot_body_points, joint_index)[:-1]):
                for point in points:
                    for joint in joint_idxs:
                        if i > 0 and p_map[i - 1, joint]:
                            jacobian[ti, i, :, joint] = np.cross(
                                joint_axis[ti, joint, :],
                                point[ti] - joint_positions[ti, joint])
        return jacobian

    def calculate_jacobian(self,
                           robot_body_points,
                           joint_index,
                           joint_values=None):
        class ParentMap(object):
            def __init__(self, num_joints):
                self.joint_idxs = [i for i in range(num_joints)]
                self.p_map = np.zeros((num_joints, num_joints))
                for i in range(num_joints):
                    for j in range(num_joints):
                        if j <= i:
                            self.p_map[i][j] = True

            def is_parent(self, parent, child):
                if child not in self.joint_idxs or parent not in self.joint_idxs:
                    return False
                return self.p_map[child][parent]

        parent_map = ParentMap(7)

        if joint_values is None:
            joint_values = list(
                self.robot_state.get_current_state().joint_state.position)[:7]

        _, t_joints = self.franka_kin.fwd_kin(joint_values)
        joint_axis = t_joints[:, :3, 2]
        joint_positions = t_joints[:7, :3,
                                   3]  # Excluding the fixed joint at the end
        jacobian = list()
        for i, points in enumerate(
                np.split(robot_body_points, joint_index)[:-1]):
            # print i, len(points)
            if i == 0:
                for point in points:
                    jacobian.append(np.zeros((3, 7)))
            else:
                for point in points:
                    jacobian.append(np.zeros((3, 7)))
                    for joint in parent_map.joint_idxs:
                        if parent_map.is_parent(joint, i - 1):
                            # find cross product
                            col = np.cross(joint_axis[joint, :],
                                           point - joint_positions[joint])
                            jacobian[-1][0][joint] = col[0]
                            jacobian[-1][1][joint] = col[1]
                            jacobian[-1][2][joint] = col[2]
                        else:
                            jacobian[-1][0][joint] = 0.0
                            jacobian[-1][1][joint] = 0.0
                            jacobian[-1][2][joint] = 0.0
        return np.array(jacobian)

    def calculate_obstacle_cost_gradient(self, trajectoryFlat):
        s = trajectoryFlat.shape
        trajectory = np.squeeze(trajectoryFlat).reshape((self.nDoF, -1)).T
        robot_discretised_points = self.calculate_robot_body_points(trajectory)
        vel_normalised, vel_magnitude, velocity = self.calculate_normalised_workspace_velocity(
            robot_discretised_points)
        curvature, orthogonal_projector = self.calculate_curvature(
            vel_normalised, vel_magnitude, velocity)
        dist = self.compute_minimum_distance_to_objects(
            robot_discretised_points[:-1],
            self.obstacle_list,
        )
        obstacle_cost_potential = np.array(self.cost_potential(dist))
        gradient_cost_potential = self.gradient_cost_potential(
            robot_discretised_points[:-1])
        obstacle_gradient = np.zeros((trajectory.shape[0], self.nDoF))
        # jacobian1 = self.calculate_jacobian2(robot_discretised_points[:-1], self.j_index, trajectory)
        a = robot_discretised_points[:-1]
        for jvs in range(trajectory.shape[0]):
            obst_grad = np.zeros(trajectory.shape[1])
            jacobian = self.calculate_jacobian(a[jvs], self.j_index,
                                               trajectory[jvs])
            for num_points in range(robot_discretised_points.shape[1]):
                temp1 = orthogonal_projector[jvs, num_points].dot(
                    gradient_cost_potential[jvs, num_points, :])
                temp2 = obstacle_cost_potential[jvs, num_points] * curvature[
                    jvs, num_points, :]
                temp3 = vel_magnitude[jvs, num_points] * (temp1 - temp2)
                obst_grad += jacobian[num_points, :].T.dot(temp3)
            obstacle_gradient[jvs, :] = obst_grad
        return obstacle_gradient.T

    def cost_gradient_analytic(
        self, trajectoryFlat
    ):  # calculate grad(cost) = grad(smoothness_cost) + grad(obstacle_cost)
        smoothness_gradient = self.calculate_smoothness_gradient(
            trajectoryFlat)
        if self.obstacle_list is not None:
            obstacle_gradient = self.calculate_obstacle_cost_gradient(
                trajectoryFlat)
        else:
            obstacle_gradient = np.zeros(len(trajectoryFlat))
        trajectory = np.squeeze(trajectoryFlat)
        cost_gradient = self.lamda_obs * obstacle_gradient.reshape(
            (len(trajectory), 1)) + self.lamda_smooth * smoothness_gradient
        return np.squeeze(cost_gradient)

    def cost_gradient_numeric(self, trajectory):
        trajectory = np.squeeze(trajectory)
        obst_cost_grad_numeric = opt.approx_fprime(
            trajectory, traj_opt.obstacle_cost,
            1e-08 * np.ones(len(trajectory)))
        smoothness_gradient = np.squeeze(
            self.calculate_smoothness_gradient(trajectory))
        return np.squeeze(obst_cost_grad_numeric + smoothness_gradient)

    def optim_callback(self, xk):
        self.costs.append(self.calculate_total_cost(xk)[0, 0])
        self.optCurve.append(xk)
        print 'Iteration {}: {:2.4}\n'.format(
            len(self.optCurve), self.costs[len(self.optCurve) - 1])

    def animation(self, optimized_trajectory, initial_trajectory):
        fig = plt.figure()
        ax = fig.add_subplot(111, projection="3d")
        # ax.axis('off')
        plt.show(block=False)
        while True:
            for i in range(len(optimized_trajectory)):
                _, T_joint_optim = self.franka_kin.fwd_kin(
                    optimized_trajectory[i])
                _, T_joint_init = self.franka_kin.fwd_kin(
                    initial_trajectory[i])
                ax.clear()
                if self.obstacle_list is not None:
                    for object in self.obstacle_list:
                        self.sphere(ax, object[-1], object[0:-1])
                self.franka_kin.plotter(ax,
                                        T_joint_optim,
                                        'optim',
                                        color='blue')
                self.franka_kin.plotter(ax, T_joint_init, 'init', color='red')
                fig.canvas.draw()
                fig.canvas.flush_events()
                plt.pause(0.01)
            plt.pause(1)
Esempio n. 6
0
    def promp_planner(self,
                      mu_x,
                      sig_x,
                      mu_quat,
                      sig_quat,
                      obstacle_list,
                      Qlists,
                      timeLists,
                      PromP_Planner=True):
        time_normalised = np.linspace(0, 1, 35)
        nDoF, nBf = 7, 5
        cur_jv = self.group.get_current_joint_values()
        weight_space_optim = optim_weight_space(time_normalised,
                                                nDoF,
                                                nBf,
                                                mu_x,
                                                sig_x,
                                                mu_quat,
                                                sig_quat,
                                                obstacle_list,
                                                curr_jvs=cur_jv,
                                                QLists=Qlists,
                                                timeLists=timeLists)
        weights = np.random.multivariate_normal(
            weight_space_optim.mean_cond_weight,
            weight_space_optim.covMat_cond_weight)
        des_jv = weight_space_optim.post_mean_q

        if not PromP_Planner:
            ################ Trajectory space optimization: CHOMP

            franka_kin = FrankaKinematics()
            n = np.linalg.norm((des_jv - cur_jv)) / (len(time_normalised) - 1)

            traj2optimise = self.discretize(cur_jv, des_jv, step_size=n)
            traj2optimise = np.insert(
                traj2optimise, len(traj2optimise), des_jv,
                axis=0)  # inserting goal state at the end of discretized
            traj2optimise = np.insert(traj2optimise, 0, cur_jv, axis=0)
            print 'chomp n', n, traj2optimise.shape[0]

            traj_opt = TrajectoryOptimize(7,
                                          obstacle_list=obstacle_list,
                                          ini_jv=cur_jv,
                                          des_jv=des_jv)

            fdm, _ = traj_opt.finite_diff_matrix(traj2optimise)
            fdm_inv = np.linalg.inv(fdm)
            traj_flat = traj2optimise.T.reshape((-1))
            epsilon_k = np.random.multivariate_normal(
                mean=np.zeros(len(traj_flat)),
                cov=fdm_inv * (1. / len(traj_flat)))
            traj_flat += epsilon_k
            traj2optimise = (traj_flat.reshape(
                (nDoF, -1))).T  # trajectory initialization as in STOMP

            start = time.time()
            opti_traj, costs, success = traj_opt.optimise(traj2optimise,
                                                          withGrad=True)
            total_time = time.time() - start
            print total_time

            save_path = '/home/automato/Ash/MPlib/src/ProMPlib/going_under_table/Simulations/CHOMP/'
            uniq_name = str(time.time())
            np.savetxt(save_path + 'traj_CHOMP_%s.out' % uniq_name,
                       opti_traj,
                       delimiter=',')
            np.savetxt(save_path + 'costs_%s.out' % uniq_name,
                       costs,
                       delimiter=',')
            T, _ = franka_kin.fwd_kin(opti_traj[-1])
            quat = np.array(tf_tran.quaternion_from_matrix(T))
            print 'quat_diff = ', quat - mu_quat
            print '#########'
            print 'pos_diff = ', T[:3, 3] - mu_x

            vel, accel, tme = self.create_q_v_a(opti_traj)
            rt = self.create_trajectory(opti_traj, vel, accel, tme)
            rt_back = self.create_trajectory(np.flipud(opti_traj),
                                             np.flipud(vel), np.flipud(accel),
                                             tme)
            smooth_cost_promp = 0.0

        ##################################
        else:
            # Weight space optimization:

            trajectoryFlat = weight_space_optim.basisMultiDoF.dot(weights)
            init_traj = (trajectoryFlat.reshape((nDoF, -1))).T
            init_traj = init_traj[1:-1]
            init_traj = np.insert(init_traj, 0, cur_jv, axis=0)
            init_traj = np.insert(init_traj,
                                  init_traj.shape[0],
                                  des_jv,
                                  axis=0)

            start = time.time()
            opti_traj, opt_weights, costs, success = weight_space_optim.optimise(
                weights, withGrad=True)
            smooth_cost_promp = weight_space_optim.smoothness_cost(opt_weights)
            total_time = time.time() - start
            print total_time

            save_path = '/home/automato/Ash/MPlib/src/ProMPlib/going_under_table/Simulations/ProMP/'
            uniq_name = str(time.time())
            np.savetxt(save_path + 'traj_promp_%s.out' % uniq_name,
                       opti_traj,
                       delimiter=',')
            np.savetxt(save_path + 'weights_promp_%s.out' % uniq_name,
                       opt_weights,
                       delimiter=',')
            np.savetxt(save_path + 'costs_%s.out' % uniq_name,
                       costs,
                       delimiter=',')

            # To plot demonstrated trajectories Vs time

            # scale = 1
            # for plotDoF in range(7):
            #     plt.figure()
            #     for i in range(init_traj.shape[0]):
            #         plt.plot(time_normalised, init_traj[:, 5], color='red', linestyle='--', label='initial trajectory')
            #         plt.plot(time_normalised, opti_traj[:, 5], color='green', label='optimized trajectory')
            #     # plt.xlim(1 * scale, 1 * scale)
            #     plt.ylim(1 * scale, 3 * scale)
            #     plt.title('DoF {}'.format(plotDoF))
            #     plt.xlabel('time')

            franka_kin = FrankaKinematics()
            T, _ = franka_kin.fwd_kin(opti_traj[-1])
            quat = np.array(tf_tran.quaternion_from_matrix(T))
            print 'quat_diff = ', quat - mu_quat
            print '#########'
            print 'pos_diff = ', T[:3, 3] - mu_x
            vel, accel, tme = self.create_q_v_a(opti_traj)
            rt = self.create_trajectory(opti_traj, vel, accel, tme)
            rt_back = self.create_trajectory(np.flipud(opti_traj),
                                             np.flipud(vel), np.flipud(accel),
                                             tme)

        return opti_traj, total_time, rt, rt_back, smooth_cost_promp, (quat - mu_quat)/mu_quat, \
               (T[:3, 3] - mu_x)/mu_x, success
Esempio n. 7
0
                #     "enter 0: RRTConnectkConfigDefault, 1: PRMkConfigDefault, 2: CHOMP, "
                #     "3: ProMP\n").strip())
                planner_index = 3

                # idxx = 0 # int(raw_input('Enter sample mu_x and Quart: 0 - 35 \n').strip())
                for idxx in range(102):
                    print idxx
                    if planner_index == 0 or planner_index == 1:
                        planner_id = planner_ids[planner_index]
                        move_robot.group.set_planner_id(planner_id)

                        plan, plan_time = move_robot.plan(
                            mu_x[idxx][0], mu_x[idxx][1], mu_x[idxx][2],
                            Quaternion[idxx][0], Quaternion[idxx][1],
                            Quaternion[idxx][2], Quaternion[idxx][3])
                        franka_kin = FrankaKinematics()
                        # if not isinstance(plan, (list, tuple, np.ndarray)):
                        if plan.joint_trajectory.points:
                            #     n = len(plan.joint_trajectory.points)
                            #     joint_positions = np.zeros((n, 7))
                            #     for i in range(n):
                            #         joint_positions[i, :] = plan.joint_trajectory.points[i].positions
                            # if plan is not None:
                            final_jv = plan.joint_trajectory.points[
                                -1].positions
                            T, _ = franka_kin.fwd_kin(final_jv)
                            quat = np.array(tf_tran.quaternion_from_matrix(T))
                            quat_err = (quat -
                                        Quaternion[idxx]) / Quaternion[idxx]
                            pos_err = (T[:3, 3] - mu_x[idxx]) / mu_x[idxx]
                            save_path = '/home/automato/Ash/MPlib/src/ProMPlib/going_under_table/RRT/'
Esempio n. 8
0
class CostFunction(object):
    def __init__(self):
        super(CostFunction, self).__init__()
        moveit_commander.roscpp_initialize(sys.argv)
        self.collision_threshold = 0.07
        self.robot_state = moveit_commander.RobotCommander()
        self.scene = moveit_commander.PlanningSceneInterface()
        self.franka_k = FrankaKinematics()

        def show_objects(self):
            for k, v in self.scene.get_objects().items():
                print "Pos:", v.primitive_poses[0].position.x, v.primitive_poses[0].position.y,\
                    v.primitive_poses[0].position.z
                print "Ori:", v.primitive_poses[0].orientation.x, v.primitive_poses[0].orientation.y,\
                    v.primitive_poses[0].orientation.z, v.primitive_poses[0].orientation.w
                print "Size:", v.primitives[0].dimensions

    def setup_planner(self):
        self.group = moveit_commander.MoveGroupCommander("panda_arm")
        self.group.set_end_effector_link(
            "panda_hand")  # planning wrt to panda_hand or link8
        self.group.set_max_velocity_scaling_factor(
            0.05)  # scaling down velocity
        self.group.set_max_acceleration_scaling_factor(
            0.05)  # scaling down velocity
        self.group.allow_replanning(True)
        self.group.set_num_planning_attempts(5)
        self.group.set_goal_position_tolerance(0.0002)
        self.group.set_goal_orientation_tolerance(0.01)
        self.group.set_planning_time(5)
        self.group.set_planner_id("FMTkConfigDefault")

    def get_robot_discretised_points(self,
                                     joint_values=None,
                                     step_size=0.2,
                                     with_joint_index=False):

        if joint_values is None:
            joint_values = list(
                self.robot_state.get_current_state().joint_state.position)[:7]

        _, t_joints = self.franka_k.fwd_kin(joint_values)
        fwd_k_j_positions = np.vstack(([0., 0., 0.], t_joints[:, :3, 3]))
        discretised = list()
        j_index = list()
        for j in range(len(fwd_k_j_positions) - 1):
            w = fwd_k_j_positions[j + 1] - fwd_k_j_positions[j]
            if len(w[w != 0.]):
                step = step_size * w / np.linalg.norm(w)
                n = int(np.linalg.norm(w) / np.linalg.norm(step)) + 1
                discretised.extend(
                    np.outer(np.arange(1, n), step) + fwd_k_j_positions[j])
            j_index.append(len(discretised))
        return (np.array(discretised),
                j_index) if with_joint_index else np.array(discretised)

    def get_object_collision_spheres(self):
        return [(v.primitive_poses[0].position.x, v.primitive_poses[0].position.y, v.primitive_poses[0].position.z,\
                    v.primitives[0].dimensions[0]) for v in self.scene.get_objects().values()]

    def compute_minimum_distance_to_objects(
        self,
        robot_body_points,
        object_list=None,
    ):
        if object_list is None:
            object_list = self.get_object_collision_spheres()
        D = list()
        if len(robot_body_points.shape) == 1:
            robot_body_points = robot_body_points.reshape(1, 3)

        for r in robot_body_points:  # expects robot_body_points as an array of dimension 1 x n
            dist = []
            for o in object_list:
                ro = r - o[:3]
                norm_ro = np.linalg.norm(ro)
                dist.append(norm_ro - 0.15 - o[3])
            D.append(np.min(np.array(dist)))
        return D

    def cost_potential(self, D):
        c = list()
        for d in D:
            if d < 0.:
                c.append(-d + 0.5 * self.collision_threshold)
            elif d <= self.collision_threshold:
                c.append((0.5 * (d - self.collision_threshold)**2) /
                         self.collision_threshold)
            else:
                c.append(0)
        return c

    def calculate_normalised_workspace_velocity(self, trajectory):
        # We have not divided by  time as this has been indexed and is thus not available
        position_vectors = np.array([
            self.get_robot_discretised_points(joint_values)
            for joint_values in trajectory
        ])
        velocity = np.gradient(position_vectors, axis=0)
        vel_magnitude = np.linalg.norm(velocity, axis=2)
        vel_normalised = np.divide(velocity,
                                   vel_magnitude[:, :, None],
                                   out=np.zeros_like(velocity),
                                   where=vel_magnitude[:, :, None] != 0)
        return vel_normalised, vel_magnitude, velocity

    def calculate_jacobian(self,
                           robot_body_points,
                           joint_index,
                           joint_values=None):
        class ParentMap(object):
            def __init__(self, num_joints):
                self.joint_idxs = [i for i in range(num_joints)]
                self.p_map = np.zeros((num_joints, num_joints))
                for i in range(num_joints):
                    for j in range(num_joints):
                        if j <= i:
                            self.p_map[i][j] = True

            def is_parent(self, parent, child):
                if child not in self.joint_idxs or parent not in self.joint_idxs:
                    return False
                return self.p_map[child][parent]

        parent_map = ParentMap(7)

        if joint_values is None:
            joint_values = list(
                self.robot_state.get_current_state().joint_state.position)[:7]

        _, t_joints = self.franka_k.fwd_kin(joint_values)
        joint_axis = t_joints[:, :3, 2]
        joint_positions = t_joints[:7, :3,
                                   3]  # Excluding the fixed joint at the end
        jacobian = list()
        for i, points in enumerate(
                np.split(robot_body_points, joint_index)[:-1]):
            # print i, len(points)
            if i == 0:
                for point in points:
                    jacobian.append(np.zeros((3, 7)))
            else:
                for point in points:
                    jacobian.append(np.zeros((3, 7)))
                    for joint in parent_map.joint_idxs:
                        if parent_map.is_parent(joint, i - 1):
                            # find cross product
                            col = np.cross(joint_axis[joint, :],
                                           point - joint_positions[joint])
                            jacobian[-1][0][joint] = col[0]
                            jacobian[-1][1][joint] = col[1]
                            jacobian[-1][2][joint] = col[2]
                        else:
                            jacobian[-1][0][joint] = 0.0
                            jacobian[-1][1][joint] = 0.0
                            jacobian[-1][2][joint] = 0.0
        return np.array(jacobian)

    def calculate_curvature(self, trajectory):
        vel_normalised, vel_magnitude, velocity = self.calculate_normalised_workspace_velocity(
            trajectory)
        temp = (np.eye(len(vel_normalised)) -
                vel_normalised.dot(vel_normalised.T))
        curvature = np.dot(temp, np.gradient(velocity)) / vel_magnitude**2
        return curvature
Esempio n. 9
0
    def __init__(self, time, nDoF, nBf, mu_x=[0.543602, -0.239265, 0.470648], sig_x=np.eye(3) * 0.0000002,
                 mu_quat=[0.724822, -0.282179, 0.544974, -0.313067], sig_quat=np.eye(4) * 0.0002,
                 obstacle_list=None, curr_jvs=None, QLists=None, timeLists=None):
        self.time_normalised = time
        self.nDoF = nDoF
        if curr_jvs is None:
            self.curr_jvs = Q[2][0, :-2]  # np.array([-0.25452656, -0.3225854, -0.24426211, -0.3497535 ,  0.06971882,  0.12819999,  0.65348821])
        else:
            self.curr_jvs = curr_jvs
        self.obstacle_list = obstacle_list
        self.franka_kin = FrankaKinematics()

        self.mu_x = mu_x
        self.sig_x = sig_x

        self.mu_quat_des = mu_quat
        self.sig_quat = sig_quat

        self.collision_threshold = 0.07
        # self.obstacle_list = np.array([[0.25, 0.0, 0.71, 0.1], [-0.15, 0.21, 0.51, 0.05]])  # for two spheres
        self.phaseGenerator = phase.LinearPhaseGenerator()
        #self.phaseGenerator = phase.SmoothPhaseGenerator(duration = 1)
        self.basisGenerator = basis.NormalizedRBFBasisGenerator(self.phaseGenerator, numBasis=nBf, duration=1,
                                                           basisBandWidthFactor=3,
                                                           numBasisOutside=1)
        self.basisMultiDoF = self.basisGenerator.basisMultiDoF(self.time_normalised, self.nDoF)
        self.learnedProMP = promps.ProMP(self.basisGenerator, self.phaseGenerator, self.nDoF)
        self.learner = promps.MAPWeightLearner(self.learnedProMP)
        self.Q_parsed, self.timeP = self.Q_parser(self.mu_x)
        # self.learnedData = self.learner.learnFromData(self.Q_parsed, self.timeP)
        if QLists is None:
            QLists = A
        else:
            QLists = QLists
        if timeLists is None:
            timeList = timeData
        else:
            timeList = timeLists
        self.learnedData = self.learner.learnFromData(QLists, timeList)

        self.mu_theta, self.sig_theta = self.learnedProMP.getMeanAndCovarianceTrajectory(np.array([1.0]))
        self.sig_theta = np.squeeze(self.sig_theta)

        self.post_mean_q, self.post_cov_q = self.franka_kin.inv_kin_ash_pose_quaternion(np.squeeze(self.mu_theta),
                                                self.sig_theta, self.mu_x, self.sig_x, self.mu_quat_des, self.sig_quat)
        self.taskProMP0 = self.learnedProMP.jointSpaceConditioning(0, desiredTheta=self.curr_jvs, desiredVar=np.eye(len(self.curr_jvs)) * 0.00001)
        self.taskProMP = self.taskProMP0.jointSpaceConditioning(1.0, desiredTheta=self.post_mean_q, desiredVar=np.eye(len(self.curr_jvs)) * 0.00001) #desiredVar=self.post_cov_q)

        self.trajectories_learned = self.learnedProMP.getTrajectorySamples(self.time_normalised, n_samples=20)
        self.trajectories_task_conditioned = self.taskProMP.getTrajectorySamples(self.time_normalised, n_samples=20)

        self.mean_cond_weight = self.taskProMP.mu
        self.covMat_cond_weight = self.taskProMP.covMat
        self.inv_covMat_cond = np.linalg.inv(self.covMat_cond_weight)

        self.trajectoryFlat = self.basisMultiDoF.dot(self.mean_cond_weight)
        self.trajectory = (self.trajectoryFlat.reshape((self.nDoF, self.trajectoryFlat.shape[0] / self.nDoF))).T
        # self.initial_joint_values = self.trajectory[0, :]
        self.initial_joint_values = self.curr_jvs  #Q[2][0, :-2]  #  np.array([-0.25452656, -0.3225854, -0.24426211, -0.3497535 ,  0.06971882,  0.12819999,  0.65348821])
        self.desired_joint_values = self.trajectory[-1, :]    # same as self.post_mean_q

        self.reguCoeff = 0.003
        self.lamda_smooth, self.lamda_obs = 10.0, 20.0
        self.optCurve, self.costs = [], []
        self.step_size = 0.06
Esempio n. 10
0
class optim_weight_space(object):
    def __init__(self, time, nDoF, nBf, mu_x=[0.543602, -0.239265, 0.470648], sig_x=np.eye(3) * 0.0000002,
                 mu_quat=[0.724822, -0.282179, 0.544974, -0.313067], sig_quat=np.eye(4) * 0.0002,
                 obstacle_list=None, curr_jvs=None, QLists=None, timeLists=None):
        self.time_normalised = time
        self.nDoF = nDoF
        if curr_jvs is None:
            self.curr_jvs = Q[2][0, :-2]  # np.array([-0.25452656, -0.3225854, -0.24426211, -0.3497535 ,  0.06971882,  0.12819999,  0.65348821])
        else:
            self.curr_jvs = curr_jvs
        self.obstacle_list = obstacle_list
        self.franka_kin = FrankaKinematics()

        self.mu_x = mu_x
        self.sig_x = sig_x

        self.mu_quat_des = mu_quat
        self.sig_quat = sig_quat

        self.collision_threshold = 0.07
        # self.obstacle_list = np.array([[0.25, 0.0, 0.71, 0.1], [-0.15, 0.21, 0.51, 0.05]])  # for two spheres
        self.phaseGenerator = phase.LinearPhaseGenerator()
        #self.phaseGenerator = phase.SmoothPhaseGenerator(duration = 1)
        self.basisGenerator = basis.NormalizedRBFBasisGenerator(self.phaseGenerator, numBasis=nBf, duration=1,
                                                           basisBandWidthFactor=3,
                                                           numBasisOutside=1)
        self.basisMultiDoF = self.basisGenerator.basisMultiDoF(self.time_normalised, self.nDoF)
        self.learnedProMP = promps.ProMP(self.basisGenerator, self.phaseGenerator, self.nDoF)
        self.learner = promps.MAPWeightLearner(self.learnedProMP)
        self.Q_parsed, self.timeP = self.Q_parser(self.mu_x)
        # self.learnedData = self.learner.learnFromData(self.Q_parsed, self.timeP)
        if QLists is None:
            QLists = A
        else:
            QLists = QLists
        if timeLists is None:
            timeList = timeData
        else:
            timeList = timeLists
        self.learnedData = self.learner.learnFromData(QLists, timeList)

        self.mu_theta, self.sig_theta = self.learnedProMP.getMeanAndCovarianceTrajectory(np.array([1.0]))
        self.sig_theta = np.squeeze(self.sig_theta)

        self.post_mean_q, self.post_cov_q = self.franka_kin.inv_kin_ash_pose_quaternion(np.squeeze(self.mu_theta),
                                                self.sig_theta, self.mu_x, self.sig_x, self.mu_quat_des, self.sig_quat)
        self.taskProMP0 = self.learnedProMP.jointSpaceConditioning(0, desiredTheta=self.curr_jvs, desiredVar=np.eye(len(self.curr_jvs)) * 0.00001)
        self.taskProMP = self.taskProMP0.jointSpaceConditioning(1.0, desiredTheta=self.post_mean_q, desiredVar=np.eye(len(self.curr_jvs)) * 0.00001) #desiredVar=self.post_cov_q)

        self.trajectories_learned = self.learnedProMP.getTrajectorySamples(self.time_normalised, n_samples=20)
        self.trajectories_task_conditioned = self.taskProMP.getTrajectorySamples(self.time_normalised, n_samples=20)

        self.mean_cond_weight = self.taskProMP.mu
        self.covMat_cond_weight = self.taskProMP.covMat
        self.inv_covMat_cond = np.linalg.inv(self.covMat_cond_weight)

        self.trajectoryFlat = self.basisMultiDoF.dot(self.mean_cond_weight)
        self.trajectory = (self.trajectoryFlat.reshape((self.nDoF, self.trajectoryFlat.shape[0] / self.nDoF))).T
        # self.initial_joint_values = self.trajectory[0, :]
        self.initial_joint_values = self.curr_jvs  #Q[2][0, :-2]  #  np.array([-0.25452656, -0.3225854, -0.24426211, -0.3497535 ,  0.06971882,  0.12819999,  0.65348821])
        self.desired_joint_values = self.trajectory[-1, :]    # same as self.post_mean_q

        self.reguCoeff = 0.003
        self.lamda_smooth, self.lamda_obs = 10.0, 20.0
        self.optCurve, self.costs = [], []
        self.step_size = 0.06

    def Q_parser(self, mu_x):
        QQ, tme = [], []
        for i in range(len(Q)):
            jvs = Q[i][-1, :]
            T, _ = self.franka_kin.fwd_kin(jvs)
            endEffPos = T[:3, 3]
            dist = np.linalg.norm((mu_x - endEffPos))
            if dist <= 0.5:
                QQ.append(Q[i])
                tme.append(timeData[i])
        return QQ, tme

    def sphere(self, ax, radius, centre):
        u = np.linspace(0, 2 * np.pi, 13)
        v = np.linspace(0, np.pi, 7)
        x = centre[0] + radius * np.outer(np.cos(u), np.sin(v))
        y = centre[1] + radius * np.outer(np.sin(u), np.sin(v))
        z = centre[2] + radius * np.outer(np.ones(np.size(u)), np.cos(v))
        xdata = scipy.ndimage.zoom(x, 3)
        ydata = scipy.ndimage.zoom(y, 3)
        zdata = scipy.ndimage.zoom(z, 3)
        ax.plot_surface(xdata, ydata, zdata, rstride=3, cstride=3, color='w', shade=0)

    def smoothness_objective(self, trajectoryFlat):   # used only to find the smoothness cost of traj sampled from ProMP
        trajectoryFlat = np.squeeze(trajectoryFlat)
        trajectory = trajectoryFlat.reshape((self.nDoF, -1)).T
        dim = np.multiply(*trajectory.shape)
        fd_matrix, b = self.finite_diff_matrix(trajectory)
        trajectory = trajectory.T.reshape((dim, 1))
        F_smooth = 0.5*(np.dot(trajectory.T, np.dot(fd_matrix, trajectory)) + np.dot(trajectory.T, b) + 0.25*np.dot(b.T, b))
        return F_smooth

    def promp_sampled_trajectory_cost(self, trajectories):  # trajectories is 3D array of (time x nDoF x nSamples)
        s = trajectories.shape
        smoothness_cost_chomp = np.zeros(s[2])   #  smoothness cost as described in chomp paper
        obstacle_cost = np.zeros(s[2])
        for i in range(s[2]):
            trajectory = trajectories[:, :, i]
            trajectoryFlat = trajectory.T.reshape((-1))
            smoothness_cost_chomp[i] = self.smoothness_objective(trajectoryFlat)
            if self.obstacle_list:
                obstacle_cost[i] = self.obstacle_cost(trajectoryFlat, self.obstacle_list)
        return smoothness_cost_chomp, obstacle_cost

    def optimise(self, weights, withGrad=True):

        if not withGrad:
        ################## Without Gradient #########################
            start = tme.time()
            optimized_weights = opt.minimize(self.calculate_total_cost, weights, method='BFGS',
                                            options={'maxiter': 150, 'disp': True},
                                            callback=self.optim_callback)
            total_time = tme.time() - start
            print 'ProMP time:without gradient:', total_time
            trajectoryFlat = self.basisMultiDoF.dot(optimized_weights.x)
            optimized_trajectory = trajectoryFlat.reshape((self.nDoF, -1)).T
            optimized_trajectory = optimized_trajectory[1:-1]
            optimized_trajectory = np.insert(optimized_trajectory, 0, self.initial_joint_values, axis=0)
            optimized_trajectory = np.insert(optimized_trajectory, optimized_trajectory.shape[0],
                                            self.desired_joint_values, axis=0)

        else:
            # ################### With Gradient ############################
            start = tme.time()
            optimized_weights = opt.minimize(self.calculate_total_cost, weights, method='BFGS', jac=self.cost_gradient_analytic,
                                                  options={'maxiter': 150, 'disp': True, 'gtol': 1e-6}, callback=self.optim_callback)
            total_time = tme.time() - start
            print 'ProMP time:with gradient:', total_time

            trajectoryFlat = self.basisMultiDoF.dot(optimized_weights.x)
            optimized_trajectory = (trajectoryFlat.reshape((self.nDoF, -1))).T
            optimized_trajectory = optimized_trajectory[1:-1]
            optimized_trajectory = np.insert(optimized_trajectory, 0, self.initial_joint_values, axis=0)
            optimized_trajectory = np.insert(optimized_trajectory, optimized_trajectory.shape[0], self.desired_joint_values, axis=0)

        return optimized_trajectory, optimized_weights.x, self.costs, optimized_weights.success

    def calculate_jacobian(self, robot_body_points, joint_index, joint_values=None):
        class ParentMap(object):
            def __init__(self, num_joints):
                self.joint_idxs = [i for i in range(num_joints)]
                self.p_map = np.zeros((num_joints, num_joints))
                for i in range(num_joints):
                    for j in range(num_joints):
                        if j <= i:
                            self.p_map[i][j] = True

            def is_parent(self, parent, child):
                if child not in self.joint_idxs or parent not in self.joint_idxs:
                    return False
                return self.p_map[child][parent]

        parent_map = ParentMap(7)

        if joint_values is None:
            joint_values = list(self.robot_state.get_current_state().joint_state.position)[:7]

        _, t_joints = self.franka_kin.fwd_kin(joint_values)
        joint_axis = t_joints[:, :3, 2]
        joint_positions = t_joints[:7, :3, 3]  # Excluding the fixed joint at the end
        jacobian = list()
        for i, points in enumerate(np.split(robot_body_points, joint_index)[:-1]):
            # print i, len(points)
            if i == 0:
                for point in points:
                    jacobian.append(np.zeros((3, 7)))
            else:
                for point in points:
                    jacobian.append(np.zeros((3, 7)))
                    for joint in parent_map.joint_idxs:
                        if parent_map.is_parent(joint, i-1):
                            # find cross product
                            col = np.cross(joint_axis[joint, :], point-joint_positions[joint])
                            jacobian[-1][0][joint] = col[0]
                            jacobian[-1][1][joint] = col[1]
                            jacobian[-1][2][joint] = col[2]
                        else:
                            jacobian[-1][0][joint] = 0.0
                            jacobian[-1][1][joint] = 0.0
                            jacobian[-1][2][joint] = 0.0
        return np.array(jacobian)

    def finite_diff_matrix(self, trajectory):
        rows, columns = trajectory.shape  # columns = nDoF
        A = 2 * np.eye(rows)
        A[0, 1] = -1
        A[rows-1, rows-2] = -1
        for ik in range(0, rows-2):
            A[ik + 1, ik] = -1
            A[ik + 1, ik + 2] = -1

        dim = rows*columns
        fd_matrix = np.zeros((dim, dim))
        b = np.zeros((dim, 1))
        i, j = 0, 0
        while i < dim:
            fd_matrix[i:i+len(A), i:i+len(A)] = A
            b[i] = -2 * self.initial_joint_values[j]
            b[i+len(A)-1] = -2 * self.desired_joint_values[j]
            i = i + len(A)
            j = j + 1
        return fd_matrix, b

    def get_robot_discretised_points(self, fwd_k_j_positions, step_size=0.2):
        discretised = list()
        j_index = list()
        # self.get_robot_discretised_joint_index(fwd_k_j_positions, step_size=0.2)
        for j in range(len(fwd_k_j_positions) - 1):
            w = fwd_k_j_positions[j+1] - fwd_k_j_positions[j]
            if len(w[w != 0.]):
                step = step_size * w / np.linalg.norm(w)
                n = int(np.linalg.norm(w) / np.linalg.norm(step)) + 1
                discretised.extend(np.outer(np.arange(1, n), step) + fwd_k_j_positions[j])
            j_index.append(len(discretised))
        self.j_index = j_index
        return np.array(discretised)

    def get_robot_joint_positions(self, joint_values):
        _, t_joints = self.franka_kin.fwd_kin(joint_values)
        return np.vstack(([0., 0., 0.], t_joints[:, :3, 3]))

    def calculate_robot_body_points(self, trajectory):
        # trajectory = np.vstack((trajectory, self.desired_joint_values))
        return np.array([self.get_robot_discretised_points(self.get_robot_joint_positions(joint_values), self.step_size,
                                                           ) for joint_values in trajectory])

    def calculate_normalised_workspace_velocity(self, robot_body_points):
        velocity = np.gradient(robot_body_points, axis=0)
        vel_magnitude = np.linalg.norm(velocity, axis=2)
        vel_normalised = np.divide(velocity, vel_magnitude[:, :, None], out=np.zeros_like(velocity), where=vel_magnitude[:, :, None] != 0)
        return vel_normalised, vel_magnitude, velocity

    def smoothness_cost(self, weights):
        temp1 = (weights - self.mean_cond_weight).reshape(-1, 1)
        temp2 = temp1.T.dot(self.inv_covMat_cond)
        return 0.5 * temp2.dot(temp1) + 0.5 * self.reguCoeff * weights.dot(weights)

    def obstacle_cost(self, trajectoryFlat, obstacle_list,):
        trajectory = trajectoryFlat.reshape((self.nDoF, -1)).T
        # trajectory = trajectory[1:-1]
        robot_body_points = self.calculate_robot_body_points(trajectory)
        vel_normalised, vel_mag, vel = self.calculate_normalised_workspace_velocity(robot_body_points)
        dist = self.compute_minimum_distance_to_objects(robot_body_points, obstacle_list)
        obstacle_cost_potential = np.array(self.cost_potential(dist))
        return np.sum(np.multiply(obstacle_cost_potential, vel_mag))

    def calculate_total_cost(self, weights):
        weights = np.squeeze(weights)
        trajectoryFlat = self.basisMultiDoF.dot(weights)
        smoothness_cost = self.smoothness_cost(weights)  # smoothness of trajectory is captured here
        if self.obstacle_list is not None:
            obstacle_cost = self.obstacle_cost(trajectoryFlat, self.obstacle_list)
        else:
            obstacle_cost = 0.0
        # return 0.001 * smoothness_cost + 1.5 * obstacle_cost   #  for without gradient
        return self.lamda_smooth * smoothness_cost + self.lamda_obs * obstacle_cost    #  for with gradient

    def smoothness_gradient(self, weights):
        return self.inv_covMat_cond.dot(weights - self.mean_cond_weight) + self.reguCoeff * weights

    def compute_minimum_distance_to_objects(self, robot_body_points, obstacle_list, body_sphere_size=0.12):
        rbp_shape = robot_body_points.shape
        return np.min(
            distance.cdist(
                robot_body_points.reshape(-1, 3, order='A'),
                obstacle_list[:, :3]
            ) - obstacle_list[:, 3] - body_sphere_size,
            axis=1
        ).reshape(rbp_shape[:2])

    def cost_potential(self, D, collision_threshold=0.07):
        c = np.zeros(D.shape)
        return np.where(
            D < 0,
            -D + 0.5 * collision_threshold,
            np.where(
                D <= collision_threshold,
                (0.5 * (D - collision_threshold) ** 2) / collision_threshold,
                c
            )
        )

    def fun(self, points):
        dist = self.compute_minimum_distance_to_objects(points.reshape((1, 1, 3)), self.obstacle_list)
        return np.array(self.cost_potential(dist))

    def gradient_cost_potential(self, robot_discretised_points):
        gradient_cost_potential = np.zeros(robot_discretised_points.reshape(-1, 3).shape)
        for i, points in enumerate(robot_discretised_points.reshape((-1, 3))):
            gradient_cost_potential[i, :] = opt.approx_fprime(points, self.fun, [1e-06, 1e-06, 1e-06])
        return np.array(gradient_cost_potential).reshape(robot_discretised_points.shape[0], -1, 3)

    def extract_block_diag(self, A, M=3, k=0):
        ny, nx = A.shape
        ndiags = min(map(lambda x: x // M, A.shape))
        offsets = (nx * M + M, nx, 1)
        strides = map(lambda x: x * A.itemsize, offsets)
        if k > 0:
            B = A[:, k * M]
            ndiags = min(nx // M - k, ny // M)
        else:
            k = -k
            B = A[k * M]
            ndiags = min(nx // M, ny // M - k)
        return as_strided(B, shape=(ndiags, M, M),
                          strides=((nx * M + M) * A.itemsize, nx * A.itemsize, A.itemsize))

    def calculate_curvature(self, vel_normalised, vel_magnitude, velocity):
        s = vel_normalised.shape
        acceleration = np.gradient(velocity, axis=0).reshape(-1, 3)
        ttm = vel_normalised.reshape(-1, 1).dot(vel_normalised.reshape(1, -1))
        orthogonal_projector = self.extract_block_diag((np.eye(ttm.shape[0]) - ttm), 3)
        temp = np.array([orthogonal_projector[i, :, :].dot(acceleration[i, :]) for i in range(orthogonal_projector.shape[0])])
        curvature = np.divide(temp, vel_magnitude.reshape(-1, 1)**2, out=np.zeros_like(temp), where=vel_magnitude.reshape(-1, 1) !=0)
        return curvature.reshape(s), orthogonal_projector.reshape((s[0], s[1], s[2], s[2]))

    def calculate_obstacle_cost_gradient(self, trajectoryFlat):
        trajectory = np.squeeze(trajectoryFlat).reshape((self.nDoF, -1)).T
        # trajectory = trajectory[1:-1]
        robot_discretised_points = self.calculate_robot_body_points(trajectory)
        vel_normalised, vel_magnitude, velocity = self.calculate_normalised_workspace_velocity(robot_discretised_points)
        curvature, orthogonal_projector = self.calculate_curvature(vel_normalised, vel_magnitude, velocity)
        dist = self.compute_minimum_distance_to_objects(robot_discretised_points, self.obstacle_list,)
        obstacle_cost_potential = np.array(self.cost_potential(dist))
        gradient_cost_potential = self.gradient_cost_potential(robot_discretised_points)
        obstacle_gradient = np.zeros((trajectory.shape[0], self.nDoF))
        a = robot_discretised_points  # [:-1]
        for jvs in range(trajectory.shape[0]):
            obst_grad = np.zeros(trajectory.shape[1])
            jacobian = self.calculate_jacobian(a[jvs], self.j_index, trajectory[jvs])
            for num_points in range(robot_discretised_points.shape[1]):
                temp1 = orthogonal_projector[jvs, num_points].dot(gradient_cost_potential[jvs, num_points, :])
                temp2 = obstacle_cost_potential[jvs, num_points] * curvature[jvs, num_points, :]
                temp3 = vel_magnitude[jvs, num_points] * (temp1 - temp2)
                obst_grad += jacobian[num_points, :].T.dot(temp3)
                # obst_grad1 += self.basisMultiDoFParsed[jvs].T.dot(jacobian[num_points, :].T.dot(temp3))
            obstacle_gradient[jvs, :] = obst_grad
        return obstacle_gradient.T

    def cost_gradient_analytic(self, weights):  # calculate grad(cost) = grad(smoothness_cost) + grad(obstacle_cost)
        weights = np.squeeze(weights)
        trajectoryFlat = self.basisMultiDoF.dot(weights)
        smoothness_gradient = self.smoothness_gradient(weights)
        if self.obstacle_list is not None:
            obstacle_gradient_traj = self.calculate_obstacle_cost_gradient(trajectoryFlat)
            obstacle_gradient_weight = self.basisMultiDoF.T.dot(obstacle_gradient_traj.reshape(-1))
        else:
            obstacle_gradient_weight = np.zeros(len(weights))
        # trajectory = np.squeeze(trajectory)
        cost_gradient = self.lamda_obs * obstacle_gradient_weight + self.lamda_smooth * smoothness_gradient
        return np.squeeze(cost_gradient)

    def optim_callback(self, xk):
        self.costs.append(self.calculate_total_cost(xk)[0, 0])
        self.optCurve.append(xk)
        print 'Iteration {}: {:2.4}\n'.format(len(self.optCurve), self.costs[len(self.optCurve) - 1])

    def animation(self, optimized_trajectory, initial_trajectory):
        fig = plt.figure()
        ax = fig.add_subplot(111, projection="3d")
        # ax.axis('off')
        plt.show(block=False)
        while True:
            for i in range(len(optimized_trajectory)):
                _, T_joint_optim = self.franka_kin.fwd_kin(optimized_trajectory[i])
                _, T_joint_init = self.franka_kin.fwd_kin(initial_trajectory[i])
                ax.clear()
                if self.obstacle_list is not None:
                    for object in self.obstacle_list:
                        self.sphere(ax, object[-1], object[0:-1])
                self.franka_kin.plotter(ax, T_joint_optim, 'optim', color='blue')
                self.franka_kin.plotter(ax, T_joint_init, 'init', color='red')
                # for x, y, z in self.get_robot_discretised_points(trajectory[i],step_size=0.2):
                #     plt.grid()
                #     ax.scatter(x, y, z, 'gray')
                fig.canvas.draw()
                fig.canvas.flush_events()
                plt.pause(0.01)
            plt.pause(1)
        # plt.show(block=True)

    def discretize(self, start, goal, step_size=0.02):
        w = goal - start
        step = step_size * w / np.linalg.norm(w)
        n = int(np.linalg.norm(w) / np.linalg.norm(step)) + 1
        discretized = np.outer(np.arange(1, n), step) + start
        return discretized
Esempio n. 11
0
class trajectory_optimization():
    def __init__(self, nDoF):
        self.nDoF = nDoF
        self.scene = moveit_commander.PlanningSceneInterface()
        self.group = moveit_commander.MoveGroupCommander("panda_arm")
        self.robot_state = moveit_commander.RobotCommander()
        self.workspace_dim = (-2, -0.2, 0.2, 1, 1, 1.5)
        self.group.set_workspace(
            self.workspace_dim
        )  # specify the workspace bounding box (static scene)
        self.franka_kin = FrankaKinematics()
        self.collision_threshold = 0.07
        self.object_list = np.array([
            [0.25, 0.21, 0.71, 0.1],
            [-0.15, 0.21, 0.51, 0.05],
            [0.15, 0.61, 0.51, 0.05],
            [-0.15, -0.61, 0.51, 0.05],
            [-0.65, 0.31, 0.21, 0.05],
            [-0.55, 0.71, 0.71, 0.06],
            [-0.95, -0.51, 0.41, 0.07],
            [-0.85, 0.27, 0.61, 0.08],
            [-0.25, -0.31, 0.11, 0.04],
            [-0.75, 0.71, 0.91, 0.09],
            [-0.35, 0.51, 0.81, 0.02],
            [-0.95, -0.81, 0.61, 0.03],
            [-0.75, 0.11, 0.41, 0.02],
            [-0.55, -0.61, 0.21, 0.06],
            [0.25, 0.31, 0.71, 0.07],
            [-0.35, -0.41, 0.41, 0.02],
            [-0.25, -0.51, 0.61, 0.08],
        ])  # for two spheres
        # self.object_list = np.array([[0.25, 0.21, 0.71, 0.1], [-0.15, 0.21, 0.51, 0.05]])  # for two spheres
        # self.object_list = np.array([[0.25, 0.21, 0.71, 0.1]])  # for one sphere (x,y,z, radius)
        # self.object_list = []
        # self.object_list = self.populate_obstacles()
        self.initial_joint_values = np.zeros(7)  # + 0.01 * np.random.random(7)
        self.ang_deg = 60
        self.desired_joint_values = np.array([
            np.pi * self.ang_deg / 180, np.pi / 3, 0.0, np.pi / 6, np.pi / 6,
            np.pi / 6, np.pi / 6
        ])
        self.optCurve = []
        self.step_size = 0.09

    def populate_obstacles(self, ):
        # if the obstacle is within robot workspace, then consider those as obstacles
        obs = []
        x_min, x_max = self.workspace_dim[0], self.workspace_dim[3]
        y_min, y_max = self.workspace_dim[1], self.workspace_dim[4]
        z_min, z_max = self.workspace_dim[2], self.workspace_dim[5]

        for k, v in self.scene.get_objects().items():
            px, py, pz = v.primitive_poses[0].position.x, v.primitive_poses[
                0].position.y, v.primitive_poses[0].position.z
            if px >= x_min and px <= x_max:
                if py >= y_min and py <= y_max:
                    if pz >= z_min and pz <= z_max:
                        obs.append([px, py, pz, 0.05])
            # a.append([px, py, pz, 0.05])

        return obs
        # print "Ori:", v.primitive_poses[0].orientation.x, v.primitive_poses[0].orientation.y, \
        #     v.primitive_poses[0].orientation.z, v.primitive_poses[0].orientation.w
        # print "Size:", v.primitives[0].dimensions

        # self.object_list.append([v.primitive_poses[0].position.x, v.primitive_poses[0].position.y, \
        #     v.primitive_poses[0].position.z, 0.05])

    def discretize(self, start, goal, step_size=0.02):
        w = goal - start
        step = step_size * w / np.linalg.norm(w)
        n = int(np.linalg.norm(w) / np.linalg.norm(step)) + 1
        discretized = np.outer(np.arange(1, n), step) + start
        return discretized

    def get_robot_discretised_points(self,
                                     joint_values=None,
                                     step_size=0.2,
                                     with_joint_index=False):

        if joint_values is None:
            joint_values = list(
                self.robot_state.get_current_state().joint_state.position)[:7]

        _, t_joints = self.franka_kin.fwd_kin(joint_values)
        fwd_k_j_positions = np.vstack(([0., 0., 0.], t_joints[:, :3, 3]))
        discretised = list()
        j_index = list()
        for j in range(len(fwd_k_j_positions) - 1):
            w = fwd_k_j_positions[j + 1] - fwd_k_j_positions[j]
            if len(w[w != 0.]):
                step = step_size * w / np.linalg.norm(w)
                n = int(np.linalg.norm(w) / np.linalg.norm(step)) + 1
                discretised.extend(
                    np.outer(np.arange(1, n), step) + fwd_k_j_positions[j])
            j_index.append(len(discretised))
        return (np.array(discretised),
                j_index) if with_joint_index else np.array(discretised)

    def compute_minimum_distance_to_objects(
        self,
        robot_body_points,
        object_list,
    ):
        # if object_list is None:
        #     object_list = self.get_object_collision_spheres()
        D = list()
        if len(robot_body_points.shape) == 1:
            robot_body_points = robot_body_points.reshape(1, 3)

        for r in robot_body_points:  # expects robot_body_points as an array of dimension 1 x n
            dist = []
            for o in object_list:
                ro = r - o[:3]
                norm_ro = np.linalg.norm(ro)
                dist.append(norm_ro - 0.15 - o[3])
            D.append(np.min(np.array(dist)))
        return D

    def cost_potential(self, D):
        c = list()
        for d in D:
            if d < 0.:
                c.append(-d + 0.5 * self.collision_threshold)
            elif d <= self.collision_threshold:
                c.append((0.5 * (d - self.collision_threshold)**2) /
                         self.collision_threshold)
            else:
                c.append(0)
        return c

    def sphere(self, ax, radius, centre):
        u = np.linspace(0, 2 * np.pi, 13)
        v = np.linspace(0, np.pi, 7)
        x = centre[0] + radius * np.outer(np.cos(u), np.sin(v))
        y = centre[1] + radius * np.outer(np.sin(u), np.sin(v))
        z = centre[2] + radius * np.outer(np.ones(np.size(u)), np.cos(v))
        xdata = scipy.ndimage.zoom(x, 3)
        ydata = scipy.ndimage.zoom(y, 3)
        zdata = scipy.ndimage.zoom(z, 3)
        ax.plot_surface(xdata,
                        ydata,
                        zdata,
                        rstride=3,
                        cstride=3,
                        color='w',
                        shade=0)

    def finite_diff_matrix(self, trajectory):
        rows, columns = trajectory.shape  # columns = nDoF
        A = 2 * np.eye(rows)
        A[0, 1] = -1
        A[rows - 1, rows - 2] = -1
        for ik in range(0, rows - 2):
            A[ik + 1, ik] = -1
            A[ik + 1, ik + 2] = -1

        dim = rows * columns
        fd_matrix = np.zeros((dim, dim))
        b = np.zeros((dim, 1))
        i, j = 0, 0
        while i < dim:
            fd_matrix[i:i + len(A), i:i + len(A)] = A
            b[i] = -2 * self.initial_joint_values[j]
            b[i + len(A) - 1] = -2 * self.desired_joint_values[j]
            i = i + len(A)
            j = j + 1
        return fd_matrix, b

    def smoothness_objective(self, trajectory):
        trajectoryFlat = np.squeeze(trajectory)
        trajectory = (trajectoryFlat.reshape(
            (self.nDoF, trajectoryFlat.shape[0] / self.nDoF))).T
        rows, columns = trajectory.shape
        dim = rows * columns
        fd_matrix, b = self.finite_diff_matrix(trajectory)
        trajectory = trajectory.T.reshape((dim, 1))
        F_smooth = 0.5 * (np.dot(trajectory.T, np.dot(fd_matrix, trajectory)) +
                          np.dot(trajectory.T, b) + 0.25 * np.dot(b.T, b))
        return F_smooth

    def calculate_obstacle_cost(self, trajectory):
        obstacle_cost = 0
        trajectoryFlat = np.squeeze(trajectory)
        trajectory = (trajectoryFlat.reshape(
            (self.nDoF, trajectoryFlat.shape[0] / self.nDoF))).T
        vel_normalised, vel_mag, vel = self.calculate_normalised_workspace_velocity(
            trajectory)  # vel_normalised = vel/vel_mag
        for jvs in range(len(trajectory)):
            # print trajectory.shape

            robot_discretised_points = np.array(
                self.get_robot_discretised_points(trajectory[jvs],
                                                  self.step_size))
            dist = self.compute_minimum_distance_to_objects(
                robot_discretised_points, self.object_list)
            obsacle_cost_potential = np.array(self.cost_potential(dist))
            obstacle_cost += np.sum(
                np.multiply(obsacle_cost_potential, vel_mag[jvs, :]))
            # obstacle_cost += np.sum(obsacle_cost_potential)
        return obstacle_cost

    def calculate_total_cost(self, trajectory):
        trajectory = np.squeeze(trajectory)
        F_smooth = self.smoothness_objective(
            trajectory)  # smoothness of trajectory is captured here
        obstacle_cost = self.calculate_obstacle_cost(trajectory)
        return 10 * F_smooth + 25.5 * obstacle_cost  #  for with gradient
        # return 10 * F_smooth + 1.5 * obstacle_cost   #  for without gradient

    def calculate_normalised_workspace_velocity(self,
                                                trajectory,
                                                desired_joint_values=None):
        if desired_joint_values is None:
            desired_joint_values = self.desired_joint_values

        # We have not divided by  time as this has been indexed and is thus not available
        trajectory = np.insert(trajectory,
                               len(trajectory),
                               desired_joint_values,
                               axis=0)
        robot_body_points = np.array([
            self.get_robot_discretised_points(joint_values, self.step_size)
            for joint_values in trajectory
        ])
        velocity = np.diff(robot_body_points, axis=0)
        vel_magnitude = np.linalg.norm(velocity, axis=2)
        vel_normalised = np.divide(velocity,
                                   vel_magnitude[:, :, None],
                                   out=np.zeros_like(velocity),
                                   where=vel_magnitude[:, :, None] != 0)
        return vel_normalised, vel_magnitude, velocity

    def calculate_jacobian(self,
                           robot_body_points,
                           joint_index,
                           joint_values=None):
        class ParentMap(object):
            def __init__(self, num_joints):
                self.joint_idxs = [i for i in range(num_joints)]
                self.p_map = np.zeros((num_joints, num_joints))
                for i in range(num_joints):
                    for j in range(num_joints):
                        if j <= i:
                            self.p_map[i][j] = True

            def is_parent(self, parent, child):
                if child not in self.joint_idxs or parent not in self.joint_idxs:
                    return False
                return self.p_map[child][parent]

        parent_map = ParentMap(7)

        if joint_values is None:
            joint_values = list(
                self.robot_state.get_current_state().joint_state.position)[:7]

        _, t_joints = self.franka_kin.fwd_kin(joint_values)
        joint_axis = t_joints[:, :3, 2]
        joint_positions = t_joints[:7, :3,
                                   3]  # Excluding the fixed joint at the end
        jacobian = list()
        for i, points in enumerate(
                np.split(robot_body_points, joint_index)[:-1]):
            # print i, len(points)
            if i == 0:
                for point in points:
                    jacobian.append(np.zeros((3, 7)))
            else:
                for point in points:
                    jacobian.append(np.zeros((3, 7)))
                    for joint in parent_map.joint_idxs:
                        if parent_map.is_parent(joint, i - 1):
                            # find cross product
                            col = np.cross(joint_axis[joint, :],
                                           point - joint_positions[joint])
                            jacobian[-1][0][joint] = col[0]
                            jacobian[-1][1][joint] = col[1]
                            jacobian[-1][2][joint] = col[2]
                        else:
                            jacobian[-1][0][joint] = 0.0
                            jacobian[-1][1][joint] = 0.0
                            jacobian[-1][2][joint] = 0.0
        return np.array(jacobian)

    def calculate_smoothness_gradient(self, trajectory):
        trajectoryFlat = np.squeeze(trajectory)
        trajectory = (trajectoryFlat.reshape(
            (self.nDoF, trajectoryFlat.shape[0] / self.nDoF))).T
        rows, columns = trajectory.shape
        dim = rows * columns
        fd_matrix, b = self.finite_diff_matrix(trajectory)
        trajectory = trajectory.T.reshape((dim, 1))
        smoothness_gradient = 0.5 * b + fd_matrix.dot(trajectory)
        return smoothness_gradient

    def calculate_curvature(self, vel_normalised, vel_magnitude, velocity):
        time_instants, body_points, n = velocity.shape[0], velocity.shape[
            1], velocity.shape[2]
        acceleration = np.gradient(velocity, axis=0)
        curvature, orthogonal_projector = np.zeros(
            (time_instants, body_points, n)), np.zeros(
                (time_instants, body_points, n, n))
        for tm in range(time_instants):
            for pts in range(body_points):
                ttm = np.dot(vel_normalised[tm, pts, :].reshape(3, 1),
                             vel_normalised[tm, pts, :].reshape(1, 3))
                temp = np.eye(3) - ttm
                orthogonal_projector[tm, pts] = temp
                if vel_magnitude[tm, pts]:
                    curvature[tm, pts] = np.dot(
                        temp, acceleration[tm, pts, :]) / vel_magnitude[tm,
                                                                        pts]**2
                else:
                    # curv.append(np.array([0, 0, 0]))
                    curvature[tm, pts] = np.array([0, 0, 0])
        return curvature, orthogonal_projector

    def fun(self, points):
        dist = self.compute_minimum_distance_to_objects(
            points, self.object_list)
        return np.array(self.cost_potential(dist))

    def gradient_cost_potential(self, robot_discretised_points):
        gradient_cost_potential = list()
        for points in robot_discretised_points:
            grad = opt.approx_fprime(points, self.fun, [1e-06, 1e-06, 1e-06])
            gradient_cost_potential.append(grad)
        return np.array(gradient_cost_potential)

    def calculate_mt(self, trajectory):
        n_time, ndof = trajectory.shape  #
        M_t = np.zeros((n_time, ndof, n_time * ndof))
        for t in range(n_time):
            k = 0
            for d in range(ndof):
                M_t[t, d, k + t] = 1
                k = k + n_time
        return M_t

    def calculate_obstacle_cost_gradient(self, trajectory):
        trajectoryFlat = np.squeeze(trajectory)
        trajectory = (trajectoryFlat.reshape(
            (self.nDoF, trajectoryFlat.shape[0] / self.nDoF))).T
        vel_normalised, vel_magnitude, velocity = self.calculate_normalised_workspace_velocity(
            trajectory)
        curvature, orthogonal_projector = self.calculate_curvature(
            vel_normalised, vel_magnitude, velocity)
        obstacle_gradient = list()
        # a, b, c, d = [], [], [], []
        for jvs in range(len(trajectory)):
            obst_grad = np.zeros(trajectory.shape[1])
            robot_discretised_points, joint_index = np.array(
                self.get_robot_discretised_points(trajectory[jvs],
                                                  self.step_size,
                                                  with_joint_index=True))
            dist = np.array(
                self.compute_minimum_distance_to_objects(
                    robot_discretised_points,
                    self.object_list,
                ))
            obstacle_cost_potential = np.array(self.cost_potential(dist))
            gradient_cost_potential = self.gradient_cost_potential(
                robot_discretised_points)
            jacobian = self.calculate_jacobian(robot_discretised_points,
                                               joint_index, trajectory[jvs])
            # a.append(robot_discretised_points)
            # b.append(obstacle_cost_potential)
            # c.append(gradient_cost_potential)
            # d.append(jacobian)
            for num_points in range(robot_discretised_points.shape[0]):
                temp1 = orthogonal_projector[jvs, num_points].dot(
                    gradient_cost_potential[num_points, :])
                temp2 = obstacle_cost_potential[num_points] * curvature[
                    jvs, num_points, :]
                temp3 = vel_magnitude[jvs, num_points] * (temp1 - temp2)
                obst_grad += jacobian[num_points, :].T.dot(temp3)
                # obst_grad += jacobian[num_points, :].T.dot(gradient_cost_potential[num_points, :])
            obstacle_gradient.append(obst_grad)
        return np.transpose(np.array(obstacle_gradient))

    def cost_gradient_analytic(
        self, trajectory
    ):  # calculate grad(cost) = grad(smoothness_cost) + grad(obstacle_cost)
        smoothness_gradient = self.calculate_smoothness_gradient(trajectory)
        obstacle_gradient = self.calculate_obstacle_cost_gradient(trajectory)
        trajectory = np.squeeze(trajectory)
        cost_gradient = obstacle_gradient.reshape(
            (len(trajectory), 1)) + smoothness_gradient
        return np.squeeze(cost_gradient)

    def cost_gradient_numeric(self, trajectory):
        trajectory = np.squeeze(trajectory)
        obst_cost_grad_numeric = opt.approx_fprime(
            trajectory, traj_opt.calculate_obstacle_cost,
            1e-08 * np.ones(len(trajectory)))
        smoothness_gradient = np.squeeze(
            self.calculate_smoothness_gradient(trajectory))
        return np.squeeze(obst_cost_grad_numeric + smoothness_gradient)

    def animation(self, optimized_trajectory, initial_trajectory):
        fig = plt.figure()
        ax = fig.add_subplot(111, projection="3d")
        # ax.axis('off')
        plt.show(block=False)
        while True:
            for i in range(len(optimized_trajectory)):
                _, T_joint_optim = self.franka_kin.fwd_kin(
                    optimized_trajectory[i])
                _, T_joint_init = self.franka_kin.fwd_kin(
                    initial_trajectory[i])
                ax.clear()
                for object in self.object_list:
                    self.sphere(ax, object[-1], object[0:-1])
                self.franka_kin.plotter(ax,
                                        T_joint_optim,
                                        'optim',
                                        color='blue')
                self.franka_kin.plotter(ax, T_joint_init, 'init', color='red')
                # for x, y, z in self.get_robot_discretised_points(trajectory[i],step_size=0.2):
                #     plt.grid()
                #     ax.scatter(x, y, z, 'gray')
                fig.canvas.draw()
                fig.canvas.flush_events()
                plt.pause(0.01)
            plt.pause(1)
        # plt.show(block=True)

    def optim_callback(self, xk):
        # xk = xk.reshape(len(xk) / 7, 7)
        costs = self.calculate_total_cost(xk)
        self.optCurve.append(xk)
        print 'Iteration {}: {}\n'.format(len(self.optCurve), costs)
Esempio n. 12
0
import numpy as np
from franka_kinematics import FrankaKinematics
import tf.transformations as tf_tran

with open(
        '/home/ash/Ash/scripts/TrajectoryRecorder/Trajectories_bag/tableandchar/format/bottle2cup.npz',
        'r') as f:
    data = np.load(f)
    Q = data['Q']
    timeData = data['time']

nDoF = 9
franka_kin = FrankaKinematics()
# end_robot_config = np.zeros((len(Q), nDoF))
euler, position, quaternion = [], [], []
for i in range(len(Q)):
    end_robot_config = Q[i][-1]
    T, _ = franka_kin.fwd_kin(end_robot_config[:-2])
    euler.append(tf_tran.euler_from_matrix(T))
    position.append(T[:3, -1])
    quaternion.append(tf_tran.quaternion_from_matrix(T))

euler = np.array(euler)
position = np.array(position)
quaternion = np.array(quaternion)

# euler_mean, euler_std = np.mean(euler, axis=0), np.std(euler, axis=0)
# position_mean, position_std = np.mean(position, axis=0), np.std(position, axis=0)
# quaternion_mean, quaternion_std = np.mean(quaternion, axis=0), np.std(quaternion, axis=0)
#
# pos_cov = np.cov(position, rowvar=0)