示例#1
0
def escape(robot, dist_est, start_cfg):
    N_WAYPOINTS = 20
    UPDATE_STEPS = 200
    safety_margin = -0.3
    lr = 5e-2
    path_history = []
    init_path = start_cfg
    p = init_path.requires_grad_(True)
    opt = torch.optim.Adam([p], lr=lr)

    for step in range(N_WAYPOINTS):
        if step % 1 == 0:
            path_history.append(p.data.clone())

        opt.zero_grad()
        collision_score = dist_est(p) - safety_margin
        loss = collision_score
        loss.backward()
        opt.step()
        p.data = utils.wrap2pi(p.data)
        if collision_score <= 1e-4:
            break
    return torch.stack(path_history, dim=0)
示例#2
0
 def pre_process(p):
     p = torch.DoubleTensor(p).reshape([-1, robot.dof])
     p[:] = utils.wrap2pi(p)
     p = torch.cat([init_path[:1], p, init_path[-1:]], dim=0)
     return p
示例#3
0
def gradient_free_traj_optimize(robot, checker, start_cfg, target_cfg, options=None):
    N_WAYPOINTS = options['N_WAYPOINTS']
    NUM_RE_TRIALS = options['NUM_RE_TRIALS']
    MAXITER = options['MAXITER']

    seed = options['seed']
    torch.manual_seed(seed)

    global cnt_check
    cnt_check = 0

    def pre_process(p):
        p = torch.DoubleTensor(p).reshape([-1, robot.dof])
        p[:] = utils.wrap2pi(p)
        p = torch.cat([init_path[:1], p, init_path[-1:]], dim=0)
        return p

    def con_max_move(p):
        p = pre_process(p)
        control_points = robot.fkine(p)
        return -torch.clamp_((control_points[1:]-control_points[:-1]).pow(2).sum(dim=2)-1.5**2, min=0).sum().numpy()
    def con_collision_free(p):
        global cnt_check
        p = pre_process(p)
        cnt_check += len(p)
        return torch.sum(-torch.clamp_(checker(p), min=0)).numpy()
    def con_joint_limit(p):
        p = pre_process(p)
        return -torch.sum(torch.clamp_(robot.limits[:, 0]-p, min=0) + torch.clamp_(p-robot.limits[:, 1], min=0)).numpy()
    def cost(p):
        p_tensor = pre_process(p)
        control_points = robot.fkine(p_tensor)
        diff = (control_points[1:]-control_points[:-1]).pow(2).sum()
        return diff.numpy()

    start_t = time()
    success = False
    for trial_time in range(NUM_RE_TRIALS):
        if trial_time == 0:
            if 'init_solution' in options:
                assert isinstance(options['init_solution'], torch.Tensor)
                init_path = options['init_solution']
            else:
                init_path = torch.from_numpy(np.linspace(start_cfg, target_cfg, num=N_WAYPOINTS, dtype=np.float64))
        else:
            init_path = (torch.rand(N_WAYPOINTS, robot.dof, dtype=torch.float64))*np.pi*2-np.pi
        init_path[0] = start_cfg
        init_path[-1] = target_cfg
        res = fmin(cost, init_path[1:-1].reshape(-1).numpy(), 
            constraints=[
                {'fun': con_max_move, 'type': 'ineq'},
                {'fun': con_collision_free, 'type': 'ineq'},
                {'fun': con_joint_limit, 'type': 'ineq'}
            ],
            options={'maxiter': MAXITER, 'disp': False})
        if res.success:
            success = True
            break
    end_t = time()

    res.x = res.x.reshape([-1, robot.dof])
    res.x = utils.wrap2pi(pre_process(res.x))
    rec = {
        'start_cfg': start_cfg.numpy().tolist(),
        'target_cfg': target_cfg.numpy().tolist(),
        'cnt_check': cnt_check,
        'cost': res.fun.item(),
        'time': end_t - start_t,
        'success': success,
        'seed': seed,
        'solution': res.x.numpy().tolist()
    }
    return rec
示例#4
0
 def pre_process(p):
     global var_p
     p = torch.DoubleTensor(p).reshape([-1, robot.dof])
     p[:] = utils.wrap2pi(p)
     var_p = torch.cat([init_path[:1], p, init_path[-1:]], dim=0).requires_grad_(True)
     return var_p
