Beispiel #1
0
def initial_state(robot: Robot) -> State:
    return State(
        zone=robot.zone,
        heading_pid=PIDController(
            full_deflection_error=math.radians(120),
            prediction_time=0.3,
            fine_tune_time=2.0,
            time=lambda: robot.time(),
        ),
        captured=frozenset(),
        uncapturable=frozenset(),
        current_target=None,
        current_zone=None,
        zone_history=[],
        kalman=KalmanFilter(
            initial_position=(
                Location(x=-7, y=0)
                if robot.zone == 0
                else Location(x=7, y=0)
            ),
            initial_heading=(
                math.radians(90)
                if robot.zone == 0
                else math.radians(270)
            ),
        ),
        kalman_time=robot.time(),
        num_captures={
            x: 0
            for x in StationCode
        },
    )
Beispiel #2
0
    def perform(self, robot: Robot, state: State, view: View) -> None:
        heading_error = self.relative_bearing(state, view)
        heading_error = (math.pi + heading_error) % math.tau - math.pi
        print(f"  RB is {math.degrees(heading_error)}°", end='')
        # Add some pseudo heading error if the proximity sensors are going off
        left_distance = view.left_distance
        right_distance = view.right_distance

        # Detect towers
        if not NERF_MODE:
            for station in StationCode:
                station_position = STATION_CODE_LOCATIONS[station]
                distance = math.hypot(
                    station_position.x - state.kalman.location.x,
                    station_position.y - state.kalman.location.y,
                )
                distance = max(0, distance - TOWER_RADIUS)
                if distance > STEERING_THRESHOLD_METRES:
                    continue
                absolute_bearing = math.atan2(
                    station_position.x - state.kalman.location.x,
                    station_position.y - state.kalman.location.y,
                ) % math.tau
                relative_bearing = absolute_bearing - state.kalman.heading
                #print(f"Proximity to {station.value}, range is {distance:.03f}m, relative {math.degrees(relative_bearing):.0f}°")
                if 0 < relative_bearing < TOWER_ANGLE:
                    right_distance = min(right_distance, distance)
                elif -TOWER_ANGLE < relative_bearing <= 0:
                    left_distance = min(left_distance, distance)

        turn_back = False

        if view.left_distance < STEERING_THRESHOLD_METRES:
            heading_error += math.tan(TOWER_CLEARANCE_DISTANCE /
                                      view.left_distance)
            turn_back = True
        if view.right_distance < STEERING_THRESHOLD_METRES:
            heading_error -= math.tan(TOWER_CLEARANCE_DISTANCE /
                                      view.right_distance)
            turn_back = True
        if turn_back:
            print(f", steering {math.degrees(heading_error)}°", end='')
        if -IN_PLACE_THRESHOLD < heading_error < IN_PLACE_THRESHOLD:
            print("... moving ahead")
            deflection = state.heading_pid.step(heading_error)
            drive(robot, FORWARD_POWER,
                  FULL_DEFLECTION_TURN_RATE_PER_SECOND * deflection)
        elif heading_error > 0:
            print("... turning right")
            drive(robot, -0.2 if turn_back else 0.2,
                  IN_PLACE_TURN_RATE_PER_SECOND)
        elif heading_error < 0:
            print("... turning left")
            drive(robot, -0.2 if turn_back else 0.2,
                  -IN_PLACE_TURN_RATE_PER_SECOND)
        robot.sleep(1 / 100)
Beispiel #3
0
def run(robot: Robot) -> None:
    state = initial_state(robot)
    last_action = ''
    last_zone = None

    while True:
        view = get_world_view(robot)
        #print(view)
        update_state_from_view(robot, state, view)
        action = choose_action(robot, state, view)
        action_desc = str(action)
        if action_desc != last_action:
            print("Action: ", action_desc)
            last_action = action_desc
        if state.current_zone != last_zone:
            print("Zone: ", state.current_zone, state.kalman.location)
            last_zone = state.current_zone
        action.perform(robot, state, view)
        robot.sleep(0.01)
def setup():
    global R
    R = Robot.setup()
    R.init()
    set_time(R.usbkey)
    logger = setup_logger(R.usbkey)
    logger.info('Battery Voltage: %.2f' % R.power.battery.voltage)
    R.wait_start()
    try:
        io = IOInterface(R)
    except:
        logger.exception("IOInterface could not initialize")
        raise
    return logger, io, R.zone
