Example #1
0
    def react(self, this_robot, sensor_suite, visualize=False):
        twist = Twist()

        print "x, y, theta: {}, {}, {} ".format(this_robot.body.position.x,
                                                this_robot.body.position.y,
                                                this_robot.body.angle)

        return twist
Example #2
0
    def react(self, this_robot, sensor_suite, visualize=False):
        twist = Twist()

        rscan = sensor_suite.range_scan
        n = len(rscan.ranges)

        target = self.get_target(rscan)

        # Convert to an angle
        if target == None:
            target_angle = None
        else:
            target_angle = (rscan.ANGLE_MIN + target * (rscan.ANGLE_MAX - rscan.ANGLE_MIN) / float(rscan.NUMBER_POINTS))

        if self.modulate and target_angle != None:
            compass_angle = normalize_angle_pm_pi(this_robot.body.angle)
            if cos(2*compass_angle) < 0:
                # Dig in to push the puck more
                target_angle = target_angle - self.ingress_angle
            else:
                # Pull out to skirt the puck
                target_angle = target_angle + self.egress_angle

        # Check for the presence of another robot in the centre of the image.
        react_to_robot = False
        react_to_robot_angle = None
        for i in range(0, n):
            if (rscan.masks[i] == ROBOT_MASK and fabs(rscan.angles[i]) < pi/4 and
                rscan.ranges[i] < 2*this_robot.radius):
                react_to_robot = True
                react_to_robot_angle = (rscan.ANGLE_MIN + i * 
                    (rscan.ANGLE_MAX - rscan.ANGLE_MIN) / float(rscan.NUMBER_POINTS))

        if react_to_robot:
            # Turn left and slow
            twist.linear = self.slow_factor * self.linear_speed
            twist.angular = self.angular_speed

            if visualize: # Reacting to robot
                self.draw_line(this_robot, rscan, react_to_robot_angle,
                               (255, 0, 0))

        elif (target_angle == None or target_angle <= 0):
            # Turn right
            twist.linear = self.linear_speed
            twist.angular = - self.angular_speed

            if visualize:
                if target_angle != None:
                    self.draw_line(this_robot, rscan, target_angle, (0, 255, 0))
        else:
            # Turn left
            twist.linear = self.linear_speed
            twist.angular = self.angular_speed

            if visualize:
                self.draw_line(this_robot, rscan, target_angle, (255, 0, 255))

        return twist
    def react(self, robot, sensor_suite, visualize=False):

        range_scan = sensor_suite.range_scan

        twist = Twist()
        twist.linear = 4

        # Find closest distance < max range
        closestI = None
        closestRange = float('inf')
        for i in range(len(range_scan.ranges)):
            r = range_scan.ranges[i]
            if r < closestRange and r < range_scan.RANGE_MAX:
                closestI = i
                closestRange = r

        if closestI != None:
            if range_scan.angles[closestI] != 0:
                twist.angular = -1 / range_scan.angles[closestI]

        return twist
Example #4
0
    def react(self, this_robot, sensor_suite, visualize=False):
        twist = Twist()

        pucks = sensor_suite.puck_scan.pucks
        robots = sensor_suite.robot_scan.robots

        # First find the puck with the smallest absolute angle.
        frontal_puck_abs_angle = float('inf')
        frontal_puck_range = float('inf')
        for puck in pucks:
            if puck.kind == 0 and fabs(puck.angle) < frontal_puck_abs_angle:
                frontal_puck_abs_angle = fabs(puck.angle)
                frontal_puck_range = puck.distance

        # Now find the robot with the smallest absolute angle.
        frontal_bot_abs_angle = float('inf')
        frontal_bot_range = float('inf')
        for robot in robots:
            if fabs(robot.angle) < frontal_bot_abs_angle:
                frontal_bot_abs_angle = fabs(robot.angle)
                frontal_bot_range = robot.distance

        # Set the two predicates 'react_to_puck' and 'react_to_robot'
        react_to_puck = frontal_puck_abs_angle <= FRONT_THRESHOLD
        react_to_robot = frontal_bot_abs_angle <= FRONT_THRESHOLD
        if react_to_puck and react_to_robot:
            # Choose which is closer, then turn off the other.
            if frontal_puck_range < frontal_bot_range:
                react_to_robot = False
            else:
                react_to_puck = False

        # At this point only one of the two predicates should be true.
        assert not (react_to_robot and react_to_puck)

        # Now react...
        if react_to_puck:
            # Turn right
            twist.linear = 4
            twist.angular = -2.0
        elif react_to_robot:
            # Turn left and slow
            twist.linear = 2
            twist.angular = 2.0
        else:
            # Turn left
            twist.linear = 4
            twist.angular = 2.0

        return twist
    def react(self, this_robot, sensor_suite, visualize=False):
        twist = Twist()

        rscan = sensor_suite.range_scan
        lscan = sensor_suite.landmark_scan
        n = len(rscan.ranges)

        (left, right) = self.get_closest_landmark_pair_leftmost_indices(lscan)
        (left_angle, right_angle) = (self.index_to_angle(lcan, left),
                                     self.index_to_angle(lcan, left))

        self.draw_line(this_robot, rscan, left_angle, (255, 0, 0))
        self.draw_line(this_robot, rscan, right_angle, (0, 255, 0))