示例#5
0
def adam_traj_optimize(robot, dist_est, start_cfg, target_cfg, options):
    N_WAYPOINTS = options['N_WAYPOINTS'] # 20
    NUM_RE_TRIALS = options['NUM_RE_TRIALS'] # 10
    MAXITER = options['MAXITER'] # 200
    history = options['history']

    dif_weight = 1 # This should NOT be changed
    max_move_weight = 10
    collision_weight = 10
    joint_limit_weight = 10
    safety_margin = options['safety_margin']
    lr = 5e-1
    seed = options['seed']
    torch.manual_seed(seed)

    lowest_loss_solution = None
    lowest_loss = np.inf
    lowest_loss_obj = np.inf
    lowest_loss_trial = None
    lowest_loss_step = None
    best_valid_solution = None
    best_valid_obj = np.inf
    best_valid_step = None
    best_valid_trial = None
    
    trial_histories = []
    cnt_check = 0

    found = False
    start_t = time()
    for trial_time in range(NUM_RE_TRIALS):
        path_history = []
        if trial_time == 0:
            if 'init_solution' in options:
                assert isinstance(options['init_solution'], torch.Tensor)
                init_path = options['init_solution']
            else:
                init_path = torch.from_numpy(np.linspace(start_cfg, target_cfg, num=N_WAYPOINTS)).double()
        else:
            init_path = torch.rand((N_WAYPOINTS, robot.dof)).double()
            init_path = init_path * (robot.limits[:, 1]-robot.limits[:, 0]) + robot.limits[:, 0]
        init_path[0] = start_cfg
        init_path[-1] = target_cfg
        p = init_path.requires_grad_(True)
        opt = torch.optim.Adam([p], lr=lr)

        for step in range(MAXITER):
            opt.zero_grad()
            collision_score = torch.clamp(dist_est(p)-safety_margin, min=0).sum()
            cnt_check += len(p) # Counting collision checks
            control_points = robot.fkine(p)
            max_move_cost = torch.clamp((control_points[1:]-control_points[:-1]).pow(2).sum(dim=2)-1.5**2, min=0).sum()
            joint_limit_cost = (
                torch.clamp(robot.limits[:, 0]-p, min=0) + torch.clamp(p-robot.limits[:, 1], min=0)).sum()
            diff = (control_points[1:]-control_points[:-1]).pow(2).sum()
            constraint_loss = collision_weight * collision_score\
                + max_move_weight * max_move_cost + joint_limit_weight * joint_limit_cost
            objective_loss = dif_weight * diff
            loss = objective_loss + constraint_loss
            loss.backward()
            p.grad[[0, -1]] = 0.0
            opt.step()
            p.data = utils.wrap2pi(p.data)
            if history:
                path_history.append(p.data.clone())
            if loss.data.numpy() < lowest_loss:
                lowest_loss = loss.data.numpy()
                lowest_loss_solution = p.data.clone()
                lowest_loss_step = step
                lowest_loss_trial = trial_time
                lowest_loss_obj = objective_loss.data.numpy()
            if constraint_loss <= 1e-2:
                if objective_loss.data.numpy() < best_valid_obj:
                    best_valid_obj = objective_loss.data.numpy()
                    best_valid_solution = p.data.clone()
                    best_valid_step = step
                    best_valid_trial = trial_time
            # if constraint_loss <= 1e-2 or step % (MAXITER/5) == 0 or step == MAXITER-1:
            #     print('Trial {}: Step {}, collision={:.3f}*{:.1f}, max_move={:.3f}*{:.1f}, diff={:.3f}*{:.1f}, Loss={:.3f}'.format(
            #         trial_time, step, 
            #         collision_score.item(), collision_weight,
            #         max_move_cost.item(), max_move_weight,
            #         diff.item(), dif_weight,
            #         loss.item()))
            if constraint_loss <= 1e-2 and torch.norm(p.grad) < 1e-4:
                break
        trial_histories.append(path_history)
        
        if best_valid_solution is not None:
            found = True
            break
    end_t = time()
    if not found:
        # print('Did not find a valid solution after {} trials!\
            # Giving the lowest cost solution'.format(NUM_RE_TRIALS))
        solution = lowest_loss_solution
        solution_step = lowest_loss_step
        solution_trial = lowest_loss_trial
        solution_obj = lowest_loss_obj
    else:
        solution = best_valid_solution
        solution_step = best_valid_step
        solution_trial = best_valid_trial
        solution_obj = best_valid_obj
    path_history = trial_histories[solution_trial] # Could be empty when history = false
    if not path_history:
        path_history.append(solution)
    else:
        path_history = path_history[:(solution_step+1)]
    
    rec = {
        'start_cfg': start_cfg.numpy().tolist(),
        'target_cfg': target_cfg.numpy().tolist(),
        'cnt_check': cnt_check,
        'cost': solution_obj.item(),
        'time': end_t - start_t,
        'success': found,
        'seed': seed,
        'solution': solution.numpy().tolist()
    }
    return rec