Beispiel #5
0
def update_state_from_view(robot: Robot, state: State, view: View) -> None:
    # Update captured
    new_captured = set(state.captured)
    for target in view.targets:
        if target.target_info.owned_by == state.zone:
            new_captured.add(target.target_info.station_code)
        else:
            if not NERF_MODE:
                # In nerf mode we pretend we're unaware of zones taken away from us
                new_captured.discard(target.target_info.station_code)
    state.captured = new_captured

    # Zone updating
    zone_list = list(state.zone_history)
    zone_list.append(get_zone(state.kalman.location))

    if len(zone_list) > 4:
        zone_list = zone_list[-4:]
    state.zone_history = zone_list

    zones = collections.Counter(zone_list)
    zones.update([zone_list[-1]])

    (element, num_instances), = zones.most_common(1)
    if num_instances > 1:
        state.current_zone = element
    else:
        state.current_zone = None

    time = robot.time()
    state.kalman.tick(
        dt=time - state.kalman_time,
        left_power=robot.motors[0].m0.power,
        right_power=robot.motors[0].m1.power,
    )
    state.kalman.update_heading(view.compass)
    for target in view.targets:
        state.kalman.update_location(
            location=single_target_position(state.kalman.heading, target),
            stdev=0.08,
        )
    state.kalman_time = time

    print(f"Position is {state.kalman.location.x:.3f}, {state.kalman.location.y:.3f} ±{state.kalman.location_error:.3f}m")
    print(f"Heading is {math.degrees(state.kalman.heading):.0f}° ±{math.degrees(state.kalman.heading_error):.0f}°")
def setup():
    # A bad way to detect whether running in simulator
    if sys.platform.startswith('win'):
        ### SIMULATOR ONLY ###
        SRBot.zone, SRBot.sim = getInfo() # I made this to make simlator work
    srBot = SRBot.setup()
    srBot.init()
    set_time(srBot.usbkey)
    logger = setup_logger(srBot.usbkey)
    logger.info('Battery Voltage: %.2f' % (srBot.power.battery.voltage))
    srBot.wait_start()
    try:
        from main import Robot
        robot = Robot(srBot)
    except:
        logger.exception("Robot could not initialize")
        raise
    return robot, srBot.zone
Beispiel #7
0
def get_world_view(R: Robot) -> View:
    compass = R.compass.get_heading()
    targets = R.radio.sweep()
    left_distance = R.ruggeduinos[0].analogue_read(0)
    right_distance = R.ruggeduinos[0].analogue_read(1)
    proximity = (
        left_distance < 0.05 or  # Front left ultrasound
        right_distance < 0.05 or  # Front right ultrasound
        R.ruggeduinos[0].digital_read(2)  # Front bump switch
    )
    return View(
        compass=compass,
        targets=list(targets),
        proximity=proximity,
        left_distance=left_distance,
        right_distance=right_distance,
        dropped=R.time() > 60.0,
    )
def setup():
    # A bad way to detect whether running in simulator
    if sys.platform.startswith('win'):
        ### SIMULATOR ONLY ###
        SRBot.zone, SRBot.sim = getInfo()  # I made this to make simlator work
    srBot = SRBot.setup()
    srBot.init()
    set_time(srBot.usbkey)
    logger = setup_logger(srBot.usbkey)
    logger.info('Battery Voltage: %.2f' % (srBot.power.battery.voltage))
    srBot.wait_start()
    try:
        from main import Robot
        robot = Robot(srBot)
    except:
        logger.exception("Robot could not initialize")
        raise
    return robot, srBot.zone