Example #6
0
    def __init__(self):
        self.mass = 1  # 1 kg

        # 0.1 meter radius, converted to pixels for display
        #self.radius = 0.05 * M_TO_PIXELS

        # Bupimo: 0.111 meter radius, converted to pixels for display
        self.radius = 0.111 * M_TO_PIXELS

        # moment of inertia for disk
        rob_I = moment_for_circle(self.mass, 0, self.radius)

        self.body = Body(self.mass, rob_I)
        self.body.position = 0, 0
        self.body.angle = 0
        self.body.velocity = 0, 0
        self.body.angular_velocity = 0

        """
        self.shape = Circle(self.body, self.radius)
        self.shape.color = 127, 0, 255  # a pinkish blue
        self.shape.filter = ShapeFilter(categories = ROBOT_MASK)
        """

        """
        r = self.radius
        p = self.radius / 2.0 # Amount the wedge part pokes out.
        vertices = [(r+p, r),
                    (-r/3, r),
                    (-r, 0),
                    (-r/3, -r),
                    (r/3, -r) ]
        """
        r = self.radius
        d = self.radius * 1.5 # Amount the wedge part pokes out.
        vertices = [(0, -r),
                    (d, 0),
                    (0, r)]
        # Now add the semicircular back part
        n = 3
        angles = [pi/2 + i*(pi/n) for i in range(1, n)]
        for a in angles:
            vertices.append((r*cos(a), r*sin(a)))

        vertices = vertices[::-1]

        self.shape = Poly(self.body, vertices)
        self.shape.color = 127, 0, 255  # a pinkish blue
        self.shape.filter = ShapeFilter(categories = ROBOT_MASK)

        self.command = Twist()
Example #7
0
    def __init__(self):
        self.mass = 1  # 1 kg

        # e-puck: 0.037 meter radius, converted to pixels for display
        #self.radius = 3.7 * CM_TO_PIXELS

        # Bupimo: 9 cm radius, converted to pixels for display
        self.radius = 9 * CM_TO_PIXELS

        self.circular = False;

        if self.circular:
            rob_I = moment_for_circle(self.mass, 0, self.radius)
            self.body = Body(self.mass, rob_I)
            self.shape = Circle(self.body, self.radius)
        else:
            r = self.radius
            d = self.radius * 1.5 # Amount the wedge part pokes out.
            vertices = [(0, -r),
                        (d, 0),
                        (0, r)]
            #vertices = [(0, -r),
            #            (d/4, 0),
            #            (d/2, r)]
            # Now add the semicircular back part
            n = 5
            angles = [pi/2 + i*(pi/n) for i in range(1, n)]
            for a in angles:
                vertices.append((r*cos(a), r*sin(a)))

            rob_I = moment_for_poly(self.mass, vertices)
            self.body = Body(self.mass, rob_I)
            self.shape = Poly(self.body, vertices)

            # EXPERIMENTAL: Add bristles to robot
#            rest_length = 100
#            stiffness = 500
#            damping = 10
#            self.bristle_body = pymunk.DampedSpring(self.body, body, \
#                                  (0,0), (0,0), rest_length, stiffness, damping)
#                self.sim.env.add(self.spring_body)

        self.body.position = 0, 0
        self.body.angle = 0
        self.body.velocity = 0, 0
        self.body.angular_velocity = 0
        self.shape.color = 0, 255, 0
        self.shape.filter = ShapeFilter(categories = ROBOT_MASK)

        self.command = Twist()
Example #8
0
    def react(self, this_robot, sensor_suite, visualize=False):
        twist = Twist()

        pucks = sensor_suite.puck_scan.pucks
        robots = sensor_suite.robot_scan.robots

        # First find the puck with the smallest absolute angle.
        frontal_puck_abs_angle = float('inf')
        frontal_puck_range = float('inf')
        for puck in pucks:
            if puck.kind == 0 and fabs(puck.angle) < frontal_puck_abs_angle:
                frontal_puck_abs_angle = fabs(puck.angle)
                frontal_puck_range = puck.distance

        # Now find the robot with the smallest absolute angle.
        frontal_bot_abs_angle = float('inf')
        frontal_bot_range = float('inf')
        for robot in robots:
            if fabs(robot.angle) < frontal_bot_abs_angle:
                frontal_bot_abs_angle = fabs(robot.angle)
                frontal_bot_range = robot.distance

        # Set the two predicates 'react_to_puck' and 'react_to_robot'
        react_to_puck = frontal_puck_abs_angle <= FRONT_THRESHOLD
        react_to_robot = frontal_bot_abs_angle <= FRONT_THRESHOLD
        if react_to_puck and react_to_robot:
            # Choose which is closer, then turn off the other.
            if frontal_puck_range < frontal_bot_range:
                react_to_robot = False
            else:
                react_to_puck = False

        # At this point only one of the two predicates should be true.
        assert not (react_to_robot and react_to_puck)

        # Now react...
        if react_to_puck:
            # Turn right
            twist.linear = 4
            twist.angular = -2.0
        elif react_to_robot:
            # Turn left and slow
            twist.linear = 2
            twist.angular = 2.0
        else:
            # Turn left
            twist.linear = 4
            twist.angular = 2.0
                
        return twist