示例#6
0
def main(checking_method='diffco'):
    DOF = 2
    env_name = '1rect_active'  # '2rect' # '1rect_1circle' '1rect' 'narrow' '2instance'

    dataset = torch.load('data/2d_{}dof_{}.pt'.format(DOF, env_name))
    cfgs = dataset['data'].double()
    labels = dataset['label'].reshape(-1, 1).double()  #.max(1).values
    dists = dataset['dist'].reshape(-1, 1).double()  #.max(1).values
    obstacles = dataset['obs']
    obstacles = [list(o) for o in obstacles]
    robot = dataset['robot'](*dataset['rparam'])
    width = robot.link_width

    #=================================================================================================================================
    fcl_obs = [FCLObstacle(*param) for param in obstacles]
    fcl_collision_obj = [fobs.cobj for fobs in fcl_obs]

    label_type = 'binary'
    num_class = 1

    T = 11
    nu = 5  #5
    kai = 1500
    sigma = 0.3
    seed = 1918
    torch.manual_seed(seed)
    np.random.seed(seed)

    num_init_points = 8000
    if label_type == 'binary':
        obs_managers = [fcl.DynamicAABBTreeCollisionManager()]
        obs_managers[0].registerObjects(fcl_collision_obj)
        obs_managers[0].setup()
    elif label_type == 'instance':
        obs_managers = [fcl.DynamicAABBTreeCollisionManager() for _ in fcl_obs]
        for mng, cobj in zip(obs_managers, fcl_collision_obj):
            mng.registerObjects([cobj])
    elif label_type == 'class':
        obs_managers = [
            fcl.DynamicAABBTreeCollisionManager() for _ in range(num_class)
        ]
        obj_by_cls = [[] for _ in range(num_class)]
        for obj in fcl_obs:
            obj_by_cls[obj.category].append(obj.cobj)
        for mng, obj_group in zip(obs_managers, obj_by_cls):
            mng.registerObjects(obj_group)

    robot_links = robot.update_polygons(cfgs[0])
    robot_manager = fcl.DynamicAABBTreeCollisionManager()
    robot_manager.registerObjects(robot_links)
    robot_manager.setup()
    for mng in obs_managers:
        mng.setup()
    gt_checker = FCLChecker(obstacles, robot, robot_manager, obs_managers)

    train_num = 6000
    fkine = robot.fkine
    # checker = DiffCo(obstacles, kernel_func=kernel.FKKernel(fkine, kernel.RQKernel(10)), beta=1.0)
    from time import time
    init_train_t = time()
    checker = MultiDiffCo(obstacles,
                          kernel_func=kernel.FKKernel(fkine,
                                                      kernel.RQKernel(10)),
                          beta=1.0)
    labels, dists = gt_checker.predict(cfgs[:train_num], distance=True)
    labels = labels.double()
    dists = dists.double()
    checker.train(cfgs[:train_num],
                  labels[:train_num],
                  max_iteration=len(cfgs[:train_num]),
                  distance=dists[:train_num])

    # Check DiffCo test ACC
    # test_preds = (checker.score(cfgs[train_num:]) > 0) * 2 - 1
    # test_acc = torch.sum(test_preds == labels[train_num:], dtype=torch.float32)/len(test_preds.view(-1))
    # test_tpr = torch.sum(test_preds[labels[train_num:]==1] == 1, dtype=torch.float32) / len(test_preds[labels[train_num:]==1])
    # test_tnr = torch.sum(test_preds[labels[train_num:]==-1] == -1, dtype=torch.float32) / len(test_preds[labels[train_num:]==-1])
    # print('Test acc: {}, TPR {}, TNR {}'.format(test_acc, test_tpr, test_tnr))
    # assert(test_acc > 0.9)

    fitting_target = 'dist'  # {label, dist, hypo}
    Epsilon = 0.01
    checker.fit_poly(kernel_func=kernel.Polyharmonic(1, Epsilon),
                     target=fitting_target,
                     fkine=fkine)  # epsilon=Epsilon,
    # checker.fit_poly(kernel_func=kernel.MultiQuadratic(Epsilon), target=fitting_target, fkine=fkine)
    # checker.fit_full_poly(epsilon=Epsilon, target=fitting_target, fkine=fkine, lmbd=10)
    dist_est = checker.rbf_score
    init_train_t = time() - init_train_t
    # dist_est = checker.score
    # dist_est = checker.poly_score
    print('MIN_SCORE = {:.6f}'.format(dist_est(cfgs[train_num:]).min()))

    positions = torch.FloatTensor(np.linspace(obstacles[0][1], [4, 3], T))
    start_cfg = torch.zeros(robot.dof,
                            dtype=cfgs.dtype)  # free_cfgs[indices[0]] #
    target_cfg = torch.zeros(robot.dof,
                             dtype=cfgs.dtype)  # free_cfgs[indices[1]] #
    start_cfg[0] = np.pi / 2  # -np.pi/16
    start_cfg[1] = -np.pi / 6
    target_cfg[0] = 0  # -np.pi/2 # -15*np.pi/16
    target_cfg[1] = np.pi / 7

    update_ts = []
    plan_ts = []
    for t, trans in zip(range(T), positions):
        ut = time()
        fcl_collision_obj[0].setTransform(
            fcl.Transform(
                # Rotation.from_rotvec([0, 0, angle]).as_quat()[[3,0,1,2]],
                [trans[0], trans[1], 0]))
        for obs_mng in obs_managers:
            obs_mng.update()

        # if checking_method == 'diffco':
        exploit_samples = torch.randn(nu,
                                      len(checker.gains),
                                      robot.dof,
                                      dtype=checker.support_points.dtype
                                      ) * sigma + checker.support_points
        exploit_samples = utils.wrap2pi(exploit_samples).reshape(-1, robot.dof)

        explore_samples = torch.rand(
            kai, robot.dof,
            dtype=checker.support_points.dtype) * 2 * np.pi - np.pi

        cfgs = torch.cat(
            [exploit_samples, explore_samples, checker.support_points])
        labels, dists = gt_checker.predict(cfgs, distance=True)
        dists = dists.double()
        print('Collision {}, Free {}\n'.format((labels == 1).sum(),
                                               (labels == -1).sum()))

        gains = torch.cat([
            torch.zeros(len(exploit_samples) + len(explore_samples),
                        checker.num_class,
                        dtype=checker.gains.dtype), checker.gains
        ])  #None #
        #TODO: bug: not calculating true hypothesis for new points
        added_hypothesis = checker.score(cfgs[:-len(checker.support_points)])
        hypothesis = torch.cat(
            [added_hypothesis, checker.hypothesis]
        )  # torch.cat([torch.zeros(len(exploit_samples)+len(explore_samples), checker.num_class), checker.hypothesis]) # None #
        # kernel_matrix = torch.zeros(len(cfgs), len(cfgs)) #None #
        # kernel_matrix[-len(checker.kernel_matrix):, -len(checker.kernel_matrix):] = checker.kernel_matrix

        checker.train(cfgs,
                      labels,
                      gains=gains,
                      hypothesis=hypothesis,
                      distance=dists)  #, kernel_matrix=kernel_matrix
        print('Num of support points {}'.format(len(checker.support_points)))
        checker.fit_poly(kernel_func=kernel.Polyharmonic(1, Epsilon),
                         target=fitting_target,
                         fkine=fkine,
                         reg=0.1)
        update_ts.append(time() - ut)

        if checking_method == 'fcl':
            fcl_options = {
                'N_WAYPOINTS': 20,
                'NUM_RE_TRIALS': 5,  # Debugging
                'MAXITER': 200,
                'seed': seed,
                'history': False
            }
        elif checking_method == 'diffco':
            diffco_options = {
                'N_WAYPOINTS': 20,
                'NUM_RE_TRIALS': 5,  # Debugging
                'MAXITER': 200,
                'safety_margin': -0.5,  #max(1/5*min_score, -0.5),
                'seed': seed,
                'history': False
            }

        print('t = {}'.format(t))
        if t % 1 == 0 and not torch.any(
                checker.predict(torch.stack([start_cfg, target_cfg], dim=0)) ==
                1):

            obstacles[0][1] = (trans[0], trans[1])
            cfg_path_plots = []
            if robot.dof > 2:
                fig, ax, link_plot, joint_plot, eff_plot = create_plots(
                    robot, obstacles, dist_est, checker)
            elif robot.dof == 2:
                fig, ax, link_plot, joint_plot, eff_plot, cfg_path_plots = create_plots(
                    robot, obstacles, dist_est, checker)

            ot = time()
            # Begin optimization==========
            if checking_method == 'diffco':
                # p, path_history, num_trial, num_step = traj_optimize(
                #     robot, dist_est, start_cfg, target_cfg, history=False)
                solution_rec = givengrad_traj_optimize(robot,
                                                       dist_est,
                                                       start_cfg,
                                                       target_cfg,
                                                       options=diffco_options)
                p = torch.FloatTensor(solution_rec['solution'])
            elif checking_method == 'fcl':
                solution_rec = gradient_free_traj_optimize(
                    robot,
                    lambda cfg: gt_checker.predict(cfg, distance=False),
                    start_cfg,
                    target_cfg,
                    options=fcl_options)
                p = torch.FloatTensor(solution_rec['solution'])
            # ============================
            plan_ts.append(time() - ot)

            # path_dir = 'results/active_learning/path_2d_{}dof_{}_seed{}_step{:02d}.json'.format(robot.dof, env_name, seed, t) # DEBUGGING
            path_dir = 'results/active_learning/path_2d_{}dof_{}_checker={}_seed{}_step{:02d}.json'.format(
                robot.dof, env_name, checking_method, seed, t)
            with open(path_dir, 'w') as f:
                json.dump({
                    'path': p.data.numpy().tolist(),
                }, f, indent=1)
                print('Plan recorded in {}'.format(f.name))

            # Use saved path ======
            # if not isfile(path_dir):
            #     continue
            # with open(path_dir, 'r') as f:
            #     path_dict = json.load(f)
            #     p = torch.FloatTensor(path_dict['path'])
            # =====================
            p = utils.make_continue(p)

            #animation
            # vid_name = None #'results/maual_trajopt_2d_{}dof_{}_fitting_{}_eps_{}_dif_{}_updates_{}_steps_{}.mp4'.format(
            #     # robot.dof, env_name, fitting_target, Epsilon, dif_weight, UPDATE_STEPS, N_STEPS)
            # if robot.dof == 2:
            #     animation_demo(
            #         robot, p, fig, link_plot, joint_plot, eff_plot,
            #         cfg_path_plots=cfg_path_plots, path_history=path_history, save_dir=vid_name)
            # elif robot.dof == 7:
            #     animation_demo(robot, p, fig, link_plot, joint_plot, eff_plot, save_dir=vid_name)

            # single shot
            single_plot(robot,
                        p,
                        fig,
                        link_plot,
                        joint_plot,
                        eff_plot,
                        cfg_path_plots=cfg_path_plots,
                        ax=ax)
            # plt.show()
            # plt.savefig('figs/path_2d_{}dof_{}.png'.format(robot.dof, env_name), dpi=500)
            # plt.savefig('figs/active_2d_{}dof_{}_{}'.format(robot.dof, env_name, t), dpi=500)
            fig_dir = 'figs/active/{random_seed}/{checking_method}'.format(
                random_seed=seed, checking_method=checking_method)
            if not isdir(fig_dir):
                makedirs(fig_dir)
            plt.savefig(join(
                fig_dir,
                '2d_{DOF}dof_{ename}_{checking_method}_{step:02d}'.format(
                    DOF=robot.dof,
                    ename=env_name,
                    checking_method=checking_method,
                    step=t)),
                        dpi=300)

    print('{} summary'.format(checking_method))
    print('Initial training {} sec.'.format(init_train_t))
    print('Update {} sec.'.format(update_ts))
    print('Planning {} sec.'.format(plan_ts))
