Beispiel #1
0
 def test_eq(self):
     commands1 = [
         None,
         Command.takeoff(),
         Command.land(),
         Command.up(1),
         Command.down(1),
         Command.left(1),
         Command.right(1),
         Command.forward(1),
         Command.backward(1),
         Command.rotate_left(1),
         Command.rotate_right(1),
         Command.wait(1),
         Command.up(2),
         Command.down(2),
         Command.left(2),
         Command.right(2),
         Command.forward(2),
         Command.backward(2),
         Command.rotate_left(2),
         Command.rotate_right(2),
         Command.wait(2)
     ]
     commands2 = [
         None,
         Command.takeoff(),
         Command.land(),
         Command.up(1),
         Command.down(1),
         Command.left(1),
         Command.right(1),
         Command.forward(1),
         Command.backward(1),
         Command.rotate_left(1),
         Command.rotate_right(1),
         Command.wait(1),
         Command.up(2),
         Command.down(2),
         Command.left(2),
         Command.right(2),
         Command.forward(2),
         Command.backward(2),
         Command.rotate_left(2),
         Command.rotate_right(2),
         Command.wait(2)
     ]
     for i in range(len(commands1)):
         for j in range(len(commands2)):
             if i == j:
                 self.assertEqual(commands1[i], commands2[j])
             else:
                 self.assertNotEqual(commands1[i], commands2[j])
Beispiel #2
0
 def test_multiple_commands_should_return_correct_command(self):
     actual = generate_commands("""
         main() {
          takeoff();
          up(1);
          down(2);
          left(3);
          right(4);
          forward(5);
          backward(6);
          rotate_left(7);
          rotate_right(8);
          wait(9);
          land(); 
         }
     """)
     expected = [
         SingleDroneCommand("DEFAULT", Command.takeoff()),
         SingleDroneCommand("DEFAULT", Command.up(1)),
         SingleDroneCommand("DEFAULT", Command.down(2)),
         SingleDroneCommand("DEFAULT", Command.left(3)),
         SingleDroneCommand("DEFAULT", Command.right(4)),
         SingleDroneCommand("DEFAULT", Command.forward(5)),
         SingleDroneCommand("DEFAULT", Command.backward(6)),
         SingleDroneCommand("DEFAULT", Command.rotate_left(7)),
         SingleDroneCommand("DEFAULT", Command.rotate_right(8)),
         SingleDroneCommand("DEFAULT", Command.wait(9)),
         SingleDroneCommand("DEFAULT", Command.land())
     ]
     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)
Beispiel #4
0
 def test_down_with_decimal_parameter_should_return_correct_command(self):
     actual = generate_commands("""
         main() { takeoff(); down(1.0); land(); }
     """)
     expected = [
         SingleDroneCommand("DEFAULT", Command.takeoff()),
         SingleDroneCommand("DEFAULT", Command.down(1.0)),
         SingleDroneCommand("DEFAULT", Command.land())
     ]
     self.assertEqual(expected, actual)
Beispiel #5
0
 def test_down_with_drone_name_should_return_correct_command(self):
     actual = generate_commands(
         """
         main() { DRONE1.takeoff(); DRONE1.down(1); DRONE1.land(); }
     """,
         drone_config_map={"DRONE1": DefaultDroneConfig()})
     expected = [
         SingleDroneCommand("DRONE1", Command.takeoff()),
         SingleDroneCommand("DRONE1", Command.down(1)),
         SingleDroneCommand("DRONE1", Command.land())
     ]
     self.assertEqual(expected, actual)
 def visitDown(self, ctx: xDroneParser.DownContext) -> None:
     exprs = [self.visit(expr) for expr in ctx.expr()]
     if ctx.DOT():
         drone_expr, expr = exprs
     else:
         drone_expr, expr = None, exprs[0]
     if expr.type != Type.int() and expr.type != Type.decimal():
         raise CompileError(
             "Expression {} should have type int or decimal, but is {}".
             format(expr, expr.type))
     drone_name = self._get_drone_name(drone_expr)
     self._get_latest_commands().append(
         SingleDroneCommand(drone_name, Command.down(expr.value)))
 def test_call_procedure_should_run_commands(self):
     commands = generate_commands("""
         procedure proc(int i, int j) {
           up(i + j);
           down(i);
         }
         main () {
           takeoff();
           proc(100, 200);
           land();
         }
         """)
     expected_commands = [SingleDroneCommand("DEFAULT", Command.takeoff()),
                          SingleDroneCommand("DEFAULT", Command.up(300)),
                          SingleDroneCommand("DEFAULT", Command.down(100)),
                          SingleDroneCommand("DEFAULT", Command.land())]
     self.assertEqual(expected_commands, commands)