Example #9
0
    def react(self, this_robot, sensor_suite, visualize=False):
        twist = Twist()

        rscan = sensor_suite.range_scan
        n = len(rscan.ranges)

        target = self.get_leftmost_pixel(rscan)

        # Convert to an angle
        if target == None:
            target_angle = None
        else:
            target_angle = self.index_to_angle(rscan, target)

        # EXPERIMENT TO ACHIEVE A MINIMUM SIZE AGGREGATE.
        lscan = sensor_suite.landmark_scan
        closest_lmark_distance = float('inf')
        for i in range(len(lscan.ranges)):
            if (lscan.masks[i] & ANY_LANDMARK_MASK != 0
               and lscan.ranges[i] < closest_lmark_distance):
                closest_lmark_distance = lscan.ranges[i]
        if closest_lmark_distance < self.circle_radius:
            target_angle = target_angle + self.egress_angle
        
        if self.modulate and target_angle != None:
            compass_angle = normalize_angle_pm_pi(this_robot.body.angle)
            if cos(2*compass_angle) < 0:
                # Dig in to push the puck more
                target_angle = target_angle - self.ingress_angle
            else:
                # Pull out to skirt the puck
                target_angle = target_angle + self.egress_angle

        # Check for the presence of another robot in the centre of the image.
        react_to_robot = False
        react_to_robot_angle = None
        for i in range(0, n):
            if (rscan.masks[i] == ROBOT_MASK and fabs(rscan.angles[i]) < pi/4 and
                rscan.ranges[i] < 2*this_robot.radius):
                react_to_robot = True
                react_to_robot_angle = (rscan.ANGLE_MIN + i * 
                    (rscan.ANGLE_MAX - rscan.ANGLE_MIN) / float(rscan.NUMBER_POINTS))

        if react_to_robot:
            # Turn left and slow
            twist.linear = self.slow_factor * self.linear_speed
            twist.angular = self.angular_speed

            if visualize: # Reacting to robot
                self.draw_line(this_robot, rscan, react_to_robot_angle,
                               (255, 0, 0))

        elif (target_angle == None or target_angle <= 0):
            # Turn right
            twist.linear = self.linear_speed
            twist.angular = - self.angular_speed

            if visualize:
                if target_angle != None:
                    self.draw_line(this_robot, rscan, target_angle, (0, 255, 0))
        else:
            # Turn left
            twist.linear = self.linear_speed
            twist.angular = self.angular_speed

            if visualize:
                self.draw_line(this_robot, rscan, target_angle, (255, 0, 255))

        self.summed_angular_speed += twist.angular

        #print self.summed_angular_speed

        return twist
Example #10
0
    def react(self, this_robot, sensor_suite, visualize=False):
        twist = Twist()

        rscan = sensor_suite.range_scan

        # Based on the closest landmark, determine whether we are inside or
        # outside the circle
        inside = False
        lscan = sensor_suite.landmark_scan
        closest_lmark_distance = float('inf')
        closest_lmark_angle = None
        for i in range(len(lscan.ranges)):
            if (lscan.masks[i] & ANY_LANDMARK_MASK != 0
                    and lscan.ranges[i] < closest_lmark_distance):
                closest_lmark_distance = lscan.ranges[i]
                closest_lmark_angle = lscan.angles[i]
        if (closest_lmark_distance == float('inf') or  # No landmarks
                closest_lmark_distance < self.circle_radius):
            inside = True

        # We use a state machine to provide some hysterisis.  If we transition
        # from inside to outside, we go into the HOMING state for a minimum
        # period.  However, if we go from
        if self.state == "PUSHING":
            if not inside:
                self.state = "HOMING"
                self.homing_countdown = self.homing_timeout
        else:  # In "HOMING"
            self.homing_countdown -= 1
            if self.homing_countdown == 0:
                self.state = "PUSHING"

        if self.state == "PUSHING":
            # Push out pucks by moving towards the weighted centroid of all
            # visible pucks.  Nearby pucks get more weight and will be targeted.
            cx = 0
            cy = 0
            pucks_in_view = False
            n = len(rscan.ranges)
            for i in range(n):
                if rscan.masks[i] & self.acceptable_puck_mask != 0:
                    angle = self.index_to_angle(rscan, i)
                    if angle >= pi / 2 or angle < -pi / 2:
                        continue
                    value = 1.0 / (1.0 + rscan.ranges[i])
                    #value = 1.0/rscan.ranges[i]
                    #value = 1.0
                    cx = cx + value * cos(angle)
                    cy = cy + value * sin(angle)
                    pucks_in_view = True
            cx /= n
            cy /= n

            if pucks_in_view:
                twist.linear = self.linear_speed
                twist.angular = 1000.0 * cy
            else:
                # We'll move randomly if no pucks are in view.
                twist.linear = self.linear_speed
                twist.angular = 5 * (random() - 0.5)

            self.draw_line(this_robot, lscan, 0, (0, 255, 0))
        else:

            # Home towards the landmark.

            if (closest_lmark_angle <= 0):
                # Turn right
                twist.linear = self.linear_speed
                twist.angular = -self.angular_speed

                if visualize:
                    if closest_lmark_angle != None:
                        self.draw_line(this_robot, rscan, closest_lmark_angle,
                                       (0, 255, 0))
            else:
                # Turn left
                twist.linear = self.linear_speed
                twist.angular = self.angular_speed

                if visualize:
                    self.draw_line(this_robot, rscan, closest_lmark_angle,
                                   (255, 0, 255))

        self.last_inside = inside

        return twist
