Beispiel #1
0
 def _update_takeoff(self, command: Command, state: State) -> State:
     assert command.opcode == "takeoff"
     state = state.copy_and_set_has_taken_off(True)
     state = state.copy_and_set_time_used_seconds(
         state.time_used_seconds + self.drone_config.takeoff_height_meters / self.drone_config.speed_mps)
     state = state.copy_and_set_z_meters(self.drone_config.takeoff_height_meters)
     return state
Beispiel #2
0
 def test_check_parallel_drone_commands_nested_should_update_states_correctly(
         self):
     drone_commands = \
         [
             ParallelDroneCommands([
                 [SingleDroneCommand("DRONE1", Command.wait(5))],
                 [SingleDroneCommand("DRONE2", Command.wait(3)),
                  ParallelDroneCommands([
                      [SingleDroneCommand("DRONE3", Command.wait(4))],
                      [SingleDroneCommand("DRONE4", Command.wait(1))]
                  ])]
             ]),
             SingleDroneCommand("DRONE1", Command.wait(1))
         ]
     drones_involved = {"DRONE1", "DRONE2", "DRONE3", "DRONE4", "DRONE5"}
     state_updaters = {
         name: StateUpdater(DroneConfig((1, 0, 0), 2, 180, 2))
         for name in drones_involved
     }
     drone_state_map = {name: State() for name in drones_involved}
     BoundaryChecker(
         self.boundary_config)._update_states_and_check_drone_commands(
             drone_commands, state_updaters, drone_state_map,
             drones_involved)
     expected = {
         name: State(time_used_seconds=8)
         for name in drones_involved
     }
     self.assertEqual(expected, drone_state_map)
    def test_update_rotate_left_should_update_state(self):
        state = State(has_taken_off=True,
                      x_meters=1,
                      y_meters=2,
                      z_meters=3,
                      orientation_degrees=60)
        actual = self.state_updater.update(Command.rotate_left(90), state)
        expected = State(has_taken_off=True,
                         time_used_seconds=1 / 0.5,
                         x_meters=1,
                         y_meters=2,
                         z_meters=3,
                         orientation_degrees=330)
        self.assertEqual(expected, actual)

        state = State(has_taken_off=True,
                      x_meters=1,
                      y_meters=2,
                      z_meters=3,
                      orientation_degrees=240)
        actual = self.state_updater.update(Command.rotate_left(90), state)
        expected = State(has_taken_off=True,
                         time_used_seconds=1 / 0.5,
                         x_meters=1,
                         y_meters=2,
                         z_meters=3,
                         orientation_degrees=150)
        self.assertEqual(expected, actual)
Beispiel #4
0
 def _update_rotate_right(self, command: Command, state: State) -> State:
     assert command.opcode == "rotate_right"
     rotate_right_degrees, = command.operands
     state = state.copy_and_set_time_used_seconds(
         state.time_used_seconds + rotate_right_degrees / self.drone_config.rotate_speed_dps)
     state = state.copy_and_set_orientation_degrees((state.orientation_degrees + rotate_right_degrees) % 360)
     return state
    def test_update_right_should_update_state(self):
        state = State(has_taken_off=True,
                      x_meters=1,
                      y_meters=2,
                      z_meters=3,
                      orientation_degrees=60)
        actual = self.state_updater.update(Command.right(1), state)
        expected = State(has_taken_off=True,
                         time_used_seconds=1 / 0.5,
                         x_meters=1 + 0.5,
                         y_meters=2 - sqrt(3) / 2,
                         z_meters=3,
                         orientation_degrees=60)
        self.assertEqual(expected, actual)

        state = State(has_taken_off=True,
                      x_meters=1,
                      y_meters=2,
                      z_meters=3,
                      orientation_degrees=240)
        actual = self.state_updater.update(Command.right(1), state)
        expected = State(has_taken_off=True,
                         time_used_seconds=1 / 0.5,
                         x_meters=1 - 0.5,
                         y_meters=2 + sqrt(3) / 2,
                         z_meters=3,
                         orientation_degrees=240)
        self.assertEqual(expected, actual)
 def test_update_down_should_update_state(self):
     state = State(has_taken_off=True, z_meters=3)
     actual = self.state_updater.update(Command.down(1), state)
     expected = State(has_taken_off=True,
                      time_used_seconds=1 / 0.5,
                      z_meters=3 - 1)
     self.assertEqual(expected, actual)
 def test_update_land_should_update_state(self):
     state = State(has_taken_off=True, z_meters=3)
     actual = self.state_updater.update(Command.land(), state)
     expected = State(has_taken_off=False,
                      time_used_seconds=3 / 0.5,
                      z_meters=0)
     self.assertEqual(expected, actual)