Beispiel #8
0
 def test_execute_single_drone_command(self):
     single_commands = [
         SingleDroneCommand("name1", Command.takeoff()),
         SingleDroneCommand("name1", Command.land()),
         SingleDroneCommand("name2", Command.up(1.1)),
         SingleDroneCommand("name2", Command.down(1.2)),
         SingleDroneCommand("name2", Command.left(1.3)),
         SingleDroneCommand("name2", Command.right(1.4)),
         SingleDroneCommand("name2", Command.forward(1.5)),
         SingleDroneCommand("name2", Command.backward(1.6)),
         SingleDroneCommand("name2", Command.rotate_left(91)),
         SingleDroneCommand("name2", Command.rotate_right(92)),
         SingleDroneCommand("name2", Command.wait(1))
     ]
     with patch(
             'xdrone.command_converters.dji_tello_edu_drone_executor.FlyTello',
             return_value=self.fly_tello):
         executor = DJITelloEduExecutor(self.name_id_map)
         executor.execute_drone_commands(single_commands)
         calls = [
             call.wait_sync(),
             call.takeoff(tello=1),
             call.wait_sync(),
             call.land(tello=1),
             call.wait_sync(),
             call.up(110, tello=2),
             call.wait_sync(),
             call.down(120, tello=2),
             call.wait_sync(),
             call.left(130, tello=2),
             call.wait_sync(),
             call.right(140, tello=2),
             call.wait_sync(),
             call.forward(150, tello=2),
             call.wait_sync(),
             call.back(160, tello=2),
             call.wait_sync(),
             call.rotate_ccw(91, tello=2),
             call.wait_sync(),
             call.rotate_cw(92, tello=2),
             call.wait_sync(),
             call.pause(1)
         ]
         self.fly.assert_has_calls(calls)
 def test_call_function_should_run_commands_and_return(self):
     commands = generate_commands("""
         function func(int i, int j) return int {
           up(i + j);
           down(i);
           return i + j;
         }
         main () {
           takeoff();
           forward(func(100, 200));
           land();
         }
         """)
     expected_commands = [SingleDroneCommand("DEFAULT", Command.takeoff()),
                          SingleDroneCommand("DEFAULT", Command.up(300)),
                          SingleDroneCommand("DEFAULT", Command.down(100)),
                          SingleDroneCommand("DEFAULT", Command.forward(300)),
                          SingleDroneCommand("DEFAULT", Command.land())]
     self.assertEqual(expected_commands, commands)