Example #11
0
    def react(self, robot, sensor_suite, visualize=False):

        range_scan = sensor_suite.range_scan
        #puck_scan = sensor_suite.puck_scan

        # We seem to have to create a new simulator object each time because
        # otherwise it would contain the obstacles from the last time step.
        # If there was a 'removeObstacle' method it would be a bit nicer.
        sim = rvo2.PyRVOSimulator(
            1 / 60.,  # Time step
            1.5,  # neighborDist
            5,  # maxNeighbors
            1.5,  # timeHorizon (other agents)
            1.5,  #2     # timeHorizon (obstacles)
            robot.radius,  # agent radius
            MAX_LINEAR_SPEED)  # agent max speed
        agent = sim.addAgent((0, 0))

        # Add range scan points as obstacles for the RVO simulator
        n = len(range_scan.ranges)
        points = []
        for i in range(0, n):
            rho = range_scan.INNER_RADIUS + range_scan.ranges[i]
            #if not (rho == float('inf') or isnan(rho)):
            theta = range_scan.angles[i]
            points.append((rho * cos(theta), rho * sin(theta)))

        # Add pucks from the puck scan
        #for puck in puck_scan.pucks:
        #    rho = puck.distance
        #    theta = puck.angle
        #    points.append((rho*cos(theta), rho*sin(theta)))

        # Add fake points behind the robot to make it think twice about going
        # backwards.
        #n_fake = 0
        #start_angle = range_scan.ANGLE_MAX
        #stop_angle = range_scan.ANGLE_MIN + 2*pi
        #angle_delta = (stop_angle - start_angle) / (n_fake - 1)
        #for i in range(n_fake):
        #    theta = start_angle + i * angle_delta
        #    rho = 2 * robot.radius
        #    points.append((rho*cos(theta), rho*sin(theta)))
        #    if visualize:
        #        vx,vy = rho*cos(theta), rho*sin(theta)
        #        self.draw_line_from_robot(robot, vx, vy, 0, 0, 255, 1)

        # The scan points will be treated together as a single "negative"
        # obstacle, with vertices specified in CW order.  This requires the
        # following sort.
        points.sort(key=lambda p: -atan2(p[1], p[0]))
        sim.addObstacle(points)
        sim.processObstacles()

        # Get the velocity in the robot reference frame with the clockwise
        # rotation matrix
        cos_theta = cos(robot.body.angle)
        sin_theta = sin(robot.body.angle)
        cur_vx = robot.body.velocity.x * cos_theta + \
                 robot.body.velocity.y * sin_theta
        cur_vy = -robot.body.velocity.x * sin_theta + \
                  robot.body.velocity.y * cos_theta

        # To prevent oscillation we will generally just test the preferred
        # velocities in the immediate neighbourhood (within the pref_vels list)
        # of the preferred velocity chosen last time.
        if self.last_mag < 20:
            # Last time the magnitude of the chosen velocity was very low.
            # Do a full search over the preferred velocities.
            start_index = 0
            stop_index = self.NUMBER_PREF_VELS - 1
        elif self.last_index == 0:
            start_index = 0
            stop_index = 1
        elif self.last_index == len(self.pref_vels) - 1:
            start_index = self.NUMBER_PREF_VELS - 2
            stop_index = self.NUMBER_PREF_VELS - 1
        else:
            # This is the general case.
            start_index = self.last_index - 1
            stop_index = self.last_index + 1

        highest_mag = 0
        chosen_vel = None
        chosen_index = None
        for i in range(start_index, stop_index + 1):
            pref_vel = self.pref_vels[i]

            # Initializing from scratch each time
            sim.setAgentPosition(agent, (0, 0))
            sim.setAgentVelocity(agent, (cur_vx, cur_vy))
            sim.setAgentPrefVelocity(agent, pref_vel)

            for j in range(self.SIM_STEPS):
                sim.doStep()

            (vx, vy) = sim.getAgentVelocity(0)
            #print "vel: {}, {}".format(vx, vy)
            if visualize:
                self.draw_line_from_robot(robot, vx, vy, 255, 255, 255, 3)

            mag = sqrt(vx * vx + vy * vy)
            if mag > highest_mag:
                highest_mag = mag
                chosen_vel = (vx, vy)
                chosen_index = i

        self.last_index = chosen_index
        self.last_mag = highest_mag
        #print "highest_mag: {}".format(highest_mag)

        #chosen_vel = (avg_vx / len(self.pref_vels),
        #              avg_vy / len(self.pref_vels))

        if visualize and chosen_vel != None:
            self.draw_line_from_robot(robot, chosen_vel[0], chosen_vel[1], 255,
                                      0, 127, 5)

        #print "MAX_LINEAR_SPEED: {}".format(MAX_LINEAR_SPEED)
        #print "current_vel: {}, {}".format(cur_vx, cur_vy)
        #print "MAG OF current_vel: {}".format(sqrt(cur_vx**2+ cur_vy**2))
        #print "chosen_vel: {}, {}".format(chosen_vel[0], chosen_vel[1])
        #print "MAG OF chosen_vel: {}".format(sqrt(chosen_vel[0]**2+ chosen_vel[1]**2))

        # Now treat (vx, vy) as the goal and apply the simple control law
        twist = Twist()
        if chosen_vel != None:
            twist.linear = 0.1 * chosen_vel[0]
            twist.angular = 0.02 * chosen_vel[1]
        else:
            print "NO AVAILABLE VELOCITY!"
            #for r in range_scan.ranges:
            #    print r
        return twist
