Skip to content

SampleSearcher

src.python_motion_planning.global_planner.sample_search.sample_search.SampleSearcher

Bases: Planner

Base class for planner based on sample searching.

Parameters:

Name Type Description Default
start tuple

start point coordinate

required
goal tuple

goal point coordinate

required
env Map

environment

required
Source code in src\python_motion_planning\global_planner\sample_search\sample_search.py
Python
class SampleSearcher(Planner):
    """
    Base class for planner based on sample searching.

    Parameters:
        start (tuple): start point coordinate
        goal (tuple): goal point coordinate
        env (Map): environment
    """
    def __init__(self, start: tuple, goal: tuple, env: Map, delta: float=0.5) -> None:
        super().__init__(start, goal, env)
        # inflation bias
        self.delta = delta

    def isCollision(self, node1: Node, node2: Node) -> bool:
        """
        Judge collision when moving from node1 to node2.

        Parameters:
            node1 (Node): node 1
            node2 (Node): node 2

        Returns:
            collision (bool): True if collision exists else False
        """
        if self.isInsideObs(node1) or self.isInsideObs(node2):
            return True

        for rect in self.env.obs_rect:
            if self.isInterRect(node1, node2, rect):
                return True

        for circle in self.env.obs_circ:
            if self.isInterCircle(node1, node2, circle):
                return True

        return False

    def isInsideObs(self, node: Node) -> bool:
        """
        Judge whether a node inside tht obstacles or not.

        Parameters:
            node (Node): node

        Returns:
            inside (bool): True if inside the obstacles else False
        """
        x, y = node.current

        for (ox, oy, r) in self.env.obs_circ:
            if math.hypot(x - ox, y - oy) <= r + self.delta:
                return True

        for (ox, oy, w, h) in self.env.obs_rect:
            if 0 <= x - (ox - self.delta) <= w + 2 * self.delta \
                and 0 <= y - (oy - self.delta) <= h + 2 * self.delta:
                return True

        for (ox, oy, w, h) in self.env.boundary:
            if 0 <= x - (ox - self.delta) <= w + 2 * self.delta \
                and 0 <= y - (oy - self.delta) <= h + 2 * self.delta:
                return True

        return False

    def isInterRect(self, node1: Node, node2: Node, rect: list) -> bool:
        # obstacle and it's vertex
        ox, oy, w, h = rect
        vertex = [[ox - self.delta, oy - self.delta],
                  [ox + w + self.delta, oy - self.delta],
                  [ox + w + self.delta, oy + h + self.delta],
                  [ox - self.delta, oy + h + self.delta]]

        # node
        x1, y1 = node1.current
        x2, y2 = node2.current

        def cross(p1, p2, p3):
            x1 = p2[0] - p1[0]
            y1 = p2[1] - p1[1]
            x2 = p3[0] - p1[0]
            y2 = p3[1] - p1[1]
            return x1 * y2 - x2 * y1

        for v1, v2 in combinations(vertex, 2):
            # rapid repulsion
            if  max(x1, x2) >= min(v1[0], v2[0]) and \
                min(x1, x2) <= max(v1[0], v2[0]) and \
                max(y1, y2) >= min(v1[1], v2[1]) and \
                min(y1, y2) <= max(v1[1], v2[1]): 
                # cross
                if cross(v1, v2, node1.current) * cross(v1, v2, node2.current) <= 0 and \
                   cross(node1.current, node2.current, v1) * cross(node1.current, node2.current, v2) <= 0:
                    return True

        return False

    def isInterCircle(self, node1: Node, node2: Node, circle: list) -> bool:
        # obstacle
        ox, oy, r = circle

        # origin
        x, y = node1.current

        # direction
        dx = node2.x - node1.x
        dy = node2.y - node1.y
        d  = [dx, dy]
        d2 = np.dot(d, d)

        if d2 == 0:
            return False

        # projection
        t = np.dot([ox - x, oy - y], d) / d2
        if 0 <= t <= 1:
            shot = Node((x + t * dx, y + t * dy), None, None, None)
            center = Node((ox, oy), None, None, None)
            if self.dist(shot, center) <= r + self.delta:
                return True

        return False

isCollision(node1, node2)

Judge collision when moving from node1 to node2.

Parameters:

Name Type Description Default
node1 Node

node 1

required
node2 Node

node 2

required

Returns:

Name Type Description
collision bool

True if collision exists else False

Source code in src\python_motion_planning\global_planner\sample_search\sample_search.py
Python
def isCollision(self, node1: Node, node2: Node) -> bool:
    """
    Judge collision when moving from node1 to node2.

    Parameters:
        node1 (Node): node 1
        node2 (Node): node 2

    Returns:
        collision (bool): True if collision exists else False
    """
    if self.isInsideObs(node1) or self.isInsideObs(node2):
        return True

    for rect in self.env.obs_rect:
        if self.isInterRect(node1, node2, rect):
            return True

    for circle in self.env.obs_circ:
        if self.isInterCircle(node1, node2, circle):
            return True

    return False

isInsideObs(node)

Judge whether a node inside tht obstacles or not.

Parameters:

Name Type Description Default
node Node

node

required

Returns:

Name Type Description
inside bool

True if inside the obstacles else False

Source code in src\python_motion_planning\global_planner\sample_search\sample_search.py
Python
def isInsideObs(self, node: Node) -> bool:
    """
    Judge whether a node inside tht obstacles or not.

    Parameters:
        node (Node): node

    Returns:
        inside (bool): True if inside the obstacles else False
    """
    x, y = node.current

    for (ox, oy, r) in self.env.obs_circ:
        if math.hypot(x - ox, y - oy) <= r + self.delta:
            return True

    for (ox, oy, w, h) in self.env.obs_rect:
        if 0 <= x - (ox - self.delta) <= w + 2 * self.delta \
            and 0 <= y - (oy - self.delta) <= h + 2 * self.delta:
            return True

    for (ox, oy, w, h) in self.env.boundary:
        if 0 <= x - (ox - self.delta) <= w + 2 * self.delta \
            and 0 <= y - (oy - self.delta) <= h + 2 * self.delta:
            return True

    return False