Beispiel #9
0
    def perform(self, robot: Robot, state: State, view: View) -> None:
        drive(robot, 0)
        robot.radio.claim_territory()
        new_targets = robot.radio.sweep()
        successful = False
        for target in new_targets:
            if target.target_info.station_code == self.station:
                if target.target_info.owned_by == state.zone:
                    successful = True
                break
        if successful:
            # We claimed this one, mark all downstreams as now capturable
            new_uncapturable = set(state.uncapturable)
            new_uncapturable.discard(self.station)
            for successor, predecessors in PREDECESSORS[Claimant(
                    robot.zone)].items():
                if predecessors is None:
                    continue
                if self.station in predecessors:
                    new_uncapturable.discard(successor)
            new_cap_count = dict(state.num_captures)
            new_cap_count[self.station] += 1
            state.uncapturable = frozenset(new_uncapturable)
            state.num_captures = new_cap_count
        else:
            # We failed to claim this one, assume that all predecessors became unowned
            predecessors = PREDECESSORS[Claimant(robot.zone)][self.station]
            if predecessors is None:
                new_owned = state.captured
            else:
                new_owned = frozenset(state.captured - set(predecessors))
            state.uncapturable = state.uncapturable | {self.station}
            state.captured = new_owned
        drive(robot, -0.5)
        robot.sleep(0.2)

        if NERF_MODE:
            if random.random() < 0.5:
                drive(robot, 0, math.radians(90) / 3)
            else:
                drive(robot, 0, -math.radians(90) / 3)
            robot.sleep(3)
            drive(robot, 0)
            robot.sleep(1)
Beispiel #10
0
from sr.robot import Robot
import time

multiplier_left = 1
multiplier_right = 0.92

distance_mps = 1.0 / 6.4
angle_dps = 360.0 / 8.5

R = Robot()
def move(distance):
    multiplier = 1
    if distance < 0:
        multiplier = -1
    R.motors[0].m0.power = multiplier_left * 30 * multiplier
    R.motors[0].m1.power = multiplier_right * -30 * multiplier
    time.sleep(abs(distance / distance_mps))
    R.motors[0].m0.power = 0
    R.motors[0].m1.power = 0

def turn(degrees):
    multiplier = 1
    if degrees < 0:
        multiplier = -1
    R.motors[0].m0.power = multiplier_left * 30 * multiplier
    R.motors[0].m1.power = multiplier_right * 30 * multiplier
    time.sleep(abs(degrees / angle_dps))
    R.motors[0].m0.power = 0
    R.motors[0].m1.power = 0
Beispiel #11
0
def choose_action(robot: Robot, state: State, view: View) -> Action:
    if NERF_MODE:
        # Artificial stupidity
        robot.sleep(0.2)

    # Consider immediate claim targets, where we're already within the territory
    for target in view.targets:
        if 1.0 / target.signal_strength > 0.22:
            continue

        if target.target_info.owned_by == robot.zone:
            #print(f"> Considered {target.target_info.station_code} but we already own it")
            continue

        if not is_capturable(state.zone, target.target_info.station_code,
                             state.captured):
            print(
                f"> Considered {target.target_info.station_code} but we believe we're missing a predecessor"
            )
            continue

        if target.target_info.station_code in state.uncapturable:
            print(
                f"> Considered {target.target_info.station_code} but skipping due to previous difficulties"
            )
            continue

        return ClaimImmediate(target.target_info.station_code)

    # Back off if we're in proximity
    if view.proximity:
        if random.random() < 0.95:
            return BackOff()
        else:
            return MoveRandomly()

    if (state.current_target is not None
            and state.current_target not in state.captured
            and state.current_target not in state.uncapturable and
            is_capturable(state.zone, state.current_target, state.captured)):
        target = state.current_target
    else:
        target = choose_next_target(
            state.zone,
            state.captured,
            state.uncapturable,
            from_location=state.kalman.location,
            dropped=view.dropped,
            pseudo_distances={
                x: 0.7 * y
                for x, y in state.num_captures.items()
            },
        )
        state.current_target = target

    next_hop, route_direct = get_next_hop(get_zone(state.kalman.location),
                                          get_station_location(target),
                                          view.dropped)
    if route_direct:
        return GotoStation(target)
    else:
        print(f"Routing to {target} via {next_hop}")
        return GotoLocation(ZONE_CENTRES[next_hop])
Beispiel #12
0
from albot.main import run
from sr.robot import Robot

robot = Robot()
run(robot)

Beispiel #13
0
 def perform(self, robot: Robot, state: State, view: View) -> None:
     drive(robot, random.random() - 0.25, 0.25 * (random.random() - 0.5))
     robot.sleep(0.2 + random.random() * 1.3)
Beispiel #14
0
 def perform(self, robot: Robot, state: State, view: View) -> State:
     drive(robot, -0.6,
           IN_PLACE_TURN_RATE_PER_SECOND * (0.15 * random.random() + 0.4))
     robot.sleep(0.4)