예제 #1
0
 def test_execute_parallel_drone_commands(self):
     parallel_commands = [
         ParallelDroneCommands(
             [[
                 SingleDroneCommand("name1", Command.takeoff()),
                 SingleDroneCommand("name1", Command.land())
             ],
              [
                  SingleDroneCommand("name2", Command.takeoff()),
                  SingleDroneCommand("name2", Command.land())
              ]])
     ]
     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(parallel_commands)
         calls = [
             call.wait_sync(),
             call.takeoff(tello=1),
             call.land(tello=1),
             call.takeoff(tello=2),
             call.land(tello=2)
         ]
         self.fly.assert_has_calls(calls)
예제 #2
0
 def test_parallel_with_different_drones_should_give_correct_commands(self):
     drone_config_map = {
         "DRONE1": DefaultDroneConfig(),
         "DRONE2": DefaultDroneConfig(),
         "DRONE3": DefaultDroneConfig()
     }
     actual = generate_commands("""
         main() { 
           {DRONE1.takeoff();} || {DRONE2.takeoff();} || {DRONE3.takeoff();}; 
           {
             DRONE1.land();
           } || {
             {DRONE2.land();} || {DRONE3.land();};
           };
         }
     """,
                                drone_config_map=drone_config_map)
     expected = [
         ParallelDroneCommands(
             [[SingleDroneCommand("DRONE1", Command.takeoff())],
              [SingleDroneCommand("DRONE2", Command.takeoff())],
              [SingleDroneCommand("DRONE3", Command.takeoff())]]),
         ParallelDroneCommands(
             [[SingleDroneCommand("DRONE1", Command.land())],
              [
                  ParallelDroneCommands(
                      [[SingleDroneCommand("DRONE2", Command.land())],
                       [SingleDroneCommand("DRONE3", Command.land())]])
              ]])
     ]
     self.assertEqual(expected, actual)
예제 #3
0
 def test_check_takeoff_land_takeoff_land_should_not_give_error(self):
     drone_commands = [
         SingleDroneCommand("DRONE1", Command.takeoff()),
         SingleDroneCommand("DRONE1", Command.land()),
         SingleDroneCommand("DRONE1", Command.takeoff()),
         SingleDroneCommand("DRONE1", Command.land()),
     ]
     BoundaryChecker(self.boundary_config).check(drone_commands,
                                                 self.state_updater_map)
예제 #4
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])
    def test_check_parallel_drone_command_should_detect_collision_and_give_error(self):
        drone_commands = [SingleDroneCommand("DRONE1", Command.takeoff()),
                          SingleDroneCommand("DRONE2", Command.takeoff()),
                          ParallelDroneCommands([
                              [SingleDroneCommand("DRONE1", Command.right(1))],
                              [SingleDroneCommand("DRONE2", Command.left(1))]
                          ]),
                          SingleDroneCommand("DRONE1", Command.land()),
                          SingleDroneCommand("DRONE2", Command.land())]

        with self.assertRaises(SafetyCheckError) as context:
            self.collision_checker.check(drone_commands, self.state_updater_map)
        self.assertTrue("Collisions might happen!\nCollision might happen between DRONE1 and DRONE2"
                        in str(context.exception))
예제 #6
0
 def test_basic_program(self):
     commands = "main() {takeoff(); land();}"
     expected = [
         SingleDroneCommand("DEFAULT", Command.takeoff()),
         SingleDroneCommand("DEFAULT", Command.land())
     ]
     self.assertEqual(expected, generate_commands(commands))
예제 #7
0
 def test_dji_tello_executor_if_receive_error_should_print(self) -> None:
     mocked_socket = Mock()
     mocked_socket.recvfrom = Mock(side_effect=Exception('timed out'))
     mocked_socket.sendto = Mock()
     commands = [Command.takeoff(), 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"land", ('192.168.10.1', 8889))
     ]
     mocked_socket.sendto.assert_has_calls(calls)
     expected_log = [
         "INFO:root:sent message: b'command'",
         "ERROR:root:Error met when receiving response: timed out",
         "INFO:root:sent message: b'takeoff'",
         "ERROR:root:Error met when receiving response: timed out",
         "INFO:root:sent message: b'land'",
         "ERROR:root:Error met when receiving response: timed out"
     ]
     self.assertEqual(expected_log, log.output)
 def test_function_procedure_in_function(self):
     commands = generate_commands("""
         function func(int i) return int {
           while i < 10 {
             i <- i + 1;
           }
           return i;
         }
         procedure proc(int i) {
           forward(i * i);
         }
         function func2(int i) return int {
           proc(func(i));
           return func(i) * func(i);
         }
         main () {
           takeoff();
           forward(func2(1));
           land();
         }
         """)
     expected_commands = [SingleDroneCommand("DEFAULT", Command.takeoff()),
                          SingleDroneCommand("DEFAULT", Command.forward(100)),
                          SingleDroneCommand("DEFAULT", Command.forward(100)),
                          SingleDroneCommand("DEFAULT", Command.land())]
     self.assertEqual(expected_commands, commands)