Example #12
0
    def react(self, this_robot, sensor_suite, visualize=False):
        twist = Twist()

        scan = sensor_suite.range_scan

        # By default we will attend to the centre of the scan
        n = len(scan.ranges)
        centre_index = n / 2

        # ...but we will shift attention based on the compass
        # John: Uncomment to play with compass-modulated shifting.
        """
        compass_angle = normalize_angle_pm_pi(this_robot.body.angle)
        sign_dir = 1
        if self.current_puck_type != None and (self.current_puck_type & RED_PUCK_MASK) != 0:
            sign_dir = -1
        if compass_angle < 0:
            centre_index = sign_dir * 2
        else:
            centre_index = -sign_dir * 2
        """

        puck_ahead = (scan.masks[centre_index]
                      & self.acceptable_puck_mask) != 0
        puck_mask = scan.masks[centre_index]

        # Set current_puck_type if uninitialized.
        if self.current_puck_type == None and puck_ahead:
            self.current_puck_type = puck_mask

        # With a small random probability, change current_puck_type to match
        # the puck ahead.
        # John: Uncomment to play with sorting
        """
        if puck_ahead and random() < 0.005:
            self.current_puck_type = puck_mask
        """

        # Set the two predicates 'react_to_puck' and 'react_to_robot'.  Only
        # one should be true.
        react_to_puck = puck_ahead and puck_mask == self.current_puck_type

        react_to_robot = scan.masks[centre_index] == ROBOT_MASK
        assert not (react_to_puck and react_to_robot)

        # Now react...
        if react_to_puck:
            # Turn right
            twist.linear = 4
            twist.angular = 2.0
        elif react_to_robot:
            # Turn left and slow
            twist.linear = 0.5
            twist.angular = -2.0
        else:
            # Turn left
            twist.linear = 4
            twist.angular = -2.0

        if visualize:
            """
            if self.current_puck_type == RED_PUCK_MASK:
                self.draw_circle(this_robot, 255, 0, 0, 1)
            elif self.current_puck_type == GREEN_PUCK_MASK:
                self.draw_circle(this_robot, 0, 255, 0, 1)
            elif self.current_puck_type == BLUE_PUCK_MASK:
                self.draw_circle(this_robot, 0, 0, 255, 1)
            else:
                self.draw_circle(this_robot, 0, 255, 255, 255)
            """
            if react_to_puck:
                self.draw_circle(this_robot, 255, 0, 0, 1)
            elif react_to_robot:
                self.draw_circle(this_robot, 0, 0, 255, 1)
            else:
                self.draw_circle(this_robot, 0, 255, 0, 1)

        return twist
Example #13
0
    def react(self, this_robot, sensor_suite, visualize=False):
        twist = Twist()

        rscan = sensor_suite.range_scan
        lscan = sensor_suite.landmark_scan

        span_angles = self.get_landmark_span_angles(lscan)
        sector_widths = self.get_sector_widths(span_angles)

        assert len(span_angles) == len(sector_widths)

        # If any sector width is greater than the threshold then we will turn
        # away from that sector.  Otherwise, we will continue forwards.  If
        # there is more than one such "bad sector" then we choose the one with
        # the smallest width.
        n = len(sector_widths)
        index_of_bad_sector = None
        smallest_bad_width = float('inf')
        for i in range(0, n):
            if (sector_widths[i] > self.threshold
                    and sector_widths[i] < smallest_bad_width):
                index_of_bad_sector = i
                smallest_bad_width = sector_widths[i]

        #print index_of_bad_sector
        if index_of_bad_sector != None:
            lmark_a_angle = self.careful_average_angles(
                span_angles[(index_of_bad_sector + 1) % n])
            lmark_b_angle = self.careful_average_angles(
                span_angles[index_of_bad_sector])
            #print "LANDMARK ANGLES (in degrees)"
            #print "A (yellow): " + str(degrees(lmark_a_angle))
            #print "B (white): " + str(degrees(lmark_b_angle))

            # Choose direction to react based on the average of the
            # corresponding landmark angles.
            react_angle = (lmark_a_angle + get_smallest_angular_difference(
                lmark_b_angle, lmark_a_angle) / 2.0)

            twist.linear = 10.0
            twist.angular = 5 * sign(normalize_angle_pm_pi(react_angle))

            self.draw_line(this_robot, lscan, lmark_a_angle, (255, 255, 0))
            self.draw_line(this_robot, lscan, lmark_b_angle, (255, 255, 255))
            self.draw_line(this_robot, lscan, react_angle, (255, 0, 0))
        else:
            # Compute centroid of all pucks in the robot's ref. frame
            cx = 0
            cy = 0
            n = len(rscan.ranges)
            for i in range(n):
                if rscan.masks[i] & self.acceptable_puck_mask != 0:
                    angle = self.index_to_angle(rscan, i)
                    if angle >= pi / 2 or angle < -pi / 2:
                        continue
                    #value = 1.0/rscan.ranges[i]
                    #value = 1.0/rscan.ranges[i]
                    value = 1.0
                    cx = cx + value * cos(angle)
                    cy = cy + value * sin(angle)
            cx /= n
            cy /= n

            twist.linear = 10.0
            twist.angular = 100.0 * cy

            self.draw_line(this_robot, lscan, 0, (0, 255, 0))

        return twist
Example #14
0
    def react(self, this_robot, sensor_suite, visualize=False):
        twist = Twist()

        rscan = sensor_suite.range_scan
        lscan = sensor_suite.landmark_scan

        span_angles = self.get_landmark_span_angles(lscan)
        sector_widths = self.get_sector_widths(span_angles)

        assert len(span_angles) == len(sector_widths)

        # If any sector width is greater than the threshold then we will turn
        # away from that sector.  Otherwise, we will continue forwards.  If
        # there is more than one such "bad sector" then we choose the one with
        # the smallest width.
        n = len(sector_widths)
        index_of_bad_sector = None
        smallest_bad_width = float('inf')
        for i in range(0, n):
            if (sector_widths[i] > self.threshold
               and sector_widths[i] < smallest_bad_width):
                index_of_bad_sector = i
                smallest_bad_width = sector_widths[i]

        #print index_of_bad_sector
        if index_of_bad_sector != None:
            lmark_a_angle = self.careful_average_angles(span_angles[(index_of_bad_sector + 1) % n])
            lmark_b_angle = self.careful_average_angles(span_angles[index_of_bad_sector])
            #print "LANDMARK ANGLES (in degrees)"
            #print "A (yellow): " + str(degrees(lmark_a_angle))
            #print "B (white): " + str(degrees(lmark_b_angle))

            # Choose direction to react based on the average of the
            # corresponding landmark angles.
            react_angle = (lmark_a_angle +
                get_smallest_angular_difference(lmark_b_angle,
                                                lmark_a_angle) / 2.0)
            
            twist.linear = 10.0
            twist.angular = 5 * sign(normalize_angle_pm_pi(react_angle))

            self.draw_line(this_robot, lscan, lmark_a_angle, (255, 255, 0))
            self.draw_line(this_robot, lscan, lmark_b_angle, (255, 255, 255))
            self.draw_line(this_robot, lscan, react_angle, (255, 0, 0))
        else:
            # Compute centroid of all pucks in the robot's ref. frame
            cx = 0
            cy = 0
            n = len(rscan.ranges)
            for i in range(n):
                if rscan.masks[i] & self.acceptable_puck_mask != 0:
                    angle = self.index_to_angle(rscan, i)
                    if angle >= pi/2 or angle < -pi/2:
                        continue
                    #value = 1.0/rscan.ranges[i]
                    #value = 1.0/rscan.ranges[i]
                    value = 1.0
                    cx = cx + value * cos(angle)
                    cy = cy + value * sin(angle)
            cx /= n
            cy /= n

            twist.linear = 10.0
            twist.angular = 100.0 * cy


            self.draw_line(this_robot, lscan, 0, (0, 255, 0))

        return twist
