コード例 #1
0
 def test_load_robot_config(self):
     with patch('ev3dev2simulator.state.RobotState.get_robot_config'
                ) as get_robot_config_mock:
         get_robot_config_mock.return_value = {
             'parts': [{
                 'name': 'brick-left',
                 'type': 'brick',
                 'brick': '0',
                 'x_offset': '-39',
                 'y_offset': '-22.5'
             }]
         }
         state = RobotState(self.default_config())
         self.assertEqual(
             len(state.parts), 4 + 1 + 2 +
             1)  # 4 sensors/actuators + 1 brick + 2 leds + 1 speaker
         config = {
             'center_x': 0,
             'center_y': 0,
             'orientation': 180,
             'name': 'test_bot',
             'type': 'test_robot'
         }
         state = RobotState(config)
         self.assertEqual(4, len(state.parts))  # only a brick
コード例 #2
0
    def test_process_data_request(self):
        robot_state = RobotState()
        robot_state.values['right_brick:ev3-ports:in4'] = 10
        robot_state.locks['right_brick:ev3-ports:in4'] = threading.Lock()

        message_processor = MessageProcessor('right_brick', robot_state)
        value = message_processor.process_data_request(DataRequest('ev3-ports:in4'))

        self.assertEqual(value, 10)
コード例 #3
0
    def test_add_robot(self):
        conf = TestRobotState.default_config()
        state = RobotState(conf)

        sidebar = Sidebar(100, 150, 200, 300)
        sidebar_sprite_mock = MagicMock()
        sidebar.init_robot(state.name, state.sensors, state.get_bricks(),
                           [sidebar_sprite_mock])

        self.assertEqual(len(sidebar.robot_info), 1)
コード例 #4
0
    def test_setters_getters(self):
        state = RobotState(self.default_config())
        state.setup_pymunk_shapes(1)

        self.assertEqual(len(state.get_shapes()), 4 + 1 + 2 + 1)
        self.assertEqual(
            state.get_sensor((0, 'ev3-ports:in4')).get_ev3type(),
            'ultrasonic_sensor')
        self.assertEqual(state.get_bricks()[0].name, 'brick-left')
        self.assertEqual(len(state.get_sensors()), 1)
        self.assertEqual(state.get_anchor().name, 'brick-left')
        del state.bricks[0]
        self.assertEqual(state.get_anchor(), None)
コード例 #5
0
    def test_create_jobs_right(self):
        robot_state = RobotState()

        message_processor = MessageProcessor('left_brick', robot_state)
        message_processor.process_rotate_command(RotateCommand('ev3-ports:outD', 10, 100, 'hold'))

        for i in range(300):
            c, l, r = robot_state.next_motor_jobs()
            self.assertIsNone(c)
            self.assertIsNone(l)
            self.assertAlmostEqual(r, 0.104, 3)

        self.assertEqual((None, None, None), robot_state.next_motor_jobs())
コード例 #6
0
    def test_create_jobs_center(self):
        robot_state = RobotState()

        message_processor = MessageProcessor('left_brick', robot_state)
        message_processor.process_rotate_command(RotateCommand('ev3-ports:outB', 20, 100, 'hold'))

        for i in range(150):
            c, l, r = robot_state.next_motor_jobs()
            self.assertAlmostEqual(c, -0.667, 3)
            self.assertIsNone(l)
            self.assertIsNone(r)

        self.assertEqual((None, None, None), robot_state.next_motor_jobs())
コード例 #7
0
 def test_get_value_and_locks(self):
     conf = TestRobotState.default_config()
     state = RobotState(conf)
     state.setup_pymunk_shapes(1)
     for arm in state.side_bar_sprites:
         arm.rotate_x = 0  # this is set in setup visuals
         arm.rotate_y = 0  # this is set in setup visuals
     sim = RobotSimulator(state)
     sim._sync_physics_sprites = MagicMock()
     val = sim.get_value((0, 'ev3-ports:in4'))
     self.assertEqual(val, 2550)
     self.assertEqual(sim.locks[(0, 'ev3-ports:in4')].locked(), True)
     sim.update()
     self.assertEqual(sim.locks[(0, 'ev3-ports:in4')].locked(), False)