예제 #9
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)
예제 #10
0
    def test_dji_tello_executor_if_interrupt_error_should_stop_and_emergency(
            self) -> None:
        mocked_socket = Mock()
        mocked_socket.recvfrom = Mock(return_value=(b'ok', ('192.168.10.1',
                                                            8889)))
        mocked_socket.sendto = Mock()

        def mocked_sendto(msg, _):
            if msg == b"takeoff":
                raise KeyboardInterrupt

        mocked_socket.sendto.side_effect = mocked_sendto
        commands = [Command.takeoff(), 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"emergency", ('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:KeyboardInterrupt received. Forced stop."
        ]
        self.assertEqual(expected_log, log.output)
 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)
예제 #12
0
 def test_eq(self):
     self.assertEqual(SingleDroneCommand("abc", Command.takeoff()),
                      SingleDroneCommand("abc", Command.takeoff()))
     self.assertNotEqual(SingleDroneCommand("", Command.takeoff()),
                         SingleDroneCommand("abc", Command.takeoff()))
     self.assertNotEqual(SingleDroneCommand("abc", Command.takeoff()),
                         SingleDroneCommand("abc", Command.land()))
     self.assertNotEqual(None, SingleDroneCommand("abc", Command.takeoff()))
예제 #13
0
 def test_land_should_return_correct_command(self):
     actual = generate_commands("""
         main() { takeoff(); land(); }
     """)
     expected = [
         SingleDroneCommand("DEFAULT", Command.takeoff()),
         SingleDroneCommand("DEFAULT", Command.land())
     ]
     self.assertEqual(expected, actual)
 def test_check_bad_collision_config_should_not_give_error(self):
     collision_config = CollisionConfig(collision_meters=0.3, time_interval_seconds=0.001)
     collision_checker = CollisionChecker(self.drone_config_map, collision_config)
     drone_commands = [SingleDroneCommand("DRONE1", Command.takeoff()),
                       SingleDroneCommand("DRONE1", Command.land())]
     with self.assertRaises(SafetyCheckError) as context:
         collision_checker.check(drone_commands, self.state_updater_map)
     self.assertTrue("Error occurred during collision check, please retry with better the collision_config."
                     in str(context.exception))
예제 #15
0
 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)
예제 #16
0
 def test_up_with_decimal_parameter_should_return_correct_command(self):
     actual = generate_commands("""
         main() { takeoff(); up(1.0); land(); }
     """)
     expected = [
         SingleDroneCommand("DEFAULT", Command.takeoff()),
         SingleDroneCommand("DEFAULT", Command.up(1.0)),
         SingleDroneCommand("DEFAULT", Command.land())
     ]
     self.assertEqual(expected, actual)
예제 #17
0
 def test_land_with_drone_name_should_return_correct_command(self):
     actual = generate_commands(
         """
         main() { DRONE1.takeoff(); DRONE1.land(); }
     """,
         drone_config_map={"DRONE1": DefaultDroneConfig()})
     expected = [
         SingleDroneCommand("DRONE1", Command.takeoff()),
         SingleDroneCommand("DRONE1", Command.land())
     ]
     self.assertEqual(expected, actual)
예제 #18
0
 def test_movement_with_no_name_specified_if_only_one_drone_should_use_that_drone(
         self):
     drone_config_map = {"THE_ONE": DefaultDroneConfig()}
     actual = generate_commands("""
         main() { takeoff(); land(); }
     """,
                                drone_config_map=drone_config_map)
     expected = [
         SingleDroneCommand("THE_ONE", Command.takeoff()),
         SingleDroneCommand("THE_ONE", Command.land())
     ]
     self.assertEqual(expected, actual)
