Esempio n. 1
0
    def linear_program3(self, lines, numObstLines, beginLine, radius, result):
        """
        Solves a two-dimensional linear program subject to linear constraints defined by lines and a circular constraint.

        Args:
            lines (list): Lines defining the linear constraints.
            numObstLines (int): Count of obstacle lines.
            beginLine (int): The line on which the 2-d linear program failed.
            radius (float): The radius of the circular constraint.
            result (Vector2): A reference to the result of the linear program.

        Returns:
            Vector2: A reference to the result of the linear program.
        """
        distance = 0.0

        for i in range(beginLine, len(lines)):
            if rvo_math.det(lines[i].direction, lines[i].point - result) > distance:
                # Result does not satisfy constraint of line i.
                projLines = []

                for ii in range(numObstLines):
                    projLines.append(lines[ii])

                for j in range(numObstLines, i):
                    line = Line()
                    determinant = rvo_math.det(
                        lines[i].direction, lines[j].direction)

                    if abs(determinant) <= rvo_math.EPSILON:
                        # Line i and line j are parallel.
                        if lines[i].direction @ lines[j].direction > 0.0:
                            # Line i and line j point in the same direction.
                            continue
                        else:
                            # Line i and line j point in opposite direction.
                            line.point = 0.5 * \
                                (lines[i].point + lines[j].point)
                    else:
                        line.point = lines[i].point + (rvo_math.det(
                            lines[j].direction, lines[i].point - lines[j].point) / determinant) * lines[i].direction

                    line.direction = rvo_math.normalize(
                        lines[j].direction - lines[i].direction)
                    projLines.append(line)

                tempResult = result
                lineFail, result = self.linear_program2(
                    projLines, radius, Vector2(-lines[i].direction.y, lines[i].direction.x), True, result)
                if lineFail < len(projLines):
                    """
                    This should in principle not happen. The result is by definition already in the feasible region of this linear program. If it fails, it is due to small floating point error, and the current result is kept.
                    """
                    result = tempResult

                distance = rvo_math.det(
                    lines[i].direction, lines[i].point - result)
        return result
Esempio n. 2
0
 def set_preferred_velocities(self):
     for i in range(self.num_agents):
         pos = self.agents_[i].position_
         target = self.goals[i][0]
         g_heading = rvo_math.normalize(target - pos) * Max_Speed
         dists = self.dist_to_goals(pos, self.goals[i])
         self.d_prev[i] = dists
         self.v_prev[i] = self.agents_[i].velocity_
         self.set_agent_pref_velocity(i, g_heading)
Esempio n. 3
0
    def set_preferred_velocities(self):
        """
        Set the preferred velocity to be a vector of unit magnitude (speed) in the direction of the goal.
        """
        for i in range(self.simulator_.num_agents):
            goal_vector = self.goals_[i] - self.simulator_.agents_[i].position_

            if rvo_math.abs_sq(goal_vector) > 1.0:
                goal_vector = rvo_math.normalize(goal_vector)

            self.simulator_.set_agent_pref_velocity(i, goal_vector)
Esempio n. 4
0
 def action_to_vector(pos, target, action, max_speed, ORCA=False):
     angle, speed = action[0], max_speed
     heading = rvo_math.normalize(target-pos)
     # if ORCA:
     #     heading = rvo_math.normalize(target-pos)
     # else:
     #     heading = Vector2(1., 0.)  # rvo_math.normalize(target-pos)
     # angle = -math.pi + random.random() * 2 * math.pi
     x1, y1 = heading.x, heading.y
     x2 = math.cos(angle) * x1 - math.sin(angle) * y1
     y2 = math.sin(angle) * x1 + math.cos(angle) * y1
     return speed * Vector2(x2, y2)
Esempio n. 5
0
    def set_preferred_velocities(self):
        # Set the preferred velocity to be a vector of unit magnitude (speed) in the direction of the goal.
        for i in range(self.simulator_.num_agents):
            goal_vector = self.goals_[i] - self.simulator_.agents_[i].position_

            if rvo_math.abs_sq(goal_vector) > 1.0:
                goal_vector = rvo_math.normalize(goal_vector)

            self.simulator_.set_agent_pref_velocity(i, goal_vector)

            # Perturb a little to avoid deadlocks due to perfect symmetry.
            angle = random.random() * 2.0 * math.pi
            dist = random.random() * 0.0001

            self.simulator_.set_agent_pref_velocity(
                i, self.simulator_.agents_[i].pref_velocity_ +
                dist * Vector2(math.cos(angle), math.sin(angle)))