Example #15
0
    def react(self, this_robot, sensor_suite, visualize=False):
        twist = Twist()

        rscan = sensor_suite.range_scan
        n = len(rscan.ranges)

        target = self.get_leftmost_pixel(rscan)

        # Convert to an angle
        if target == None:
            target_angle = None
        else:
            target_angle = self.index_to_angle(rscan, target)

        # EXPERIMENT TO ACHIEVE A MINIMUM SIZE AGGREGATE.
        lscan = sensor_suite.landmark_scan
        closest_lmark_distance = float('inf')
        for i in range(len(lscan.ranges)):
            if (lscan.masks[i] & ANY_LANDMARK_MASK != 0
                    and lscan.ranges[i] < closest_lmark_distance):
                closest_lmark_distance = lscan.ranges[i]
        if closest_lmark_distance < self.circle_radius:
            target_angle = target_angle + self.egress_angle

        if self.modulate and target_angle != None:
            compass_angle = normalize_angle_pm_pi(this_robot.body.angle)
            if cos(2 * compass_angle) < 0:
                # Dig in to push the puck more
                target_angle = target_angle - self.ingress_angle
            else:
                # Pull out to skirt the puck
                target_angle = target_angle + self.egress_angle

        # Check for the presence of another robot in the centre of the image.
        react_to_robot = False
        react_to_robot_angle = None
        for i in range(0, n):
            if (rscan.masks[i] == ROBOT_MASK and fabs(rscan.angles[i]) < pi / 4
                    and rscan.ranges[i] < 2 * this_robot.radius):
                react_to_robot = True
                react_to_robot_angle = (rscan.ANGLE_MIN + i *
                                        (rscan.ANGLE_MAX - rscan.ANGLE_MIN) /
                                        float(rscan.NUMBER_POINTS))

        if react_to_robot:
            # Turn left and slow
            twist.linear = self.slow_factor * self.linear_speed
            twist.angular = self.angular_speed

            if visualize:  # Reacting to robot
                self.draw_line(this_robot, rscan, react_to_robot_angle,
                               (255, 0, 0))

        elif (target_angle == None or target_angle <= 0):
            # Turn right
            twist.linear = self.linear_speed
            twist.angular = -self.angular_speed

            if visualize:
                if target_angle != None:
                    self.draw_line(this_robot, rscan, target_angle,
                                   (0, 255, 0))
        else:
            # Turn left
            twist.linear = self.linear_speed
            twist.angular = self.angular_speed

            if visualize:
                self.draw_line(this_robot, rscan, target_angle, (255, 0, 255))

        self.summed_angular_speed += twist.angular

        #print self.summed_angular_speed

        return twist
Example #16
0
    def react(self, this_robot, sensor_suite, visualize=False):
        twist = Twist()

        scan = sensor_suite.range_scan

        # By default we will attend to the centre of the scan
        n = len(scan.ranges)
        centre_index = n/2

        # ...but we will shift attention based on the compass
        # John: Uncomment to play with compass-modulated shifting.
        """
        compass_angle = normalize_angle_pm_pi(this_robot.body.angle)
        sign_dir = 1
        if self.current_puck_type != None and (self.current_puck_type & RED_PUCK_MASK) != 0:
            sign_dir = -1
        if compass_angle < 0:
            centre_index = sign_dir * 2
        else:
            centre_index = -sign_dir * 2
        """

        puck_ahead = (scan.masks[centre_index] & self.acceptable_puck_mask) != 0
        puck_mask = scan.masks[centre_index]

        # Set current_puck_type if uninitialized.
        if self.current_puck_type == None and puck_ahead:
            self.current_puck_type = puck_mask

        # With a small random probability, change current_puck_type to match
        # the puck ahead.
        # John: Uncomment to play with sorting
        """
        if puck_ahead and random() < 0.005:
            self.current_puck_type = puck_mask
        """

        # Set the two predicates 'react_to_puck' and 'react_to_robot'.  Only
        # one should be true.
        react_to_puck = puck_ahead and puck_mask == self.current_puck_type

        react_to_robot = scan.masks[centre_index] == ROBOT_MASK
        assert not (react_to_puck and react_to_robot)

        # Now react...
        if react_to_puck:
            # Turn right
            twist.linear = 4
            twist.angular =  2.0
        elif react_to_robot:
            # Turn left and slow
            twist.linear = 0.5 
            twist.angular = -2.0
        else:
            # Turn left
            twist.linear = 4
            twist.angular = -2.0

        if visualize:
            """
            if self.current_puck_type == RED_PUCK_MASK:
                self.draw_circle(this_robot, 255, 0, 0, 1)
            elif self.current_puck_type == GREEN_PUCK_MASK:
                self.draw_circle(this_robot, 0, 255, 0, 1)
            elif self.current_puck_type == BLUE_PUCK_MASK:
                self.draw_circle(this_robot, 0, 0, 255, 1)
            else:
                self.draw_circle(this_robot, 0, 255, 255, 255)
            """
            if react_to_puck:
                self.draw_circle(this_robot, 255, 0, 0, 1)
            elif react_to_robot:
                self.draw_circle(this_robot, 0, 0, 255, 1)
            else:
                self.draw_circle(this_robot, 0, 255, 0, 1)

        return twist
