def parallel_connect_worker(batches, interp_fn, distance_fn, sim_context_cls,
                            sim_config):
    sim_context = sim_context_cls(sim_config, setup=False)
    sim_context.setup(sim_overrides={"run_parallel": True, "use_gui": False})
    sim = sim_context.get_sim_instance()
    _ = sim_context.get_logger()
    _ = sim_context.get_state_space()
    svc = sim_context.get_state_validity()
    sawyer_robot = sim_context.get_robot()
    _ = sawyer_robot.get_simulator_id()

    # Disabled collisions during planning with certain exclusions in place.
    # collision_exclusions = sim_context.get_collision_exclusions()
    collision_exclusions = {}

    with DisabledCollisionsContext(sim, **collision_exclusions):
        connections = []
        for batch in batches:
            q_sample = batch[0]
            neighbors = batch[1]
            for q_near in neighbors:
                local_path = interp_fn(np.array(q_near),
                                       np.array(q_sample),
                                       steps=10)
                valid = subdivision_evaluate(svc.validate, local_path)
                if valid:
                    connections.append(
                        [q_near, q_sample,
                         distance_fn(local_path)])
        return connections
 def _extend(self, q_near, q_rand):
     local_path = self.interp_fn(np.array(q_near), np.array(q_rand))
     valid = subdivision_evaluate(self.svc.validate, local_path)
     if valid:
         return True, local_path
     else:
         return False, []
 def get_lazy_path(self):
     success = False
     # The successful path we will build by iteratively moving through the best current path and redirecting it as needed according
     # to state validity etc,.
     successful_vertex_sequence = []
     # Find the initial best path in the graph, if it exists.
     current_best_plan = self._get_best_path("start", "goal")
     while not success:
         if current_best_plan is None or len(current_best_plan) == 1:
             return []
         points = [(_id,
                    self.graph.vs[self.graph.vs['id'].index(_id)]['value'])
                   for _id in current_best_plan]
         for idx, _ in enumerate(points):
             # we first get the current or 'from' vertex id of wherever we are in the path.
             from_id = points[idx][0]
             # we first get the current or 'from' value of wherever we are in the path.
             from_value = points[idx][1]
             to_id = points[idx + 1][0]  # get the 'to' point vertex id
             to_value = points[idx + 1][1]  # get the 'to' point value
             if to_id in successful_vertex_sequence:
                 continue
             if self._validate(to_value):  # validate the 'to' point value
                 # generate an interpolated path between 'from' and 'to'
                 segment = self.interp_fn(np.array(from_value),
                                          np.array(to_value))
                 # perform segment evaluation for state validity etc
                 valid = subdivision_evaluate(self.svc.validate, segment)
                 if valid:
                     # if valid, we add the 'to' vertex id since we know we can reach it
                     successful_vertex_sequence.append(to_id)
                     goal_idx = self.graph.vs[self.graph.vs['name'].index(
                         "goal")].index
                     if to_id == goal_idx:
                         success = True  # if we made a path to goal, then planning was a success and we can break out
                         break
                     current_best_plan = self._get_best_path(
                         "start", "goal")
                 else:
                     self._remove_edge(from_id, to_id)
                     current_best_plan = self._get_best_path(
                         "start", "goal")
                     successful_vertex_sequence = []
                     break  # we break out of looping with for loop to generate a new best path
             else:
                 # if the 'to' point is invalid, then we remove it and associated edges from the graph
                 self._remove_node_and_edges(to_id)
                 successful_vertex_sequence = []
                 current_best_plan = self._get_best_path("start", "goal")
                 break
     successful_vertex_sequence.insert(
         0, self.graph.vs[self.graph.vs['name'].index("start")].index)
     return [
         self.graph.vs['id'].index(_id)
         for _id in successful_vertex_sequence
     ]
 def shortcut(plan):
     idx_range = [i for i in range(0, len(plan))]
     indexed_plan = list(zip(idx_range, plan))
     for curr_idx, vid1 in indexed_plan:
         for test_idx, vid2 in indexed_plan[::-1]:
             v1 = self.graph.vs[vid1]
             v2 = self.graph.vs[vid2]
             p1 = self.graph.vs[vid1]["value"]
             p2 = self.graph.vs[vid2]["value"]
             segment = self.interp_fn(np.array(p1), np.array(p2))
             valid = subdivision_evaluate(self.svc.validate, segment)
             if test_idx == curr_idx + 1:
                 break
             if valid and curr_idx < test_idx:
                 del plan[curr_idx + 1:test_idx]
                 return False, plan
     return True, plan