コード例 #8
0
    def test_process_data_request(self):
        d = {
            'type': 'DataRequest',
            'address': 'ev3-ports:in4',
        }

        robot_state = RobotState()
        robot_state.values['left_brick:ev3-ports:in4'] = 10
        robot_state.locks['left_brick:ev3-ports:in4'] = threading.Lock()

        server = ClientSocketHandler(robot_state, None, 'left_brick')
        data = server._process_data_request(d)
        val = self._deserialize(data)

        self.assertEqual(val, 10)
コード例 #9
0
    def test_process_sound_command(self):
        robot_state = RobotState()

        frames_per_second = get_config().get_data()['exec_settings']['frames_per_second']
        frames = int(round((32 / 2.5) * frames_per_second))

        message_processor = MessageProcessor('left_brick', robot_state)
        message_processor.process_sound_command(SoundCommand('A test is running at the moment!'))

        for i in range(frames - 1):
            self.assertIsNotNone(robot_state.next_sound_job())

        message = robot_state.next_sound_job()
        self.assertEqual(message, 'A test is \nrunning at\n the momen\nt!')
        self.assertIsNone(robot_state.next_sound_job())
コード例 #10
0
    def test_constructor_and_reset(self):
        conf = TestRobotState.default_config()
        state = RobotState(conf)
        state.setup_pymunk_shapes(1)
        for arm in state.side_bar_sprites:
            arm.rotate_x = 0  # this is set in setup visuals
            arm.rotate_y = 0  # this is set in setup visuals
        sim = RobotSimulator(state)
        sim._sync_physics_sprites = MagicMock()
        sim.update()

        sim._sync_physics_sprites.assert_called_once()
        sim.should_reset = True
        self.assertEqual(sim.should_reset, True)
        sim.reset()
        self.assertEqual(sim.should_reset, False)
        sim.release_locks()
コード例 #11
0
    def test_add_robot_info(self):
        conf = TestRobotState.default_config()
        state = RobotState(conf)

        sidebar = Sidebar(100, 150, 200, 300)
        sidebar_sprite_mock = MagicMock()
        state.values[(0, 'ev3-ports:in4')] = 5
        state.sounds[(0, 'speaker')] = 'test_sound'
        sidebar.init_robot(state.name, state.sensors, state.get_bricks(),
                           [sidebar_sprite_mock])

        sidebar.add_robot_info(state.name, state.values, state.sounds)
        self.assertEqual(
            sidebar.robot_info[state.name][(0, 'ev3-ports:in4')]['value'], 5)
        self.assertEqual(
            sidebar.robot_info[state.name][(0, 'speaker')]['value'],
            'test_sound')
コード例 #12
0
    def test_set_obstacles(self):
        config = self.default_config().copy()
        config['parts'].append({
            'name': 'color_test_sensor',
            'type': 'color_sensor',
            'x_offset': 0,
            'y_offset': 81,
            'brick': 0,
            'port': 'ev3-ports:in2'
        })

        config['parts'].append({
            'name': 'touch_test_sensor',
            'type': 'touch_sensor',
            'side': 'left',
            'x_offset': 0,
            'y_offset': -81,
            'brick': 0,
            'port': 'ev3-ports:in3'
        })
        state = RobotState(config)
        state.setup_pymunk_shapes(1)
        for arm in state.side_bar_sprites:
            arm.rotate_x = 0  # this is set in setup visuals

        color_obstacle_mock = MagicMock()
        rock_mock = MagicMock()
        lake_mock = MagicMock()

        state.set_color_obstacles([color_obstacle_mock])
        state.set_touch_obstacles([rock_mock])
        state.set_falling_obstacles([lake_mock])

        self.assertEqual(
            state.sensors[(0, 'ev3-ports:in3')].sensible_obstacles,
            [rock_mock])
        self.assertEqual(
            state.sensors[(0, 'ev3-ports:in2')].sensible_obstacles,
            [color_obstacle_mock])
        self.assertEqual(
            state.sensors[(0, 'ev3-ports:in4')].sensible_obstacles,
            [lake_mock])
        self.assertEqual(
            state.actuators[(0, 'ev3-ports:outA')].sensible_obstacles,
            [lake_mock])