Beispiel #10
0
 def test_check_single_drone_command_other_command_when_not_taken_off_should_give_error(
         self):
     commands = [
         Command.land(),
         Command.up(1),
         Command.down(1),
         Command.left(1),
         Command.right(1),
         Command.forward(1),
         Command.backward(1),
         Command.rotate_left(90),
         Command.rotate_right(90)
     ]
     for command in commands:
         with self.assertRaises(SafetyCheckError) as context:
             drone_commands = [SingleDroneCommand("DRONE1", command)]
             BoundaryChecker(self.boundary_config).check(
                 drone_commands, self.state_updater_map)
         self.assertTrue(
             "'{}' command used when drone 'DRONE1' has not been taken off".
             format(command.opcode) in str(context.exception))
    def test_convert_command(self):
        commands = [
            SingleDroneCommand("DRONE1", Command.takeoff()),
            SingleDroneCommand("DRONE1", Command.up(1)),
            SingleDroneCommand("DRONE1", Command.down(1)),
            SingleDroneCommand("DRONE1", Command.left(1)),
            SingleDroneCommand("DRONE1", Command.right(1)),
            SingleDroneCommand("DRONE1", Command.forward(1)),
            SingleDroneCommand("DRONE1", Command.backward(1)),
            SingleDroneCommand("DRONE1", Command.rotate_left(1)),
            SingleDroneCommand("DRONE1", Command.rotate_right(1)),
            ParallelDroneCommands(
                [[
                    ParallelDroneCommands(
                        [[], [SingleDroneCommand("DRONE1", Command.up(1))]])
                ],
                 [
                     SingleDroneCommand("DRONE2", Command.takeoff()),
                     SingleDroneCommand("DRONE2", Command.land())
                 ]]),
            SingleDroneCommand("DRONE1", Command.land()),
            SingleDroneCommand("DRONE1", Command.wait(1))
        ]
        drone_config_map = {
            "DRONE1": DroneConfig((1, 2, 3), 1, 90, 2),
            "DRONE2": DroneConfig((0, 0, 0), 1, 90, 1)
        }
        expected = {
            "config": [{
                "name": "DRONE1",
                "init_pos": [1, 2, 3],
                "speed": 1,
                "rotate_speed": 90,
                "takeoff_height": 2
            }, {
                "name": "DRONE2",
                "init_pos": [0, 0, 0],
                "speed": 1,
                "rotate_speed": 90,
                "takeoff_height": 1
            }],
            "commands": [{
                "type": "single",
                "name": "DRONE1",
                "action": "takeoff",
                "values": []
            }, {
                "type": "single",
                "name": "DRONE1",
                "action": "up",
                "values": [1]
            }, {
                "type": "single",
                "name": "DRONE1",
                "action": "down",
                "values": [1]
            }, {
                "type": "single",
                "name": "DRONE1",
                "action": "left",
                "values": [1]
            }, {
                "type": "single",
                "name": "DRONE1",
                "action": "right",
                "values": [1]
            }, {
                "type": "single",
                "name": "DRONE1",
                "action": "forward",
                "values": [1]
            }, {
                "type": "single",
                "name": "DRONE1",
                "action": "backward",
                "values": [1]
            }, {
                "type": "single",
                "name": "DRONE1",
                "action": "rotate_left",
                "values": [1]
            }, {
                "type": "single",
                "name": "DRONE1",
                "action": "rotate_right",
                "values": [1]
            }, {
                "type":
                "parallel",
                "branches": [[{
                    "type":
                    "parallel",
                    "branches": [[],
                                 [{
                                     "type": "single",
                                     "name": "DRONE1",
                                     "action": "up",
                                     "values": [1]
                                 }]]
                }],
                             [{
                                 "type": "single",
                                 "name": "DRONE2",
                                 "action": "takeoff",
                                 "values": []
                             }, {
                                 "type": "single",
                                 "name": "DRONE2",
                                 "action": "land",
                                 "values": []
                             }]]
            }, {
                "type": "single",
                "name": "DRONE1",
                "action": "land",
                "values": []
            }, {
                "type": "single",
                "name": "DRONE1",
                "action": "wait",
                "values": [1]
            }]
        }
        actual = SimulationConverter().convert(commands, drone_config_map)

        self.assertEqual(expected,
                         json.loads(zlib.decompress(b64decode(actual))))