示例#7
0
def escape(robot, dist_est, start_cfg):
    N_WAYPOINTS = 20
    # NUM_RE_TRIALS = 10
    UPDATE_STEPS = 200
    # dif_weight = 1
    # max_move_weight = 10
    # collision_weight = 10
    safety_margin = -0.3  #torch.FloatTensor([-2, -0.2])
    lr = 5e-2
    # seed = 19961221
    # torch.manual_seed(seed)

    # lowest_cost_solution = None
    # lowest_cost = np.inf
    # lowest_cost_trial = None
    # lowest_cost_step = None
    # best_valid_solution = None
    # best_valid_cost = np.inf
    # best_valid_step = None
    # best_valid_trial = None

    # trial_histories = []

    # found = False
    # p = torch.FloatTensor(np.concatenate([np.linspace(start_cfg, (-np.pi, 0), N_STEPS/2), np.linspace((np.pi, 0), target_cfg, N_STEPS/2)], axis=0)).requires_grad_(True)
    # for trial_time in range(NUM_RE_TRIALS):
    path_history = []
    # if trial_time == 0:
    #     init_path = torch.from_numpy(np.linspace(start_cfg, target_cfg, num=UPDATE_STEPS))
    # else:
    #     init_path = (torch.rand(N_WAYPOINTS, robot.dof))*np.pi*2-np.pi
    init_path = start_cfg
    # init_path[-1] = target_cfg
    p = init_path.requires_grad_(True)
    opt = torch.optim.Adam([p], lr=lr)
    # opt = torch.optim.SGD([p], lr=lr, momentum=0.0)

    for step in range(N_WAYPOINTS):
        if step % 1 == 0:
            path_history.append(p.data.clone())

        opt.zero_grad()
        collision_score = dist_est(p) - safety_margin  #, min=0).sum()
        # print(torch.clamp(dist_est(p)-safety_margin, min=0).max(dim=0).values.data)
        # control_points = robot.fkine(p)
        # max_move_cost = torch.clamp((control_points[1:]-control_points[:-1]).pow(2).sum(dim=2)-1.0**2, min=0).sum()
        # diff = dif_weight * (control_points[1:]-control_points[:-1]).pow(2).sum()
        # np.clip(1.5*float(i)/UPDATE_STEPS, 0, 1)**2 (float(i)/UPDATE_STEPS) *
        # torch.clamp(utils.wrap2pi(p[1:]-p[:-1]).abs(), min=0.3).pow(2).sum()
        # constraint_loss = collision_weight * collision_score + max_move_weight * max_move_cost
        # objective_loss = dif_weight * diff
        loss = collision_score  #objective_loss + constraint_loss
        loss.backward()
        # p.grad[[0, -1]] = 0.0
        opt.step()
        p.data = utils.wrap2pi(p.data)
        # if history:

        # if loss.data.numpy() < lowest_cost:
        #     lowest_cost = loss.data.numpy()
        #     lowest_cost_solution = p.data.clone()
        #     lowest_cost_step = step
        #     lowest_cost_trial = trial_time
        if collision_score <= 1e-4:
            # if objective_loss.data.numpy() < best_valid_cost:
            #     best_valid_cost = objective_loss.data.numpy()
            #     best_valid_solution = p.data.clone()
            #     best_valid_step = step
            #     best_valid_trial = trial_time
            break
        # if constraint_loss <= 1e-2 or step % (UPDATE_STEPS/5) == 0 or step == UPDATE_STEPS-1:
        #     print('Trial {}: Step {}, collision={:.3f}*{:.1f}, max_move={:.3f}*{:.1f}, diff={:.3f}*{:.1f}, Loss={:.3f}'.format(
        #         trial_time, step,
        #         collision_score.item(), collision_weight,
        #         max_move_cost.item(), max_move_weight,
        #         diff.item(), dif_weight,
        #         loss.item()))
        # trial_histories.append(path_history)

        # if best_valid_solution is not None:
        #     found = True
        #     break
    # if not found:
    #     print('Did not find a valid solution after {} trials!\
    #         Giving the lowest cost solution'.format(NUM_RE_TRIALS))
    #     solution = lowest_cost_solution
    #     solution_step = lowest_cost_step
    #     solution_trial = lowest_cost_trial
    # else:
    #     solution = best_valid_solution
    #     solution_step = best_valid_step
    #     solution_trial = best_valid_trial
    # path_history = trial_histories[solution_trial] # Could be empty when history = false
    # if not path_history:
    #     path_history.append(solution)
    # else:
    #     path_history = path_history[:(solution_step+1)]
    return torch.stack(path_history, dim=0)  # sum(trial_histories, []),