コード例 #13
0
    def test_process_sound_command(self):
        d = {
            'type': 'SoundCommand',
            'message': 'A test is running at the moment!',
        }

        frames_per_second = get_config().get_data(
        )['exec_settings']['frames_per_second']
        frames = int(round((32 / 2.5) * frames_per_second))
        robot_state = RobotState()

        server = ClientSocketHandler(robot_state, None, 'left_brick')
        server._process_sound_command(d)

        for i in range(frames):
            self.assertIsNotNone(robot_state.next_sound_job())

        self.assertIsNone(robot_state.next_sound_job())
コード例 #14
0
    def test_create_jobs_coast_center(self):
        coasting_sub = get_config().get_data()['motor_settings']['degree_coasting_subtraction']
        robot_state = RobotState()

        message_processor = MessageProcessor('left_brick', robot_state)
        message_processor.process_rotate_command(RotateCommand('ev3-ports:outB', 80, 200, 'coast'))

        for i in range(75):
            c, l, r = robot_state.next_motor_jobs()
            self.assertAlmostEqual(c, -2.667, 3)
            self.assertIsNone(l)
            self.assertIsNone(r)

        ppf = 2.667 - coasting_sub
        for i in range(2):
            c, l, r = robot_state.next_motor_jobs()
            self.assertAlmostEqual(c, -ppf, 3)
            self.assertIsNone(l)
            self.assertIsNone(r)
            ppf = max(ppf - coasting_sub, 0)

        self.assertEqual((None, None, None), robot_state.next_motor_jobs())
コード例 #15
0
    def test_create_jobs_coast_left(self):
        coasting_sub = apply_scaling(get_config().get_data()['motor_settings']['pixel_coasting_subtraction'])
        robot_state = RobotState()

        message_processor = MessageProcessor('left_brick', robot_state)
        message_processor.process_rotate_command(RotateCommand('ev3-ports:outA', 80, 200, 'coast'))

        for i in range(75):
            c, l, r = robot_state.next_motor_jobs()
            self.assertIsNone(c)
            self.assertAlmostEqual(l, 0.833, 3)
            self.assertIsNone(r)

        ppf = 0.833 - coasting_sub
        for i in range(2):
            c, l, r = robot_state.next_motor_jobs()
            self.assertIsNone(c)
            self.assertAlmostEqual(l, ppf, 3)
            self.assertIsNone(r)
            ppf = max(ppf - coasting_sub, 0)

        self.assertEqual((None, None, None), robot_state.next_motor_jobs())
コード例 #16
0
    def test_determine_port(self):
        conf = TestRobotState.default_config()
        state = RobotState(conf)
        sim = RobotSimulator(state)

        # nothing given
        kwargs = {}
        port = sim.determine_port(0, kwargs, '')
        self.assertEqual(port, 'dev_not_connected')

        # no class given
        kwargs = {'address': 'ev3-ports:in4'}
        port = sim.determine_port(0, kwargs, '')
        self.assertEqual(port, 'dev_not_connected')

        # single class and address given
        kwargs = {'address': 'ev3-ports:in4', 'driver_name': 'lego-ev3-us'}
        port = sim.determine_port(0, kwargs, '')
        self.assertEqual(port, 'ev3-ports:in4')

        # single class and None address given
        kwargs = {'address': None, 'driver_name': 'lego-ev3-us'}
        port = sim.determine_port(0, kwargs, '')
        self.assertEqual(port, 'ev3-ports:in4')

        # multiple classes and address given
        kwargs = {
            'address': 'ev3-ports:outA',
            'driver_name': ['lego-ev3-l-motor', 'lego-nxt-motor']
        }
        port = sim.determine_port(0, kwargs, '')
        self.assertEqual(port, 'ev3-ports:outA')

        # single class and invalid address given
        kwargs = {'address': 'ev3-ports:in3', 'driver_name': 'lego-ev3-us'}
        port = sim.determine_port(0, kwargs, '')
        self.assertEqual(port, 'dev_not_connected')

        # multiple classes and invalid address given
        kwargs = {
            'address': 'ev3-ports:outC',
            'driver_name': ['lego-ev3-l-motor', 'lego-nxt-motor']
        }
        port = sim.determine_port(0, kwargs, '')
        self.assertEqual(port, 'dev_not_connected')

        # leds
        kwargs = {'address': None, 'driver_name': None}
        port = sim.determine_port(0, kwargs, 'leds')
        self.assertEqual(port, 'leds_addr')