Beispiel #12
0
 def _update_states(self, single_drone_command: SingleDroneCommand,
                    state_updaters: Dict[str, StateUpdater],
                    drone_trajectory_map: Dict[str, List[State]],
                    drones_involved: Set[str]) -> float:
     time_interval = self.collision_config.time_interval_seconds
     drone_name = single_drone_command.drone_name
     command = single_drone_command.command
     if command.opcode == "takeoff":
         takeoff_distance = self.drone_config_map[
             drone_name].takeoff_height_meters
         new_drone_command = SingleDroneCommand(
             drone_name, Command.up(takeoff_distance))
         return self._update_states(new_drone_command, state_updaters,
                                    drone_trajectory_map, drones_involved)
     if command.opcode == "land":
         old_state = drone_trajectory_map[drone_name][-1]
         land_distance = old_state.z_meters
         new_drone_command = SingleDroneCommand(drone_name,
                                                Command.down(land_distance))
         return self._update_states(new_drone_command, state_updaters,
                                    drone_trajectory_map, drones_involved)
     if command.opcode == "wait":
         seconds, = command.operands
         old_state = drone_trajectory_map[drone_name][-1]
         if seconds <= time_interval:
             new_state = state_updaters[drone_name].update(
                 Command.wait(seconds), old_state)
             drone_trajectory_map[drone_name].append(new_state)
             for name in drones_involved.difference({drone_name}):
                 state = drone_trajectory_map[name][-1]
                 drone_trajectory_map[name].append(
                     state.copy_and_set_time_used_seconds(
                         state.time_used_seconds + seconds))
             return seconds
         else:
             new_state = state_updaters[drone_name].update(
                 Command.wait(time_interval), old_state)
             drone_trajectory_map[drone_name].append(new_state)
             for name in drones_involved.difference({drone_name}):
                 state = drone_trajectory_map[name][-1]
                 drone_trajectory_map[name].append(
                     state.copy_and_set_time_used_seconds(
                         state.time_used_seconds + time_interval))
             new_drone_command = SingleDroneCommand(
                 drone_name, Command.wait(seconds - time_interval))
             return time_interval + self._update_states(
                 new_drone_command, state_updaters, drone_trajectory_map,
                 drones_involved)
     if command.opcode in ["rotate_left", "rotate_right"]:
         degrees, = command.operands
         old_state = drone_trajectory_map[drone_name][-1]
         rotate_speed = self.drone_config_map[drone_name].rotate_speed_dps
         seconds = degrees / rotate_speed
         if seconds <= time_interval:
             new_state = state_updaters[drone_name].update(
                 Command(command.opcode, [rotate_speed * seconds]),
                 old_state)
             drone_trajectory_map[drone_name].append(new_state)
             for name in drones_involved.difference({drone_name}):
                 state = drone_trajectory_map[name][-1]
                 drone_trajectory_map[name].append(
                     state.copy_and_set_time_used_seconds(
                         state.time_used_seconds + seconds))
             return seconds
         else:
             new_state = state_updaters[drone_name].update(
                 Command(command.opcode, [rotate_speed * time_interval]),
                 old_state)
             drone_trajectory_map[drone_name].append(new_state)
             for name in drones_involved.difference({drone_name}):
                 state = drone_trajectory_map[name][-1]
                 drone_trajectory_map[name].append(
                     state.copy_and_set_time_used_seconds(
                         state.time_used_seconds + time_interval))
             new_drone_command = SingleDroneCommand(
                 drone_name,
                 Command(command.opcode,
                         [degrees - rotate_speed * time_interval]))
             return time_interval + self._update_states(
                 new_drone_command, state_updaters, drone_trajectory_map,
                 drones_involved)
     if command.opcode in [
             "up", "down", "left", "right", "forward", "backward"
     ]:
         meters, = command.operands
         old_state = drone_trajectory_map[drone_name][-1]
         speed = self.drone_config_map[drone_name].speed_mps
         seconds = meters / speed
         if seconds <= time_interval:
             new_state = state_updaters[drone_name].update(
                 Command(command.opcode, [speed * seconds]), old_state)
             drone_trajectory_map[drone_name].append(new_state)
             for name in drones_involved.difference({drone_name}):
                 state = drone_trajectory_map[name][-1]
                 drone_trajectory_map[name].append(
                     state.copy_and_set_time_used_seconds(
                         state.time_used_seconds + seconds))
             return seconds
         else:
             new_state = state_updaters[drone_name].update(
                 Command(command.opcode, [speed * time_interval]),
                 old_state)
             drone_trajectory_map[drone_name].append(new_state)
             for name in drones_involved.difference({drone_name}):
                 state = drone_trajectory_map[name][-1]
                 drone_trajectory_map[name].append(
                     state.copy_and_set_time_used_seconds(
                         state.time_used_seconds + time_interval))
             new_drone_command = SingleDroneCommand(
                 drone_name,
                 Command(command.opcode, [meters - speed * time_interval]))
             return time_interval + self._update_states(
                 new_drone_command, state_updaters, drone_trajectory_map,
                 drones_involved)