Example #17
0
    def react(self, this_robot, sensor_suite, visualize=False):
        twist = Twist()

        rscan = sensor_suite.range_scan
        n = len(rscan.ranges)

        target = self.get_target(rscan)

        # Convert to an angle
        if target == None:
            target_angle = None
        else:
            target_angle = (rscan.ANGLE_MIN + target *
                            (rscan.ANGLE_MAX - rscan.ANGLE_MIN) /
                            float(rscan.NUMBER_POINTS))

        if self.modulate and target_angle != None:
            compass_angle = normalize_angle_pm_pi(this_robot.body.angle)
            if cos(2 * compass_angle) < 0:
                # Dig in to push the puck more
                target_angle = target_angle - self.ingress_angle
            else:
                # Pull out to skirt the puck
                target_angle = target_angle + self.egress_angle

        # Check for the presence of another robot in the centre of the image.
        react_to_robot = False
        react_to_robot_angle = None
        for i in range(0, n):
            if (rscan.masks[i] == ROBOT_MASK and fabs(rscan.angles[i]) < pi / 4
                    and rscan.ranges[i] < 2 * this_robot.radius):
                react_to_robot = True
                react_to_robot_angle = (rscan.ANGLE_MIN + i *
                                        (rscan.ANGLE_MAX - rscan.ANGLE_MIN) /
                                        float(rscan.NUMBER_POINTS))

        if react_to_robot:
            # Turn left and slow
            twist.linear = self.slow_factor * self.linear_speed
            twist.angular = self.angular_speed

            if visualize:  # Reacting to robot
                self.draw_line(this_robot, rscan, react_to_robot_angle,
                               (255, 0, 0))

        elif (target_angle == None or target_angle <= 0):
            # Turn right
            twist.linear = self.linear_speed
            twist.angular = -self.angular_speed

            if visualize:
                if target_angle != None:
                    self.draw_line(this_robot, rscan, target_angle,
                                   (0, 255, 0))
        else:
            # Turn left
            twist.linear = self.linear_speed
            twist.angular = self.angular_speed

            if visualize:
                self.draw_line(this_robot, rscan, target_angle, (255, 0, 255))

        return twist
Example #18
0
 def stop(self):
     """Stop robot motion."""
     self.set_command(Twist())
Example #19
0
    def react(self, this_robot, sensor_suite, visualize=False):
        twist = Twist()

        rscan = sensor_suite.range_scan

        # Based on the closest landmark, determine whether we are inside or
        # outside the circle
        inside = False
        lscan = sensor_suite.landmark_scan
        closest_lmark_distance = float('inf')
        closest_lmark_angle = None
        for i in range(len(lscan.ranges)):
            if (lscan.masks[i] & ANY_LANDMARK_MASK != 0
               and lscan.ranges[i] < closest_lmark_distance):
                closest_lmark_distance = lscan.ranges[i]
                closest_lmark_angle = lscan.angles[i]
        if (closest_lmark_distance == float('inf') or  # No landmarks
           closest_lmark_distance < self.circle_radius):
            inside = True

        # We use a state machine to provide some hysterisis.  If we transition
        # from inside to outside, we go into the HOMING state for a minimum
        # period.  However, if we go from 
        if self.state == "PUSHING":
            if not inside:
                self.state = "HOMING"
                self.homing_countdown = self.homing_timeout
        else: # In "HOMING"
            self.homing_countdown -= 1
            if self.homing_countdown == 0:
                self.state = "PUSHING"

        if self.state == "PUSHING":
            # Push out pucks by moving towards the weighted centroid of all
            # visible pucks.  Nearby pucks get more weight and will be targeted.
            cx = 0
            cy = 0
            pucks_in_view = False
            n = len(rscan.ranges)
            for i in range(n):
                if rscan.masks[i] & self.acceptable_puck_mask != 0:
                    angle = self.index_to_angle(rscan, i)
                    if angle >= pi/2 or angle < -pi/2:
                        continue
                    value = 1.0/(1.0 + rscan.ranges[i])
                    #value = 1.0/rscan.ranges[i]
                    #value = 1.0
                    cx = cx + value * cos(angle)
                    cy = cy + value * sin(angle)
                    pucks_in_view = True
            cx /= n
            cy /= n

            if pucks_in_view:
                twist.linear = self.linear_speed
                twist.angular = 1000.0 * cy
            else:
                # We'll move randomly if no pucks are in view.
                twist.linear = self.linear_speed
                twist.angular = 5 * (random() - 0.5)

            self.draw_line(this_robot, lscan, 0, (0, 255, 0))
        else:

            # Home towards the landmark.

            if (closest_lmark_angle <= 0):
                # Turn right
                twist.linear = self.linear_speed
                twist.angular = - self.angular_speed

                if visualize:
                    if closest_lmark_angle != None:
                        self.draw_line(this_robot, rscan, closest_lmark_angle, (0, 255, 0))
            else:
                # Turn left
                twist.linear = self.linear_speed
                twist.angular = self.angular_speed

                if visualize:
                    self.draw_line(this_robot, rscan, closest_lmark_angle, (255, 0, 255))

        self.last_inside = inside

        return twist