Beispiel #8
0
 def _update_down(self, command: Command, state: State) -> State:
     assert command.opcode == "down"
     down_meters, = command.operands
     state = state.copy_and_set_time_used_seconds(
         state.time_used_seconds + down_meters / self.drone_config.speed_mps)
     state = state.copy_and_set_z_meters(state.z_meters - down_meters)
     return state
Beispiel #9
0
 def _update_land(self, command: Command, state: State) -> State:
     assert command.opcode == "land"
     state = state.copy_and_set_has_taken_off(False)
     state = state.copy_and_set_time_used_seconds(
         state.time_used_seconds + state.z_meters / self.drone_config.speed_mps)
     state = state.copy_and_set_z_meters(0)
     return state
 def test_update_takeoff_should_update_state(self):
     state = State()
     actual = self.state_updater.update(Command.takeoff(), state)
     expected = State(
         has_taken_off=True,
         time_used_seconds=self.drone_config.takeoff_height_meters / 0.5,
         z_meters=self.drone_config.takeoff_height_meters)
     self.assertEqual(expected, actual)
Beispiel #11
0
 def _update_backward(self, command: Command, state: State) -> State:
     assert command.opcode == "backward"
     backward_meters, = command.operands
     move_direction = state.orientation_degrees + 180
     state = state.copy_and_set_time_used_seconds(
         state.time_used_seconds + backward_meters / self.drone_config.speed_mps)
     state = state.copy_and_set_x_meters(state.x_meters + backward_meters * sin(radians(move_direction)))
     state = state.copy_and_set_y_meters(state.y_meters + backward_meters * cos(radians(move_direction)))
     return state
Beispiel #12
0
 def test_check_should_call_update_states_and_check_drone_commands_with_correct_parameters(
         self):
     boundary_checker = BoundaryChecker(self.boundary_config)
     boundary_checker._update_states_and_check_drone_commands = Mock()
     drone_state_map = {"DRONE1": State(), "DRONE2": State(x_meters=1)}
     drones_involved = {"DRONE1", "DRONE2"}
     boundary_checker.check([], self.state_updater_map)
     boundary_checker._update_states_and_check_drone_commands.assert_called_once_with(
         [], self.state_updater_map, drone_state_map, drones_involved)
 def test_get_init_state(self):
     self.assertEqual(State(x_meters=0, y_meters=0, z_meters=0),
                      self.state_updater.get_init_state())
     drone_config = DroneConfig(init_position=(1, 2, 3),
                                speed_mps=0.5,
                                rotate_speed_dps=45,
                                takeoff_height_meters=1)
     state_updater = StateUpdater(drone_config=drone_config)
     self.assertEqual(State(x_meters=1, y_meters=2, z_meters=3),
                      state_updater.get_init_state())
 def test_update_wait_should_update_state(self):
     state = State(has_taken_off=True,
                   x_meters=1,
                   y_meters=2,
                   z_meters=3,
                   orientation_degrees=60)
     actual = self.state_updater.update(Command.wait(5), state)
     expected = State(has_taken_off=True,
                      time_used_seconds=5,
                      x_meters=1,
                      y_meters=2,
                      z_meters=3,
                      orientation_degrees=60)
     self.assertEqual(expected, actual)
Beispiel #15
0
 def test_check_single_drone_command_should_update_state_correctly(self):
     drone_commands = [SingleDroneCommand("DRONE1", Command.takeoff())]
     drone_state_map = {"DRONE1": State(), "DRONE2": State(x_meters=1)}
     drones_involved = {"DRONE1", "DRONE2"}
     BoundaryChecker(
         self.boundary_config)._update_states_and_check_drone_commands(
             drone_commands, self.state_updater_map, drone_state_map,
             drones_involved)
     expected = {
         "DRONE1": State(has_taken_off=True,
                         time_used_seconds=1,
                         z_meters=1),
         "DRONE2": State(time_used_seconds=1, x_meters=1)
     }
     self.assertEqual(expected, drone_state_map)