def parallel_connect_worker(batches):

    ########################################################
    # Create the Simulator and pass it a Logger (optional) #
    ########################################################
    logger = Logger()
    if not Simulator.is_instantiated():
        sim = Simulator(logger=logger, use_ros=False, use_gui=False,
                        use_real_time=True)  # Initialize the Simulator
    else:
        sim = Simulator.get_instance()

    #####################################
    # Create a Robot, or two, or three. #
    #####################################
    sawyer_robot = Sawyer("sawyer0", [0, 0, 0.9], fixed_base=1)

    #############################################
    # Create sim environment objects and assets #
    #############################################
    ground_plane = SimObject("Ground", "plane.urdf", [0, 0, 0])
    sawyer_id = sawyer_robot.get_simulator_id()

    # Exclude the ground plane and the pedestal feet from disabled collisions.
    excluded_bodies = [ground_plane.get_simulator_id()]  # the ground plane
    pedestal_feet_idx = get_joint_info_by_name(sawyer_id, 'pedestal_feet').idx
    # The (sawyer_idx, pedestal_feet_idx) tuple the ecluded from disabled collisions.
    excluded_body_link_pairs = [(sawyer_id, pedestal_feet_idx)]

    ##########
    # EXTEND #
    ##########
    valid_samples = []
    # Disabled collisions during planning with certain eclusions in place.
    with DisabledCollisionsContext(sim, excluded_bodies, excluded_body_link_pairs):
        #########################
        # STATE SPACE SELECTION #
        #########################
        # This inherently uses UniformSampler but a different sampling class could be injected.
        state_space = SawyerConfigurationSpace()

        ##############################
        # STATE VALIDITY FORMULATION #
        ##############################
        # Certain links in Sawyer seem to be permentently in self collision. This is how to remove them by name when getting all link pairs to check for self collision.
        excluded_pairs = [(get_joint_info_by_name(sawyer_id, "right_l1_2").idx, get_joint_info_by_name(sawyer_id, "right_l0").idx),
                          (get_joint_info_by_name(sawyer_id, "right_l1_2").idx, get_joint_info_by_name(sawyer_id, "head").idx)]
        link_pairs = get_link_pairs(sawyer_id, excluded_pairs=excluded_pairs)
        self_collision_fn = partial(
            self_collision_test, robot=sawyer_robot, link_pairs=link_pairs)

        # Create constraint checks
        # def constraint_test(q):
        #     upright_orientation = [
        #         0.0005812598018143569, 0.017721236427960724, -0.6896867930096543, 0.723890701324838]
        #     axis = 'z'
        #     threshold = 15
        #     world_pose, _ = sawyer_robot.solve_forward_kinematics(q)
        #     return orientation(upright_orientation, world_pose[1], threshold, axis)

        # In this case, we only have a self_col_fn.
        svc = StateValidityChecker(
            self_col_func=self_collision_fn, col_func=None, validity_funcs=None)
        # svc = StateValidityChecker(
        #     self_col_func=self_collision_fn, col_func=None, validity_funcs=[constraint_test])

        pairs = []
        for batch in batches:
            q_sample = batch[0]
            neighbors = batch[1]
            for q_near in neighbors:
                local_path = parametric_lerp(
                    np.array(q_near), np.array(q_sample), steps=10)
                valid = subdivision_evaluate(svc.validate, local_path)
                if valid:
                    pairs.append(
                        [q_near, q_sample, cumulative_distance(local_path)])
        return pairs
        # Goal is always at the 1 index.
        graph.vs[1]["value"] = end

        for sample in samples:
            graph.add_vertex(None, **{'value': list(sample)})

        for pair in connections:
            graph.add_edge(graph.vs['value'].index(list(pair[0])), graph.vs['value'].index(
                list(pair[1])), **{'weight': pair[2]})

        distances, neighbors = nn.query(np.array(start), k=10)
        for q_near in neighbors:
            if graph.vs['value'].index(q_near) != 0:
                local_path = parametric_lerp(
                    np.array(start), np.array(q_near), steps=10)
                valid = subdivision_evaluate(svc.validate, local_path)
                if valid:
                    graph.add_edge(graph.vs['value'].index(start), graph.vs['value'].index(list(q_near)), **{'weight': pair[2]})
                    break
        distances, neighbors = nn.query(np.array(end), k=10)
        for q_near in neighbors:
            if graph.vs['value'].index(q_near) != 0:
                local_path = parametric_lerp(
                    np.array(start), np.array(q_near), steps=10)
                valid = subdivision_evaluate(svc.validate, local_path)
                if valid:
                    graph.add_edge(graph.vs['value'].index(end), graph.vs['value'].index(list(q_near)), **{'weight': pair[2]})
                    break

        graph_path = graph.get_shortest_paths(
            'start', 'goal', weights='weight', mode='ALL')[0]