예제 #19
0
 def test_check_single_drone_command_should_check_state_and_catch_error(
         self):
     boundary_checker = BoundaryChecker(self.boundary_config)
     boundary_checker.boundary_config.check_state = Mock(
         side_effect=SafetyCheckError)
     drone_commands = [
         SingleDroneCommand("DRONE1", Command.takeoff()),
         SingleDroneCommand("DRONE1", Command.land())
     ]
     with self.assertRaises(SafetyCheckError) as context:
         BoundaryChecker(self.boundary_config).check(
             drone_commands, self.state_updater_map)
예제 #20
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)
예제 #21
0
 def test_if_with_error_commands_not_entering_should_not_give_error(self):
     actual_commands = generate_commands("""
         main () {
           takeoff();
           if false {
             int a <- "error";
             forward(1);
           }
           land();
         }
         """)
     expected_commands = [SingleDroneCommand("DEFAULT", Command.takeoff()),
                          SingleDroneCommand("DEFAULT", Command.land())]
     self.assertEqual(expected_commands, actual_commands)
예제 #22
0
 def test_repeat_should_run_correct_commands(self):
     actual_commands = generate_commands("""
         main () {
           takeoff();
           repeat 4 times {
             forward(1);
           }
           land();
         }
         """)
     expected_commands = [SingleDroneCommand("DEFAULT", Command.takeoff())] + \
                         [SingleDroneCommand("DEFAULT", Command.forward(1)) for _ in range(4)] + \
                         [SingleDroneCommand("DEFAULT", Command.land())]
     self.assertEqual(expected_commands, actual_commands)
 def test_call_procedure_with_parameter_should_shadow_constant(self):
     commands = generate_commands("""
         procedure proc(drone DRONE2) {
           DRONE2.up(1);
         }
         main () {
           DRONE1.takeoff();
           proc(DRONE1);
           DRONE1.land();
         }
         """, drone_config_map={"DRONE1": DefaultDroneConfig(), "DRONE2": DefaultDroneConfig()})
     expected_commands = [SingleDroneCommand("DRONE1", Command.takeoff()),
                          SingleDroneCommand("DRONE1", Command.up(1)),
                          SingleDroneCommand("DRONE1", Command.land())]
     self.assertEqual(expected_commands, commands)
예제 #24
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_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)
 def test_recursion(self):
     commands = generate_commands("""
         function func(int i) return int {
           if i >= 10 {
             return 10;
           }
           return func(i + 1);
         }
         main () {
           takeoff();
           forward(func(1));
           land();
         }
         """)
     expected_commands = [SingleDroneCommand("DEFAULT", Command.takeoff()),
                          SingleDroneCommand("DEFAULT", Command.forward(10)),
                          SingleDroneCommand("DEFAULT", Command.land())]
     self.assertEqual(expected_commands, commands)
예제 #27
0
 def test_if_true_without_else_should_run_correct_commands(self):
     actual_st = SymbolTable()
     actual_commands = generate_commands("""
         main () {
           takeoff();
           if true {
             int a <- 1;
             forward(a);
           }
           land();
         }
         """, symbol_table=actual_st)
     expected_st = SymbolTable()
     self.assertEqual(expected_st, actual_st)
     expected_commands = [SingleDroneCommand("DEFAULT", Command.takeoff()),
                          SingleDroneCommand("DEFAULT", Command.forward(1)),
                          SingleDroneCommand("DEFAULT", Command.land())]
     self.assertEqual(expected_commands, actual_commands)
 def test_loops_in_function(self):
     commands = generate_commands("""
         function func(int i) return int {
           while i < 10 {
             i <- i + 1;
           }
           return i;
         }
         main () {
           takeoff();
           forward(func(1));
           land();
         }
         """)
     expected_commands = [SingleDroneCommand("DEFAULT", Command.takeoff()),
                          SingleDroneCommand("DEFAULT", Command.forward(10)),
                          SingleDroneCommand("DEFAULT", Command.land())]
     self.assertEqual(expected_commands, commands)
 def test_loops_in_function(self):
     commands = generate_commands("""
         procedure proc(int i) {
           while i < 10 {
             i <- i + 1;
           }
           forward(i);
         }
         main () {
           takeoff();
           proc(1);
           land();
         }
         """)
     expected_commands = [SingleDroneCommand("DEFAULT", Command.takeoff()),
                          SingleDroneCommand("DEFAULT", Command.forward(10)),
                          SingleDroneCommand("DEFAULT", Command.land())]
     self.assertEqual(expected_commands, commands)
예제 #30
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)