コード例 #17
0
    def test_process_stop_command(self):
        d = {
            'type': 'StopCommand',
            'address': 'ev3-ports:outD',
            'speed': 100,
            'stop_action': 'coast'
        }

        robot_state = RobotState()
        server = ClientSocketHandler(robot_state, None, 'left_brick')

        data = server._process_stop_command(d)
        val = self._deserialize(data)

        self.assertAlmostEqual(0.0667, val, 3)
コード例 #18
0
    def test_reset(self):
        state = RobotState(self.default_config())
        state.setup_pymunk_shapes(1)
        for arm in state.side_bar_sprites:
            arm.rotate_x = 0  # this is set in setup visuals
            arm.rotate_y = 0  # this is set in setup visuals
        x = state.x * state.scale
        y = state.y * state.scale
        state.body.position = Vec2d(5, 5)  # 5 per sec
        state._move_position(Vec2d(5, 5))
        self.assertEqual(state.body.position, Vec2d(5, 5))
        self.assertEqual(state.body.velocity, Vec2d(5 * 30, 5 * 30))

        state.reset()

        self.assertEqual(state.body.position, Vec2d(x, y))
        self.assertEqual(state.body.velocity, Vec2d(0, 0))
コード例 #19
0
    def test_process_drive_command_pixels(self):
        d = {
            'type': 'RotateCommand',
            'address': 'ev3-ports:outB',
            'speed': 10,
            'distance': 100,
            'stop_action': 'hold'
        }

        robot_state = RobotState()
        server = ClientSocketHandler(robot_state, None, 'left_brick')

        data = server._process_drive_command(d)
        val = self._deserialize(data)

        self.assertEqual(10, val)
コード例 #20
0
 def test_execute_movement(self):
     state = RobotState(self.default_config())
     state.setup_pymunk_shapes(1)
     for arm in state.side_bar_sprites:
         arm.rotate_x = 0  # this is set in setup visuals
         arm.rotate_y = 0  # this is set in setup visuals
     state.execute_movement(5, 5)
     self.assertAlmostEqual(tuple(state.body.velocity)[0], 0.0,
                            3)  # no x movement
     self.assertAlmostEqual(tuple(state.body.velocity)[1], -5.0 * 30,
                            3)  # -150 y distance per second
     self.assertEqual(state.body.angle, pi)
コード例 #21
0
    def test_process_right_led_command(self):
        robot_state = RobotState()
        message_processor = MessageProcessor('right_brick', robot_state)

        command1 = LedCommand('led0:red:brick-status', 1)
        command2 = LedCommand('led0:green:brick-status', 1)

        message_processor.process_led_command(command1)
        message_processor.process_led_command(command2)

        self.assertEqual(robot_state.right_brick_left_led_color, 0)
        self.assertEqual(robot_state.right_brick_right_led_color, 1)

        command3 = LedCommand('led1:red:brick-status', 1)
        command4 = LedCommand('led1:green:brick-status', 0.5)

        message_processor.process_led_command(command3)
        message_processor.process_led_command(command4)

        self.assertEqual(robot_state.right_brick_left_led_color, 0)
        self.assertEqual(robot_state.right_brick_right_led_color, 4)
コード例 #22
0
    def test_setup_pymunk_shapes(self):
        state = RobotState(self.default_config())
        state.setup_pymunk_shapes(1)
        self.assertEqual(state.wheel_distance, 120)
        self.assertEqual(
            len(state.shapes), 4 + 1 + 2 +
            1)  # 4 sensors/actuators + 1 brick + 2 leds + 1 speaker
        self.assertEqual(state.body.angle, pi)

        config_with_one_wheel = self.default_config().copy()
        del config_with_one_wheel['parts'][1]
        config_with_one_wheel['parts'].append({
            'name':
            'invalid_sensor',
            'type':
            'type_that_does_not_exist',
        })
        state = RobotState(config_with_one_wheel)
        self.assertRaises(RuntimeError, state.setup_pymunk_shapes, 1)