Beispiel #13
0
 def test_dji_tello_executor_should_send_correct_message(self) -> None:
     mocked_socket = Mock()
     mocked_socket.recvfrom = Mock(return_value=(b'ok', ('192.168.10.1',
                                                         8889)))
     mocked_socket.sendto = Mock()
     commands = [
         Command.takeoff(),
         Command.up(1),
         Command.down(1),
         Command.left(1),
         Command.right(1),
         Command.forward(1),
         Command.backward(1),
         Command.rotate_left(90),
         Command.rotate_right(90),
         Command.wait(0),
         Command.land()
     ]
     executor = DJITelloExecutor()
     executor.sock.close()
     executor.sock = mocked_socket
     with self.assertLogs(logging.getLogger()) as log:
         executor.execute_commands(commands)
     calls = [
         call(b"command", ('192.168.10.1', 8889)),
         call(b"takeoff", ('192.168.10.1', 8889)),
         call(b"up 100", ('192.168.10.1', 8889)),
         call(b"down 100", ('192.168.10.1', 8889)),
         call(b"left 100", ('192.168.10.1', 8889)),
         call(b"right 100", ('192.168.10.1', 8889)),
         call(b"forward 100", ('192.168.10.1', 8889)),
         call(b"back 100", ('192.168.10.1', 8889)),
         call(b"ccw 90", ('192.168.10.1', 8889)),
         call(b"cw 90", ('192.168.10.1', 8889)),
         call(b"land", ('192.168.10.1', 8889))
     ]
     mocked_socket.sendto.assert_has_calls(calls)
     expected_log = [
         "INFO:root:sent message: b'command'",
         "INFO:root:received response: ok",
         "INFO:root:sent message: b'takeoff'",
         "INFO:root:received response: ok",
         "INFO:root:sent message: b'up 100'",
         "INFO:root:received response: ok",
         "INFO:root:sent message: b'down 100'",
         "INFO:root:received response: ok",
         "INFO:root:sent message: b'left 100'",
         "INFO:root:received response: ok",
         "INFO:root:sent message: b'right 100'",
         "INFO:root:received response: ok",
         "INFO:root:sent message: b'forward 100'",
         "INFO:root:received response: ok",
         "INFO:root:sent message: b'back 100'",
         "INFO:root:received response: ok",
         "INFO:root:sent message: b'ccw 90'",
         "INFO:root:received response: ok",
         "INFO:root:sent message: b'cw 90'",
         "INFO:root:received response: ok",
         "INFO:root:sent message: b'land'",
         "INFO:root:received response: ok"
     ]
     self.assertEqual(expected_log, log.output)
Beispiel #14
0
 def test_down(self):
     self.assertEqual(Command.down(1), Command.down(1))
     self.assertEqual("down", Command.down(1).opcode)
     self.assertEqual([1], Command.down(1).operands)
     self.assertEqual("Command: { opcode: down, operands: [1] }",
                      str(Command.down(1)))