示例#8
0
def traj_optimize(robot, dist_est, start_cfg, target_cfg, history=False):
    N_WAYPOINTS = 20
    NUM_RE_TRIALS = 5
    UPDATE_STEPS = 200
    dif_weight = 1
    max_move_weight = 10
    collision_weight = 10
    safety_margin = torch.FloatTensor([0])  #-3,  #-1 (shown)
    lr = 5e-1

    lowest_cost_solution = None
    lowest_cost = np.inf
    lowest_cost_trial = None
    lowest_cost_step = None
    best_valid_solution = None
    best_valid_cost = np.inf
    best_valid_step = None
    best_valid_trial = None

    trial_histories = []

    found = False
    # p = torch.FloatTensor(np.concatenate([np.linspace(start_cfg, (-np.pi, 0), N_STEPS/2), np.linspace((np.pi, 0), target_cfg, N_STEPS/2)], axis=0)).requires_grad_(True)
    for trial_time in range(NUM_RE_TRIALS):
        path_history = []
        if trial_time == 0 and False:  # Temp
            init_path = torch.from_numpy(
                np.linspace(start_cfg, target_cfg, num=N_WAYPOINTS))
        else:
            init_path = (torch.rand(N_WAYPOINTS,
                                    robot.dof)) * np.pi * 2 - np.pi
        init_path[0] = start_cfg
        init_path[-1] = target_cfg
        p = init_path.requires_grad_(True)
        opt = torch.optim.Adam([p], lr=lr)
        # opt = torch.optim.SGD([p], lr=lr, momentum=0.0)

        for step in range(UPDATE_STEPS):
            opt.zero_grad()
            collision_score = torch.clamp(dist_est(p) - safety_margin,
                                          min=0).sum()
            # print(torch.clamp(dist_est(p)-safety_margin, min=0).max(dim=0).values.data)
            control_points = robot.fkine(p)
            max_move_cost = torch.clamp((control_points[1:, -1:]-control_points[:-1, -1:]).pow(2).sum(dim=2)-1**2, min=0).sum() \
                + torch.clamp((utils.wrap2pi(p[1:]-p[:-1])).pow(2).sum(dim=1)-(5*np.pi/180)**2, min=0).sum()
            diff = (control_points[1:] - control_points[:-1]).pow(2).sum()
            # np.clip(1.5*float(i)/UPDATE_STEPS, 0, 1)**2 (float(i)/UPDATE_STEPS) *
            # torch.clamp(utils.wrap2pi(p[1:]-p[:-1]).abs(), min=0.3).pow(2).sum()
            constraint_loss = collision_weight * collision_score + max_move_weight * max_move_cost
            objective_loss = dif_weight * diff
            loss = objective_loss + constraint_loss
            loss.backward()
            p.grad[[0, -1]] = 0.0
            opt.step()
            p.data = utils.wrap2pi(p.data)
            if history:
                path_history.append(p.data.clone())
            # if loss.data.numpy() < lowest_cost:
            if constraint_loss.data.numpy() < lowest_cost:
                lowest_cost = loss.data.numpy()
                lowest_cost_solution = p.data.clone()
                lowest_cost_step = step
                lowest_cost_trial = trial_time
            if constraint_loss <= 1e-2:
                if objective_loss.data.numpy() < best_valid_cost:
                    best_valid_cost = objective_loss.data.numpy()
                    best_valid_solution = p.data.clone()
                    best_valid_step = step
                    best_valid_trial = trial_time
            if constraint_loss <= 1e-2 or step % (
                    UPDATE_STEPS / 5) == 0 or step == UPDATE_STEPS - 1:
                print(
                    'Trial {}: Step {}, collision={:.3f}*{:.1f}, max_move={:.3f}*{:.1f}, diff={:.3f}*{:.1f}, Loss={:.3f}'
                    .format(trial_time, step,
                            collision_score.item(), collision_weight,
                            max_move_cost.item(), max_move_weight, diff.item(),
                            dif_weight, loss.item()))
        trial_histories.append(path_history)

        if best_valid_solution is not None:
            found = True
            break
    if not found:
        print('Did not find a valid solution after {} trials!\
            Giving the lowest cost solution'.format(NUM_RE_TRIALS))
        solution = lowest_cost_solution
        solution_step = lowest_cost_step
        solution_trial = lowest_cost_trial
    else:
        solution = best_valid_solution
        solution_step = best_valid_step
        solution_trial = best_valid_trial
    path_history = trial_histories[
        solution_trial]  # Could be empty when history = false
    if not path_history:
        path_history.append(solution)
    else:
        path_history = path_history[:(solution_step + 1)]
    return solution, path_history, solution_trial, solution_step  # sum(trial_histories, []),