コード例 #23
0
    def test_arm_movement(self):
        config = self.default_config().copy()
        config['parts'].append({
            'name': 'measurement-probe',
            'type': 'arm',
            'x_offset': 15,
            'y_offset': 102,
            'brick': 0,
            'port': 'ev3-ports:outB'
        })

        with patch('ev3dev2simulator.robotpart.Arm.ArmLarge') as ArmLargeMock:
            arm_instance = ArmLargeMock.return_value
            state = RobotState(self.default_config())
            state.setup_pymunk_shapes(1)

            state.execute_arm_movement((0, 'ev3-ports:outB'), 15)
            state.actuators[(0, 'ev3-ports:outB')].side_bar_arm.degrees = 15

            self.assertEqual(len(arm_instance.mock_calls),
                             3)  # first two have to do with a sprite list
            fn_name, args, kwargs = arm_instance.mock_calls[2]
            self.assertEqual(fn_name, 'rotate')
            self.assertEqual(args, (15, ))
コード例 #24
0
def main():
    """
    Spawns the user thread and creates and starts the simulation.
    """

    parser = argparse.ArgumentParser()
    parser.add_argument("-V",
                        "--version",
                        action='store_true',
                        help="Show version info")
    parser.add_argument("-s",
                        "--window_scaling",
                        default=0.65,
                        help="Scaling of the screen, default is 0.65",
                        required=False,
                        type=validate_scale)
    parser.add_argument(
        "-t",
        "--simulation_type",
        choices=['small', 'large'],
        default='small',
        help="Type of the simulation (small or large). Default is small",
        required=False,
        type=str)
    parser.add_argument(
        "-x",
        "--robot_position_x",
        default=200,
        help="Starting position x-coordinate of the robot, default is 200",
        required=False,
        type=validate_xy)
    parser.add_argument(
        "-y",
        "--robot_position_y",
        default=300,
        help="Starting position y-coordinate of the robot, default is 300",
        required=False,
        type=validate_xy)
    parser.add_argument("-o",
                        "--robot_orientation",
                        default=0,
                        help="Starting orientation the robot, default is 0",
                        required=False,
                        type=int)
    parser.add_argument(
        "-c",
        "--connection_order_first",
        choices=['left', 'right'],
        default='left',
        help=
        "Side of the first brick to connect to the simulator, default is 'left'",
        required=False,
        type=str)

    parser.add_argument(
        "-2",
        "--show-on-second-monitor",
        action='store_true',
        help=
        "Show simulator window on second monitor instead, default is first monitor"
    )
    parser.add_argument("-f",
                        "--fullscreen",
                        action='store_true',
                        help="Show simulator fullscreen")
    parser.add_argument("-m",
                        "--maximized",
                        action='store_true',
                        help="Show simulator maximized")

    args = vars(parser.parse_args())

    if args['version'] == True:
        from ev3dev2 import version as apiversion
        from ev3dev2simulator import version as simversion
        print("version ev3dev2           : " + apiversion.__version__)
        print("version ev3dev2simulator  : " + simversion.__version__)
        sys.exit(0)

    config = get_config()

    s = args['window_scaling']
    config.write_scale(s)

    t = args['simulation_type']
    config.write_sim_type(t)

    x = apply_scaling(args['robot_position_x'])
    y = apply_scaling(args['robot_position_y'])
    o = args['robot_orientation']

    c = args['connection_order_first']

    use_second_screen_to_show_simulator = args['show_on_second_monitor']
    show_fullscreen = args['fullscreen']
    show_maximized = args['maximized']

    robot_state = RobotState()
    robot_pos = (x, y, o)

    sim = Simulator(robot_state, robot_pos, show_fullscreen, show_maximized,
                    use_second_screen_to_show_simulator)
    #sim.setup()

    server_thread = ServerSocketDouble(
        robot_state, c) if t == 'large' else ServerSocketSingle(robot_state)
    server_thread.setDaemon(True)
    server_thread.start()

    arcade.run()