# TestOrbit.py # shotmanager # # Unit tests for the orbit smart shot. # # Created by Will Silva and Eric Liao on 1/19/2015. # Copyright (c) 2016 3D Robotics. # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. import orbit from orbit import * import shotManager from shotManager import ShotManager import unittest import mock from mock import call from mock import Mock from mock import MagicMock from mock import patch class TestShotInit(unittest.TestCase): def setUp(self): '''Create a mock vehicle object''' vehicle = mock.create_autospec(Vehicle) '''Create a mock shotManager object''' shotmgr = mock.create_autospec(ShotManager) shotmgr.getParam.return_value = 0 # so mock doesn't do lazy binds shotmgr.rcMgr = Mock(specs=['remapper']) '''Run the shot constructor''' self.shot = orbit.OrbitShot(vehicle, shotmgr) def testInit(self): '''Test that the shot initialized properly''' # vehicle object should be created (not None) self.assertNotEqual(self.shot.vehicle, None) # shotManager object should be created (not None) self.assertNotEqual(self.shot.shotmgr, None) # roi should be None self.assertEqual(self.shot.roi, None) # pathController should be None self.assertEqual(self.shot.pathController, None) # ticksPaddleCentered should be initialized to infinity self.assertEqual(self.shot.ticksPaddleCentered, float('inf')) # pathHandler should be None self.assertEqual(self.shot.pathHandler, None) # shotmgr.getParam should be called thrice # once for maxClimbRate and once for maxAlt and once for FENCE_ENABLE calls = [call("PILOT_VELZ_MAX", DEFAULT_PILOT_VELZ_MAX_VALUE), call("FENCE_ALT_MAX", DEFAULT_FENCE_ALT_MAX), call("FENCE_ENABLE", DEFAULT_FENCE_ENABLE)] self.shot.shotmgr.getParam.assert_has_calls(calls) class TestHandleRCs(unittest.TestCase): def setUp(self): #Create a mock vehicle object vehicle = mock.create_autospec(Vehicle) #Create a mock shotManager object shotmgr = mock.create_autospec(ShotManager) shotmgr.getParam.return_value = 0 # so mock doesn't do lazy binds shotmgr.rcMgr = Mock(specs=['remapper']) #Run the shot constructor self.shot = orbit.OrbitShot(vehicle, shotmgr) #set roi self.shot.roi = LocationGlobalRelative(37.873168,-122.302062, 0) #3DR #Mock the pathHandler object self.shot.pathHandler = mock.create_autospec(pathHandler.PathHandler) self.shot.pathHandler.cruiseSpeed = 0 #Mock the pathController object self.shot.pathController = mock.create_autospec(OrbitController) self.shot.pathController.move.return_value = (LocationGlobalRelative(37.873168,-122.302062, 0),Vector3(0,0,0)) #Neutral sticks throttle = 0.0 roll = 0.0 pitch = 0.0 yaw = 0.0 self.channels = [throttle, roll, pitch, yaw, 0.0, 0.0, 0.0, 0.0] def testNoROI(self): '''If not ROI is set then do NOT continue''' self.shot.roi = None self.shot.handleRCs(self.channels) assert not self.shot.pathController.called def testSetPositionMsg(self): '''Test that we're sending a lat,lon,alt/x,y,z vel to APM''' self.shot.handleRCs(self.channels) self.shot.vehicle.message_factory.set_position_target_global_int_encode.assert_called_with( 0, # time_boot_ms (not used) 0, 1, # target system, target component mavutil.mavlink.MAV_FRAME_GLOBAL_RELATIVE_ALT, # frame 0b0000110111000000, # type_mask - enable pos/vel 37.873168*1E7, -122.302062*1E7, 0, # x, y, z positions 0, 0, 0, # x, y, z velocity in m/s 0, 0, 0, # x, y, z acceleration (not used) 0, 0) # yaw, yaw_rate (not used) self.shot.vehicle.send_mavlink.assert_called_with(mock.ANY) def testCallsetROIAltitude(self): '''Tests that we're calling setROIAltitude() with correct channels''' self.channels[5] = 0.5 self.channels[7] = 0.75 self.shot.setROIAltitude = Mock() self.shot.handleRCs(self.channels) self.shot.setROIAltitude.assert_called_with(0.5,0.75) def testsetROIAltitudeMsg(self): '''Test that we're sending an roi lat,lon,alt to APM''' self.shot.handleRCs(self.channels) self.shot.vehicle.message_factory.command_long_encode.assert_called_with( 0, 1, # target system, target component mavutil.mavlink.MAV_CMD_DO_SET_ROI, #command 0, #confirmation 0, 0, 0, 0, #params 1-4 self.shot.roi.lat, self.shot.roi.lon, self.shot.roi.alt ) self.shot.vehicle.send_mavlink.assert_called_with(mock.ANY) class TestAddLocation(unittest.TestCase): def setUp(self): #Create a mock vehicle object vehicle = mock.create_autospec(Vehicle) #Create a mock shotManager object shotmgr = mock.create_autospec(ShotManager) shotmgr.appMgr = Mock() shotmgr.rcMgr = Mock(specs=['remapper']) #Run the shot constructor self.shot = orbit.OrbitShot(vehicle, shotmgr) #Mock initOrbitShot self.shot.initOrbitShot = Mock() @mock.patch('location_helpers.getDistanceFromPoints', return_value = 10) @mock.patch('location_helpers.calcAzimuthFromPoints', return_value = 45) def testCallingLocationHelperFunctions(self, location_helpers_calcAzimuthFromPoints, location_helpers_getDistanceFromPoints): '''Make sure all location_helpers functions are called''' self.shot.addLocation(LocationGlobalRelative(37.873168,-122.302062, 0)) location_helpers_getDistanceFromPoints.assert_called_with(self.shot.roi, self.shot.vehicle.location.global_relative_frame) location_helpers_calcAzimuthFromPoints.assert_called_with(self.shot.roi, self.shot.vehicle.location.global_relative_frame) @mock.patch('orbitController.OrbitController', return_value = mock.create_autospec(OrbitController)) def testCreatingPathController(self, OrbitController): '''Test that the pathController object is instantiated''' self.shot.addLocation(LocationGlobalRelative(37.873168,-122.302062, 0)) self.assertNotEqual(self.shot.pathController, None) self.shot.pathController.setOptions.assert_called_with(maxAlt = mock.ANY, maxClimbRate = mock.ANY) def testNoPreviouslysetROIAltitude(self): '''If no roi has been set previously, then call initOrbitShot()''' self.shot.roi = None self.shot.initOrbitShot = Mock() self.shot.addLocation(LocationGlobalRelative(37.873168,-122.302062, 0)) self.assertEqual(self.shot.roi.lat, 37.873168) self.assertEqual(self.shot.roi.lon, -122.302062) self.assertEqual(self.shot.roi.alt, 0) self.shot.initOrbitShot.assert_called_with() def testOverwriteROI(self): '''If an ROI is already set, overwrite it & call initOrbitShot()''' self.shot.roi = LocationGlobalRelative(37.873168,-122.302062, 0) self.shot.initOrbitShot = Mock() self.shot.addLocation(LocationGlobalRelative(37.873169,-122.302063, 5)) self.assertEqual(self.shot.roi.lat, 37.873169) self.assertEqual(self.shot.roi.lon, -122.302063) self.assertEqual(self.shot.roi.alt, 5) assert self.shot.initOrbitShot.called def testSendROIToApp(self): '''Send the added ROI to the app as confirmation''' self.shot.roi = LocationGlobalRelative(37.873168,-122.302062, 0) self.shot.addLocation(LocationGlobalRelative(37.873169,-122.302063, 5)) expectedPacket = struct.pack('