def test_update_backward_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.backward(1), state) expected = State(has_taken_off=True, time_used_seconds=1 / 0.5, x_meters=1 - sqrt(3) / 2, y_meters=2 - 0.5, 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.backward(1), state) expected = State(has_taken_off=True, time_used_seconds=1 / 0.5, x_meters=1 + sqrt(3) / 2, y_meters=2 + 0.5, z_meters=3, orientation_degrees=240) self.assertEqual(expected, actual)
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])
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_backward_with_int_parameter_should_return_correct_command(self): actual = generate_commands(""" main() { takeoff(); backward(1); land(); } """) expected = [ SingleDroneCommand("DEFAULT", Command.takeoff()), SingleDroneCommand("DEFAULT", Command.backward(1)), SingleDroneCommand("DEFAULT", Command.land()) ] self.assertEqual(expected, actual)
def test_backward_with_drone_name_should_return_correct_command(self): actual = generate_commands( """ main() { DRONE1.takeoff(); DRONE1.backward(1); DRONE1.land(); } """, drone_config_map={"DRONE1": DefaultDroneConfig()}) expected = [ SingleDroneCommand("DRONE1", Command.takeoff()), SingleDroneCommand("DRONE1", Command.backward(1)), SingleDroneCommand("DRONE1", Command.land()) ] self.assertEqual(expected, actual)
def visitBackward(self, ctx: xDroneParser.BackwardContext) -> 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.backward(expr.value)))
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_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))))
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)
def test_backward(self): self.assertEqual(Command.backward(1), Command.backward(1)) self.assertEqual("backward", Command.backward(1).opcode) self.assertEqual([1], Command.backward(1).operands) self.assertEqual("Command: { opcode: backward, operands: [1] }", str(Command.backward(1)))