Beispiel #16
0
 def test_check_parallel_drone_commands_should_let_drone_not_involved_wait(
         self):
     drone_commands = [
         ParallelDroneCommands(
             [[], [SingleDroneCommand("DRONE2", Command.wait(5))]])
     ]
     drone_state_map = {"DRONE1": State(), "DRONE2": State(x_meters=1)}
     drones_involved = {"DRONE1", "DRONE2"}
     BoundaryChecker(
         self.boundary_config)._update_states_and_check_drone_commands(
             drone_commands, self.state_updater_map, drone_state_map,
             drones_involved)
     expected = {
         "DRONE1": State(time_used_seconds=5),
         "DRONE2": State(time_used_seconds=5, x_meters=1)
     }
     self.assertEqual(expected, drone_state_map)
Beispiel #17
0
 def test_check_single_drone_command_should_check_state(self):
     boundary_checker = BoundaryChecker(self.boundary_config)
     boundary_checker.boundary_config.check_state = Mock()
     drone_commands = [
         SingleDroneCommand("DRONE1", Command.takeoff()),
         SingleDroneCommand("DRONE1", Command.land())
     ]
     BoundaryChecker(self.boundary_config).check(drone_commands,
                                                 self.state_updater_map)
     calls = [
         call("DRONE1",
              State(has_taken_off=True, time_used_seconds=1, z_meters=1)),
         call("DRONE2", State(time_used_seconds=1, x_meters=1)),
         call("DRONE1", State(time_used_seconds=2)),
         call("DRONE2", State(time_used_seconds=2, x_meters=1))
     ]
     boundary_checker.boundary_config.check_state.assert_has_calls(calls)
 def test_init_state(self):
     state = State()
     self.assertEqual(False, state.has_taken_off)
     self.assertEqual(0, state.time_used_seconds)
     self.assertEqual(0, state.x_meters)
     self.assertEqual(0, state.y_meters)
     self.assertEqual(0, state.z_meters)
     self.assertEqual(0, state.orientation_degrees)
 def test_property(self):
     state = State(has_taken_off=True, time_used_seconds=1,
                   x_meters=1, y_meters=1, z_meters=1, orientation_degrees=1)
     self.assertEqual(True, state.has_taken_off)
     self.assertEqual(1, state.time_used_seconds)
     self.assertEqual(1, state.x_meters)
     self.assertEqual(1, state.y_meters)
     self.assertEqual(1, state.z_meters)
     self.assertEqual(1, state.orientation_degrees)
Beispiel #20
0
 def test_check_parallel_drone_commands_should_wait_for_slower_branch(self):
     drone_commands = [
         ParallelDroneCommands(
             [[SingleDroneCommand("DRONE1", Command.takeoff())],
              [SingleDroneCommand("DRONE2", Command.wait(5))]])
     ]
     drone_state_map = {"DRONE1": State(), "DRONE2": State(x_meters=1)}
     drones_involved = {"DRONE1", "DRONE2"}
     BoundaryChecker(
         self.boundary_config)._update_states_and_check_drone_commands(
             drone_commands, self.state_updater_map, drone_state_map,
             drones_involved)
     expected = {
         "DRONE1": State(has_taken_off=True,
                         time_used_seconds=5,
                         z_meters=1),
         "DRONE2": State(time_used_seconds=5, x_meters=1)
     }
     self.assertEqual(expected, drone_state_map)