Example #20
0
    def react(self, robot, sensor_suite, visualize=False):

        range_scan = sensor_suite.range_scan
        #puck_scan = sensor_suite.puck_scan

        # We seem to have to create a new simulator object each time because
        # otherwise it would contain the obstacles from the last time step.
        # If there was a 'removeObstacle' method it would be a bit nicer.
        sim = rvo2.PyRVOSimulator(1/60., # Time step
                                  1.5,   # neighborDist
                                  5,     # maxNeighbors
                                  1.5,   # timeHorizon (other agents)
                                  1.5,   #2     # timeHorizon (obstacles)
                                  robot.radius,   # agent radius
                                  MAX_LINEAR_SPEED)     # agent max speed
        agent = sim.addAgent((0, 0))

        # Add range scan points as obstacles for the RVO simulator
        n = len(range_scan.ranges)
        points = []
        for i in range(0, n):
            rho = range_scan.INNER_RADIUS + range_scan.ranges[i]
            #if not (rho == float('inf') or isnan(rho)):
            theta = range_scan.angles[i]
            points.append((rho*cos(theta), rho*sin(theta)))

        # Add pucks from the puck scan
        #for puck in puck_scan.pucks:
        #    rho = puck.distance
        #    theta = puck.angle
        #    points.append((rho*cos(theta), rho*sin(theta)))

        # Add fake points behind the robot to make it think twice about going
        # backwards.
        #n_fake = 0
        #start_angle = range_scan.ANGLE_MAX
        #stop_angle = range_scan.ANGLE_MIN + 2*pi
        #angle_delta = (stop_angle - start_angle) / (n_fake - 1)
        #for i in range(n_fake):
        #    theta = start_angle + i * angle_delta
        #    rho = 2 * robot.radius
        #    points.append((rho*cos(theta), rho*sin(theta)))
        #    if visualize:
        #        vx,vy = rho*cos(theta), rho*sin(theta)
        #        self.draw_line_from_robot(robot, vx, vy, 0, 0, 255, 1)

        # The scan points will be treated together as a single "negative"
        # obstacle, with vertices specified in CW order.  This requires the
        # following sort.
        points.sort(key = lambda p: -atan2(p[1], p[0]))
        sim.addObstacle(points)
        sim.processObstacles()

        # Get the velocity in the robot reference frame with the clockwise
        # rotation matrix
        cos_theta = cos(robot.body.angle)
        sin_theta = sin(robot.body.angle)
        cur_vx = robot.body.velocity.x * cos_theta + \
                 robot.body.velocity.y * sin_theta
        cur_vy = -robot.body.velocity.x * sin_theta + \
                  robot.body.velocity.y * cos_theta


        # To prevent oscillation we will generally just test the preferred
        # velocities in the immediate neighbourhood (within the pref_vels list)
        # of the preferred velocity chosen last time.
        if self.last_mag < 20:
            # Last time the magnitude of the chosen velocity was very low.
            # Do a full search over the preferred velocities.
            start_index = 0
            stop_index = self.NUMBER_PREF_VELS - 1
        elif self.last_index == 0:
            start_index = 0
            stop_index = 1
        elif self.last_index == len(self.pref_vels)-1:
            start_index = self.NUMBER_PREF_VELS - 2
            stop_index = self.NUMBER_PREF_VELS - 1
        else:
            # This is the general case.
            start_index = self.last_index - 1
            stop_index = self.last_index + 1

        highest_mag = 0
        chosen_vel = None
        chosen_index = None
        for i in range(start_index, stop_index+1):
            pref_vel = self.pref_vels[i]

            # Initializing from scratch each time
            sim.setAgentPosition(agent, (0, 0))
            sim.setAgentVelocity(agent, (cur_vx, cur_vy))
            sim.setAgentPrefVelocity(agent, pref_vel)
            
            for j in range(self.SIM_STEPS):
                sim.doStep()

            (vx, vy) = sim.getAgentVelocity(0)
            #print "vel: {}, {}".format(vx, vy)
            if visualize:
                self.draw_line_from_robot(robot, vx, vy, 255, 255, 255, 3)

            mag = sqrt(vx*vx + vy*vy)
            if mag > highest_mag:
                highest_mag = mag
                chosen_vel = (vx, vy)
                chosen_index = i

        self.last_index = chosen_index
        self.last_mag = highest_mag
        #print "highest_mag: {}".format(highest_mag)

        #chosen_vel = (avg_vx / len(self.pref_vels),
        #              avg_vy / len(self.pref_vels))

        if visualize and chosen_vel != None:
            self.draw_line_from_robot(robot, chosen_vel[0], chosen_vel[1], 255, 0, 127, 5)

        #print "MAX_LINEAR_SPEED: {}".format(MAX_LINEAR_SPEED)
        #print "current_vel: {}, {}".format(cur_vx, cur_vy)
        #print "MAG OF current_vel: {}".format(sqrt(cur_vx**2+ cur_vy**2))
        #print "chosen_vel: {}, {}".format(chosen_vel[0], chosen_vel[1])
        #print "MAG OF chosen_vel: {}".format(sqrt(chosen_vel[0]**2+ chosen_vel[1]**2))

        # Now treat (vx, vy) as the goal and apply the simple control law
        twist = Twist()
        if chosen_vel != None:
            twist.linear = 0.1 * chosen_vel[0]
            twist.angular = 0.02 * chosen_vel[1]
        else:
            print "NO AVAILABLE VELOCITY!"
            #for r in range_scan.ranges:
            #    print r
        return twist