def test_update_rotate_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.rotate_right(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) 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_right(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)
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_rotate_right_with_decimal_parameter_should_return_correct_command( self): actual = generate_commands(""" main() { takeoff(); rotate_right(1.0); land(); } """) expected = [ SingleDroneCommand("DEFAULT", Command.takeoff()), SingleDroneCommand("DEFAULT", Command.rotate_right(1)), SingleDroneCommand("DEFAULT", Command.land()) ] self.assertEqual(expected, actual)
def test_rotate_right_with_drone_name_should_return_correct_command(self): actual = generate_commands( """ main() { DRONE1.takeoff(); DRONE1.rotate_right(1); DRONE1.land(); } """, drone_config_map={"DRONE1": DefaultDroneConfig()}) expected = [ SingleDroneCommand("DRONE1", Command.takeoff()), SingleDroneCommand("DRONE1", Command.rotate_right(1)), SingleDroneCommand("DRONE1", Command.land()) ] self.assertEqual(expected, actual)
def visitRotateRight(self, ctx: xDroneParser.RotateRightContext) -> 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.rotate_right(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_rotate_right(self): self.assertEqual(Command.rotate_right(1), Command.rotate_right(1)) self.assertEqual("rotate_right", Command.rotate_right(1).opcode) self.assertEqual([1], Command.rotate_right(1).operands) self.assertEqual("Command: { opcode: rotate_right, operands: [1] }", str(Command.rotate_right(1)))