Esempio n. 6
0
    def add_obstacle(self, vertices):
        """
        Adds a new obstacle to the simulation.

        Args:
            vertices (list): List of the vertices of the polygonal obstacle in counterclockwise order.

        Returns:
            int: The number of the first vertex of the obstacle, or -1 when the number of vertices is less than two.

        Remarks:
            To add a "negative" obstacle, e.g. a bounding polygon around the environment, the vertices should be listed in clockwise order.
        """
        if len(vertices) < 2:
            raise ArgumentError('Must have at least 2 vertices.')

        obstacleNo = len(self.obstacles_)

        for i in range(len(vertices)):
            obstacle = Obstacle()
            obstacle.point_ = vertices[i]

            if i != 0:
                obstacle.previous_ = self.obstacles_[len(self.obstacles_) - 1]
                obstacle.previous_.next_ = obstacle

            if i == len(vertices) - 1:
                obstacle.next_ = self.obstacles_[obstacleNo]
                obstacle.next_.previous_ = obstacle

            obstacle.direction_ = rvo_math.normalize(
                vertices[0 if i == len(vertices) - 1 else i + 1] - vertices[i])

            if len(vertices) == 2:
                obstacle.convex_ = True
            else:
                obstacle.convex_ = rvo_math.left_of(
                    vertices[len(vertices) - 1 if i == 0 else i - 1],
                    vertices[i],
                    vertices[0 if i == len(vertices) - 1 else i + 1]) >= 0.0

            obstacle.id_ = len(self.obstacles_)
            self.obstacles_.append(obstacle)

        return obstacleNo
Esempio n. 7
0
    def cal_collision_reward(self, pos, goals, vel, d_cur):
        d_cur_np = np.array(d_cur)

        rewards = []
        for goal in goals:
            direct = rvo_math.normalize(goal-pos)
            reward = (direct.x*vel.x + direct.y*vel.y)/Max_Speed
            rewards.append(reward)
        pos_count = np.sum(list(map(lambda x: x >= 0, rewards)))
        if pos_count.item() > 1:
            important_ratio = d_cur_np.max() / d_cur_np
            important_ratio = important_ratio / important_ratio.max()
            rewards = important_ratio * np.array(rewards)
        elif pos_count.item() == 1:
            return np.array(rewards).max()
        else:
            important_ratio = d_cur_np / d_cur_np.max()
            rewards = important_ratio * np.array(rewards)
        return rewards.max()
Esempio n. 8
0
    def linear_program2(self, lines, radius, optVelocity, directionOpt,
                        result):
        """
        Solves a two-dimensional linear program subject to linear constraints defined by lines and a circular constraint.

        Args:
            lines (list): Lines defining the linear constraints.
            radius (float): The radius of the circular constraint.
            optVelocity (Vector2): The optimization velocity.
            directionOpt (bool): True if the direction should be optimized.
            result (Vector2): A reference to the result of the linear program.

        Returns:
            int: The number of the line it fails on, and the number of lines if successful.
            Vector2: A reference to the result of the linear program.
        """
        if directionOpt:
            # Optimize direction. Note that the optimization velocity is of unit length in this case.
            result = optVelocity * radius
        elif rvo_math.abs_sq(optVelocity) > rvo_math.square(radius):
            # Optimize closest point and outside circle.
            result = rvo_math.normalize(optVelocity) * radius
        else:
            # Optimize closest point and inside circle.
            result = optVelocity

        for i in range(len(lines)):
            if rvo_math.det(lines[i].direction, lines[i].point - result) > 0.0:
                # Result does not satisfy constraint i. Compute new optimal result.
                tempResult = result
                success, result = self.linear_program1(lines, i, radius,
                                                       optVelocity,
                                                       directionOpt)
                if not success:
                    result = tempResult
                    return i, result

        return len(lines), result