示例#9
0
def traj_optimize(robot, dist_est, start_cfg, target_cfg, history=False):
    # There is a slightly different version in speed_compare.py,
    # which allows using SLSQP instead of Adam, allows
    # inputting an initial solution other than straight line,
    # and is better modularly written.
    # That one with SLSQP is more recommended to use.
    N_WAYPOINTS = 20
    NUM_RE_TRIALS = 10
    UPDATE_STEPS = 200
    dif_weight = 1
    max_move_weight = 10
    collision_weight = 10
    safety_margin = torch.FloatTensor([-12, -1.2])  #([-8.0, -0.8]) #
    lr = 5e-1
    seed = 19961221
    torch.manual_seed(seed)

    lowest_cost_solution = None
    lowest_cost = np.inf
    lowest_cost_trial = None
    lowest_cost_step = None
    best_valid_solution = None
    best_valid_cost = np.inf
    best_valid_step = None
    best_valid_trial = None

    trial_histories = []

    found = False
    for trial_time in range(NUM_RE_TRIALS):
        path_history = []
        if trial_time == 0:
            init_path = torch.from_numpy(
                np.linspace(start_cfg, target_cfg, num=N_WAYPOINTS))
        else:
            init_path = (torch.rand(N_WAYPOINTS,
                                    robot.dof)) * np.pi * 2 - np.pi
        init_path[0] = start_cfg
        init_path[-1] = target_cfg
        p = init_path.requires_grad_(True)
        opt = torch.optim.Adam([p], lr=lr)

        for step in range(UPDATE_STEPS):
            opt.zero_grad()
            collision_score = torch.clamp(dist_est(p) - safety_margin,
                                          min=0).sum()
            control_points = robot.fkine(p)
            max_move_cost = torch.clamp(
                (control_points[1:] - control_points[:-1]).pow(2).sum(dim=2) -
                0.3**2,
                min=0).sum()
            diff = (control_points[1:] - control_points[:-1]).pow(2).sum()
            constraint_loss = collision_weight * collision_score + max_move_weight * max_move_cost
            objective_loss = dif_weight * diff
            loss = objective_loss + constraint_loss
            loss.backward()
            p.grad[[0, -1]] = 0.0
            opt.step()
            p.data = utils.wrap2pi(p.data)
            if history:
                path_history.append(p.data.clone())
            if loss.data.numpy() < lowest_cost:
                lowest_cost = loss.data.numpy()
                lowest_cost_solution = p.data.clone()
                lowest_cost_step = step
                lowest_cost_trial = trial_time
            if constraint_loss <= 1e-2:
                if objective_loss.data.numpy() < best_valid_cost:
                    best_valid_cost = objective_loss.data.numpy()
                    best_valid_solution = p.data.clone()
                    best_valid_step = step
                    best_valid_trial = trial_time
            if constraint_loss <= 1e-2 or step % (
                    UPDATE_STEPS / 5) == 0 or step == UPDATE_STEPS - 1:
                print(
                    'Trial {}: Step {}, collision={:.3f}*{:.1f}, max_move={:.3f}*{:.1f}, diff={:.3f}*{:.1f}, Loss={:.3f}'
                    .format(trial_time, step,
                            collision_score.item(), collision_weight,
                            max_move_cost.item(), max_move_weight, diff.item(),
                            dif_weight, loss.item()))
        trial_histories.append(path_history)

        if best_valid_solution is not None:
            found = True
            break
    if not found:
        print('Did not find a valid solution after {} trials!\
            Giving the lowest cost solution'.format(NUM_RE_TRIALS))
        solution = lowest_cost_solution
        solution_step = lowest_cost_step
        solution_trial = lowest_cost_trial
    else:
        solution = best_valid_solution
        solution_step = best_valid_step
        solution_trial = best_valid_trial
    path_history = trial_histories[
        solution_trial]  # Could be empty when history = false
    if not path_history:
        path_history.append(solution)
    else:
        path_history = path_history[:(solution_step + 1)]
    return solution, path_history, solution_trial, solution_step