Beispiel #21
0
 def test_check_parallel_drone_commands_should_check_state(self):
     boundary_checker = BoundaryChecker(self.boundary_config)
     boundary_checker.boundary_config.check_state = Mock()
     drone_commands = [
         ParallelDroneCommands(
             [[
                 SingleDroneCommand("DRONE1", Command.takeoff()),
                 SingleDroneCommand("DRONE1", Command.land())
             ],
              [
                  SingleDroneCommand("DRONE2", Command.takeoff()),
                  SingleDroneCommand("DRONE2", Command.land())
              ]])
     ]
     BoundaryChecker(self.boundary_config).check(drone_commands,
                                                 self.state_updater_map)
     last_two_calls = [
         call("DRONE1", State(time_used_seconds=2)),
         call("DRONE2", State(time_used_seconds=2, x_meters=1))
     ]
     boundary_checker.boundary_config.check_state.assert_has_calls(
         last_two_calls)
 def test_check_state_if_no_limit_should_not_give_error(self):
     boundary_config = BoundaryConfig()
     for number in [1e-5, 1e-3, 1e0, 1e3, 1e5, 1e10, float('inf')]:
         boundary_config.check_state('default', State(x_meters=number))
         boundary_config.check_state('default', State(y_meters=number))
         boundary_config.check_state('default', State(z_meters=number))
         boundary_config.check_state('default', State(x_meters=-number))
         boundary_config.check_state('default', State(y_meters=-number))
         boundary_config.check_state('default', State(z_meters=-number))
         boundary_config.check_state('default',
                                     State(time_used_seconds=number))
    def test_check_state_if_beyond_limit_should_give_error(self):
        boundary_config = BoundaryConfig(max_seconds=0,
                                         max_x_meters=0,
                                         max_y_meters=0,
                                         max_z_meters=0,
                                         min_x_meters=0,
                                         min_y_meters=0,
                                         min_z_meters=0)
        with self.assertRaises(SafetyCheckError) as context:
            boundary_config.check_state('default', State(x_meters=10))
        self.assertTrue(
            "Drone 'default': the x coordinate 10 will go beyond its upper limit 0"
            in str(context.exception))

        with self.assertRaises(SafetyCheckError) as context:
            boundary_config.check_state('default', State(y_meters=10))
        self.assertTrue(
            "Drone 'default': the y coordinate 10 will go beyond its upper limit 0"
            in str(context.exception))

        with self.assertRaises(SafetyCheckError) as context:
            boundary_config.check_state('default', State(z_meters=10))
        self.assertTrue(
            "Drone 'default': the z coordinate 10 will go beyond its upper limit 0"
            in str(context.exception))

        with self.assertRaises(SafetyCheckError) as context:
            boundary_config.check_state('default', State(x_meters=-10))
        self.assertTrue(
            "Drone 'default': the x coordinate -10 will go beyond its lower limit 0"
            in str(context.exception))

        with self.assertRaises(SafetyCheckError) as context:
            boundary_config.check_state('default', State(y_meters=-10))
        self.assertTrue(
            "Drone 'default': the y coordinate -10 will go beyond its lower limit 0"
            in str(context.exception))

        with self.assertRaises(SafetyCheckError) as context:
            boundary_config.check_state('default', State(z_meters=-10))
        self.assertTrue(
            "Drone 'default': the z coordinate -10 will go beyond its lower limit 0"
            in str(context.exception))

        with self.assertRaises(SafetyCheckError) as context:
            boundary_config.check_state('default', State(time_used_seconds=10))
        self.assertTrue(
            "Drone 'default': the time used 10 seconds will go beyond the time limit 0 seconds"
            in str(context.exception))
 def test_eq(self):
     self.assertEqual(State(), State())
     self.assertNotEqual(State(time_used_seconds=False), State(has_taken_off=True))
     self.assertNotEqual(State(time_used_seconds=0), State(time_used_seconds=1))
     self.assertNotEqual(State(x_meters=0), State(x_meters=1))
     self.assertNotEqual(State(y_meters=0), State(y_meters=1))
     self.assertNotEqual(State(z_meters=0), State(z_meters=1))
     self.assertNotEqual(State(orientation_degrees=0), State(orientation_degrees=1))
     self.assertNotEqual(None, State())
 def test_str(self):
     state = State()
     self.assertEqual("State: { has_taken_off: False, time_used_seconds: 0, " +
                      "x_meters: 0, y_meters: 0, z_meters: 0, orientation_degrees: 0 }",
                      str(state))
 def test_copy_and_set_orientation_degrees(self):
     state = State()
     actual = state.copy_and_set_orientation_degrees(1)
     expected = State(has_taken_off=False, time_used_seconds=0,
                      x_meters=0, y_meters=0, z_meters=0, orientation_degrees=1)
     self.assertEqual(expected, actual)
Beispiel #27
0
 def _update_wait(self, command: Command, state: State) -> State:
     assert command.opcode == "wait"
     wait_seconds, = command.operands
     state = state.copy_and_set_time_used_seconds(state.time_used_seconds + wait_seconds)
     return state
Beispiel #28
0
 def get_init_state(self) -> State:
     (x, y, z) = self.drone_config.init_position
     return State(x_meters=x, y_meters=y, z_meters=z)