Esempio n. 9
0
    def compute_new_velocity(self):
        """
        Computes the new velocity of this agent.
        """
        self.orca_lines_ = []

        invTimeHorizonObst = 1.0 / self.time_horizon_obst_

        # Create obstacle ORCA lines.
        for i in range(len(self.obstacle_neighbors_)):
            obstacle1 = self.obstacle_neighbors_[i][1]
            obstacle2 = obstacle1.next_

            relativePosition1 = obstacle1.point_ - self.position_
            relativePosition2 = obstacle2.point_ - self.position_

            # Check if velocity obstacle of obstacle is already taken care of by previously constructed obstacle ORCA lines.
            alreadyCovered = False

            for j in range(len(self.orca_lines_)):
                det1 = rvo_math.det(
                    invTimeHorizonObst * relativePosition1 -
                    self.orca_lines_[j].point, self.orca_lines_[j].direction)
                det2 = rvo_math.det(
                    invTimeHorizonObst * relativePosition2 -
                    self.orca_lines_[j].point, self.orca_lines_[j].direction)
                if (det1 - invTimeHorizonObst * self.radius_ >=
                        -rvo_math.EPSILON) and (
                            det2 - invTimeHorizonObst * self.radius_ >=
                            -rvo_math.EPSILON):
                    alreadyCovered = True
                    break

            if alreadyCovered:
                continue

            # Not yet covered. Check for collisions.
            distSq1 = rvo_math.abs_sq(relativePosition1)
            distSq2 = rvo_math.abs_sq(relativePosition2)

            radiusSq = rvo_math.square(self.radius_)

            obstacleVector = obstacle2.point_ - obstacle1.point_
            s = (-relativePosition1
                 @ obstacleVector) / rvo_math.abs_sq(obstacleVector)
            distSqLine = rvo_math.abs_sq(-relativePosition1 -
                                         s * obstacleVector)

            line = Line()

            if s < 0.0 and distSq1 <= radiusSq:
                # Collision with left vertex. Ignore if non-convex.
                if obstacle1.convex_:
                    line.point = Vector2(0.0, 0.0)
                    line.direction = rvo_math.normalize(
                        Vector2(-relativePosition1.y, relativePosition1.x))
                    self.orca_lines_.append(line)
                continue
            elif s > 1.0 and distSq2 <= radiusSq:
                # Collision with right vertex. Ignore if non-convex or if it will be taken care of by neighboring obstacle.
                if obstacle2.convex_ and rvo_math.det(
                        relativePosition2, obstacle2.direction_) >= 0.0:
                    line.point = Vector2(0.0, 0.0)
                    line.direction = rvo_math.normalize(
                        Vector2(-relativePosition2.y, relativePosition2.x))
                    self.orca_lines_.append(line)
                continue
            elif s >= 0.0 and s < 1.0 and distSqLine <= radiusSq:
                # Collision with obstacle segment.
                line.point = Vector2(0.0, 0.0)
                line.direction = -obstacle1.direction_
                self.orca_lines_.append(line)
                continue

            # No collision. Compute legs. When obliquely viewed, both legs can come from a single vertex. Legs extend cut-off line when non-convex vertex.
            leftLegDirection = None
            rightLegDirection = None

            if s < 0.0 and distSqLine <= radiusSq:
                # Obstacle viewed obliquely so that left vertex defines velocity obstacle.
                if not obstacle1.convex_:
                    # Ignore obstacle.
                    continue

                obstacle2 = obstacle1

                leg1 = math.sqrt(distSq1 - radiusSq)
                leftLegDirection = Vector2(
                    relativePosition1.x * leg1 - relativePosition1.y *
                    self.radius_, relativePosition1.x * self.radius_ +
                    relativePosition1.y * leg1) / distSq1
                rightLegDirection = Vector2(
                    relativePosition1.x * leg1 + relativePosition1.y *
                    self.radius_, -relativePosition1.x * self.radius_ +
                    relativePosition1.y * leg1) / distSq1
            elif s > 1.0 and distSqLine <= radiusSq:
                # Obstacle viewed obliquely so that right vertex defines velocity obstacle.
                if not obstacle2.convex_:
                    # Ignore obstacle.
                    continue

                obstacle1 = obstacle2

                leg2 = math.sqrt(distSq2 - radiusSq)
                leftLegDirection = Vector2(
                    relativePosition2.x * leg2 - relativePosition2.y *
                    self.radius_, relativePosition2.x * self.radius_ +
                    relativePosition2.y * leg2) / distSq2
                rightLegDirection = Vector2(
                    relativePosition2.x * leg2 + relativePosition2.y *
                    self.radius_, -relativePosition2.x * self.radius_ +
                    relativePosition2.y * leg2) / distSq2
            else:
                # Usual situation.
                if obstacle1.convex_:
                    leg1 = math.sqrt(distSq1 - radiusSq)
                    leftLegDirection = Vector2(
                        relativePosition1.x * leg1 - relativePosition1.y *
                        self.radius_, relativePosition1.x * self.radius_ +
                        relativePosition1.y * leg1) / distSq1
                else:
                    # Left vertex non-convex left leg extends cut-off line.
                    leftLegDirection = -obstacle1.direction_

                if obstacle2.convex_:
                    leg2 = math.sqrt(distSq2 - radiusSq)
                    rightLegDirection = Vector2(
                        relativePosition2.x * leg2 + relativePosition2.y *
                        self.radius_, -relativePosition2.x * self.radius_ +
                        relativePosition2.y * leg2) / distSq2
                else:
                    # Right vertex non-convex right leg extends cut-off line.
                    rightLegDirection = obstacle1.direction_

            # Legs can never point into neighboring edge when convex vertex, take cutoff-line of neighboring edge instead. If velocity projected on "foreign" leg, no constraint is added.

            leftNeighbor = obstacle1.previous_

            isLeftLegForeign = False
            isRightLegForeign = False

            if obstacle1.convex_ and rvo_math.det(
                    leftLegDirection, -leftNeighbor.direction_) >= 0.0:
                # Left leg points into obstacle.
                leftLegDirection = -leftNeighbor.direction_
                isLeftLegForeign = True

            if obstacle2.convex_ and rvo_math.det(rightLegDirection,
                                                  obstacle2.direction_) <= 0.0:
                # Right leg points into obstacle.
                rightLegDirection = obstacle2.direction_
                isRightLegForeign = True

            # Compute cut-off centers.
            leftCutOff = invTimeHorizonObst * (obstacle1.point_ -
                                               self.position_)
            rightCutOff = invTimeHorizonObst * (obstacle2.point_ -
                                                self.position_)
            cutOffVector = rightCutOff - leftCutOff

            # Project current velocity on velocity obstacle.

            # Check if current velocity is projected on cutoff circles.
            t = 0.5 if obstacle1 == obstacle2 else (
                (self.velocity_ -
                 leftCutOff) @ cutOffVector) / rvo_math.abs_sq(cutOffVector)
            tLeft = (self.velocity_ - leftCutOff) @ leftLegDirection
            tRight = (self.velocity_ - rightCutOff) @ rightLegDirection

            if (t < 0.0 and tLeft < 0.0) or (obstacle1 == obstacle2
                                             and tLeft < 0.0 and tRight < 0.0):
                # Project on left cut-off circle.
                unitW = rvo_math.normalize(self.velocity_ - leftCutOff)
                line.direction = Vector2(unitW.y, -unitW.x)
                line.point = leftCutOff + self.radius_ * invTimeHorizonObst * unitW
                self.orca_lines_.append(line)
                continue

            elif t > 1.0 and tRight < 0.0:
                # Project on right cut-off circle.
                unitW = rvo_math.normalize(self.velocity_ - rightCutOff)
                line.direction = Vector2(unitW.y, -unitW.x)
                line.point = rightCutOff + self.radius_ * invTimeHorizonObst * unitW
                self.orca_lines_.append(line)
                continue

            # Project on left leg, right leg, or cut-off line, whichever is closest to velocity.
            distSqCutoff = math.inf if t < 0.0 or t > 1.0 or obstacle1 == obstacle2 else rvo_math.abs_sq(
                self.velocity_ - (leftCutOff + t * cutOffVector))
            distSqLeft = math.inf if tLeft < 0.0 else rvo_math.abs_sq(
                self.velocity_ - (leftCutOff + tLeft * leftLegDirection))
            distSqRight = math.inf if tRight < 0.0 else rvo_math.abs_sq(
                self.velocity_ - (rightCutOff + tRight * rightLegDirection))

            if distSqCutoff <= distSqLeft and distSqCutoff <= distSqRight:
                # Project on cut-off line.
                line.direction = -obstacle1.direction_
                line.point = leftCutOff + self.radius_ * invTimeHorizonObst * Vector2(
                    -line.direction.y, line.direction.x)
                self.orca_lines_.append(line)
                continue

            if distSqLeft <= distSqRight:
                # Project on left leg.
                if isLeftLegForeign:
                    continue

                line.direction = leftLegDirection
                line.point = leftCutOff + self.radius_ * invTimeHorizonObst * Vector2(
                    -line.direction.y, line.direction.x)
                self.orca_lines_.append(line)

                continue

            # Project on right leg.
            if isRightLegForeign:
                continue

            line.direction = -rightLegDirection
            line.point = rightCutOff + self.radius_ * invTimeHorizonObst * Vector2(
                -line.direction.y, line.direction.x)
            self.orca_lines_.append(line)

        numObstLines = len(self.orca_lines_)

        invTimeHorizon = 1.0 / self.time_horizon_

        # Create agent ORCA lines.
        for i in range(len(self.agent_neighbors_)):
            other = self.agent_neighbors_[i][1]

            relativePosition = other.position_ - self.position_
            relativeVelocity = self.velocity_ - other.velocity_

            distSq = rvo_math.abs_sq(relativePosition)
            combinedRadius = self.radius_ + other.radius_
            combinedRadiusSq = rvo_math.square(combinedRadius)

            line = Line()
            u = Vector2()

            if distSq > combinedRadiusSq:
                # No collision.
                w = relativeVelocity - invTimeHorizon * relativePosition

                # Vector from cutoff center to relative velocity.
                wLengthSq = rvo_math.abs_sq(w)
                dotProduct1 = w @ relativePosition

                if dotProduct1 < 0.0 and rvo_math.square(
                        dotProduct1) > combinedRadiusSq * wLengthSq:
                    # Project on cut-off circle.
                    wLength = math.sqrt(wLengthSq)
                    unitW = w / wLength

                    line.direction = Vector2(unitW.y, -unitW.x)
                    u = (combinedRadius * invTimeHorizon - wLength) * unitW
                else:
                    # Project on legs.
                    leg = math.sqrt(distSq - combinedRadiusSq)

                    if rvo_math.det(relativePosition, w) > 0.0:
                        # Project on left leg.
                        line.direction = Vector2(
                            relativePosition.x * leg -
                            relativePosition.y * combinedRadius,
                            relativePosition.x * combinedRadius +
                            relativePosition.y * leg) / distSq
                    else:
                        # Project on right leg.
                        line.direction = -Vector2(
                            relativePosition.x * leg + relativePosition.y *
                            combinedRadius, -relativePosition.x *
                            combinedRadius + relativePosition.y * leg) / distSq

                    dotProduct2 = relativeVelocity @ line.direction
                    u = dotProduct2 * line.direction - relativeVelocity
            else:
                # Collision. Project on cut-off circle of time timeStep.
                invTimeStep = 1.0 / self.simulator_.time_step_

                # Vector from cutoff center to relative velocity.
                w = relativeVelocity - invTimeStep * relativePosition

                wLength = abs(w)
                unitW = w / wLength

                line.direction = Vector2(unitW.y, -unitW.x)
                u = (combinedRadius * invTimeStep - wLength) * unitW

            line.point = self.velocity_ + 0.5 * u
            self.orca_lines_.append(line)

        lineFail, self.new_velocity_ = self.linear_program2(
            self.orca_lines_, self.max_speed_, self.pref_velocity_, False,
            self.new_velocity_)

        if lineFail < len(self.orca_lines_):
            self.new_velocity_ = self.linear_program3(self.orca_lines_,
                                                      numObstLines, lineFail,
                                                      self.max_speed_,
                                                      self.new_velocity_)
Esempio n. 10
0
 def cal_smooth_rewards(self, v_prev, v_cur):
     v_prev_ = rvo_math.normalize(v_prev)
     v_cur_ = rvo_math.normalize(v_cur)
     dot_product = v_prev_.x * v_cur_.x + v_prev_.y * v_cur_.y
     reward = dot_product * 1.0
     return reward