示例#10
0
def traj_optimize(robot,
                  start_cfg,
                  target_cfg,
                  dist_est,
                  initial_guess=None,
                  history=False):
    N_WAYPOINTS = 50
    NUM_RE_TRIALS = 1  #10
    UPDATE_STEPS = 400
    dif_weight = 5
    max_move_weight = 10
    collision_weight = 10
    joint_limit_weight = 10
    safety_margin = -1  # Corresponds to safety_bias in paper
    lr = 1e-2
    seed = 19961221
    torch.manual_seed(seed)

    lowest_cost_solution = None
    lowest_cost = np.inf
    lowest_cost_trial = None
    lowest_cost_step = None
    best_valid_solution = None
    best_valid_cost = np.inf
    best_valid_step = None
    best_valid_trial = None

    trial_histories = []

    found = False
    for trial_time in range(NUM_RE_TRIALS):
        path_history = []
        if trial_time == 0:
            if initial_guess is None:
                init_path = torch.from_numpy(
                    np.linspace(start_cfg, target_cfg, num=N_WAYPOINTS))
            else:
                init_path = initial_guess
        else:
            init_path = (torch.rand(N_WAYPOINTS,
                                    robot.dof)) * np.pi * 2 - np.pi
        init_path[0] = start_cfg
        init_path[-1] = target_cfg
        p = init_path.requires_grad_(True)
        opt = torch.optim.Adam([p], lr=lr)

        for step in range(UPDATE_STEPS):
            opt.zero_grad()
            assert p.dtype == torch.float
            collision_score = torch.clamp(dist_est(p) - safety_margin,
                                          min=0).sum()
            control_points = robot.fkine(p, reuse=True)
            max_move_cost = torch.clamp(
                (control_points[1:] - control_points[:-1]).pow(2).sum(dim=2) -
                0.03**2,
                min=0).sum()
            joint_limit_cost = (
                torch.clamp(robot.limits[:, 0] - p, min=0) +
                torch.clamp(p - robot.limits[:, 1], min=0)).sum()
            diff = (control_points[1:] - control_points[:-1]).pow(2).sum() + (
                utils.wrap2pi(p[1:] - p[:-1])).pow(2).sum()

            constraint_loss = collision_weight * collision_score \
                + max_move_weight * max_move_cost + joint_limit_weight * joint_limit_cost
            opt_loss = dif_weight * diff
            loss = constraint_loss + opt_loss
            loss.backward()
            p.grad[[0, -1]] = 0.0  # Do not change start and goal configuration
            opt.step()
            p.data = utils.wrap2pi(
                p.data)  # Do not wrap if your configuration is not angular
            if history:
                path_history.append(p.data.clone())
            if loss.data.numpy() < lowest_cost:
                lowest_cost = loss.data.numpy()
                lowest_cost_solution = p.data.clone()
                lowest_cost_step = step
                lowest_cost_trial = trial_time
            if constraint_loss <= 1e-2:
                if opt_loss.data.numpy() < best_valid_cost:
                    best_valid_cost = opt_loss.data.numpy()
                    best_valid_solution = p.data.clone()
                    best_valid_step = step
                    best_valid_trial = trial_time
            if constraint_loss <= 1e-2 or step % (
                    UPDATE_STEPS / 5) == 0 or step == UPDATE_STEPS - 1:
                print(
                    'Trial {}: Step {}, collision={:.3f}*{:.1f}, max_move={:.3f}*{:.1f}, joint_limit={:.3f}*{:.1f}, diff={:.3f}*{:.1f}, Loss={:.3f}'
                    .format(trial_time, step,
                            collision_score.item(), collision_weight,
                            max_move_cost.item(), max_move_weight,
                            joint_limit_cost.item(), joint_limit_weight,
                            diff.item(), dif_weight, loss.item()))
        trial_histories.append(path_history)

        if best_valid_solution is not None:
            found = True
            break

    if not found:
        print('Did not find a valid solution after {} trials!\
            Giving the lowest cost solution'.format(NUM_RE_TRIALS))
        solution = lowest_cost_solution
        solution_step = lowest_cost_step
        solution_trial = lowest_cost_trial
    else:
        solution = best_valid_solution
        solution_step = best_valid_step
        solution_trial = best_valid_trial
    path_history = trial_histories[
        solution_trial]  # Could be empty when history = false
    if not path_history:
        path_history.append(solution)
    else:
        path_history = path_history[:(solution_step + 1)]
    return solution, path_history, solution_trial, solution_step