Exemple #1
0
    def test(self):
        truncateTable('outgoing_manual')
        dao = OutgoingManualDAO(defaultConfigPath())

        # see how it works on an empty table
        self.assertIsNone(dao.submitAllPendingTargets())

        # this will insert records for 2 different targets from 3 classifications:
        testIns = outgoing_manual()
        testIns.crop_id = 42
        testIns.shape = 'circle'
        testIns.background_color = 'white'
        testIns.alphanumeric = 'A'
        testIns.alphanumeric_color = 'black'
        dao.addClassification(testIns)

        testIns.crop_id = 43
        dao.addClassification(testIns)

        testIns.crop_id = 44
        testIns.alphanumeric = 'C'
        testIns.submitted = 'submitted'  # this wont work -> it should still be unsubmitted
        dao.addClassification(testIns)

        result = dao.submitAllPendingTargets()
        self.assertIsNotNone(result)
        self.assertEqual(len(result), 2)  # should have 2 targets
Exemple #2
0
    def post(self):

        # confirm that the X-Manual header was specified
        manual = checkXManual(request)

        prevId = -1
        if 'X-Crop-Id' in request.headers:
            prevId = request.headers.get('X-Crop-Id')
        else:
            abort(400, "Need to specify header 'X-Crop-Id'!")

        dao = OutgoingManualDAO(
            defaultConfigPath()) if manual else OutgoingAutonomousDAO(
                defaultConfigPath())

        outgoingIn = outgoing_manual(
            json=request.get_json()) if manual else outgoing_autonomous(
                json=request.get_json())
        outgoingIn.crop_id = prevId
        resultingId = dao.upsertClassification(outgoingIn)

        if resultingId == -1:
            return {
                'message':
                'Failed to insert classification into outgoing table'
            }, 500

        response = make_response(
            jsonify({
                'message': 'success!',
                'id': resultingId
            }))
        response.headers['X-Class-Id'] = resultingId
        return response
Exemple #3
0
    def test(self):
        testIns = outgoing_manual()
        testIns.crop_id = 42
        testIns.type = 'standard'
        testIns.orientation = 'NE'
        testIns.shape = 'star'
        testIns.background_color = 'blue'
        testIns.alphanumeric = 'A'
        testIns.alphanumeric_color = 'purple'
        testIns.latitude  = 40.11111
        testIns.longitude = -111.222222

        truncateTable('outgoing_manual')
        dao = OutgoingManualDAO(defaultConfigPath())

        id = dao.addClassification(testIns)
        self.assertNotEqual(id, -1)

        model = dao.getClassification(id)
        self.assertIsNotNone(model)

        classOut = dao.submitPendingTarget(model.target)
        self.assertIsNotNone(classOut)

        imgPath = os.path.dirname(os.path.realpath(__file__)) + '/assets/star.png'
        
        targetOut = submitted_target(outgoingManualOrAutonomous=classOut, autonomous_in=False)
        targetOut.crop_path = imgPath
        auvsiDao = AuvsiOdlcDao()
        auvsiDao.addTarget(targetOut)
Exemple #4
0
    def test(self):
        # insert some targets
        dao = OutgoingManualDAO(defaultConfigPath())

        truncateTable('outgoing_manual')
        # see what it does with an empty table:
        self.assertIsNone(dao.submitPendingTarget(1))

        testIns = outgoing_manual()
        testIns.crop_id = 42
        testIns.latitude = 40.111
        testIns.longitude = -111.111
        testIns.orientation = 'N'
        testIns.shape = 'circle'
        testIns.background_color = 'white'
        testIns.alphanumeric = 'A'
        testIns.alphanumeric_color = 'black'
        self.assertIsNot(dao.addClassification(testIns), -1)

        testIns.crop_id = 43
        testIns.latitude = 40.222
        testIns.longitude = -111.222
        testIns.orientation = 'NE'
        testIns.background_color = 'orange'
        self.assertIsNot(dao.addClassification(testIns), -1)

        testIns.crop_id = 44
        testIns.latitude = 40.333
        testIns.longitude = -111.333
        testIns.alphanumeric_color = 'white'
        resultingId = dao.addClassification(testIns)
        self.assertIsNot(resultingId, -1)

        classResult = dao.getClassification(resultingId)
        submissionResult = dao.submitPendingTarget(classResult.target)

        self.assertAlmostEqual(submissionResult.latitude, 40.222)
        self.assertAlmostEqual(submissionResult.longitude, -111.222)
        self.assertEqual(submissionResult.orientation, 'NE')
        self.assertEqual(submissionResult.background_color, 'orange')
        self.assertEqual(submissionResult.alphanumeric_color, 'black')
        self.assertEqual(submissionResult.alphanumeric, 'A')
        self.assertEqual(submissionResult.shape, 'circle')

        # make sure that when we submit another classification that belongs
        # to the same target that its submitted state automatically goes to
        # 'inherited_submission'
        testIns.crop_id = 45
        resultingId = dao.addClassification(testIns)
        self.assertNotEqual(resultingId, -1)
        classResult = dao.getClassification(resultingId)
        self.assertIsNotNone(classResult)
        self.assertEqual(classResult.submitted, 'inherited_submission')
Exemple #5
0
    def test(self):
        truncateTable('outgoing_manual')
        dao = OutgoingManualDAO(defaultConfigPath())

        testIns = outgoing_manual()
        testIns.crop_id = 42
        testIns.shape = 'circle'
        testIns.background_color = 'white'
        testIns.alphanumeric = 'A'
        testIns.alphanumeric_color = 'black'
        self.assertNotEqual(dao.addClassification(testIns), -1)

        # should now fail to insert a duplicate crop_id
        self.assertEqual(dao.addClassification(testIns), -1)
        self.assertIsNotNone(dao.getClassificationByUID(42))
Exemple #6
0
    def get(self, class_id):

        # confirm that the X-Manual header was specified
        manual = checkXManual(request)

        dao = OutgoingManualDAO(
            defaultConfigPath()) if manual else OutgoingAutonomousDAO(
                defaultConfigPath())
        result = dao.getClassification(class_id)
        if result is None:
            return {
                'message':
                'Failed to locate classification with id {}'.format(class_id)
            }, 404
        return jsonify(result.toDict())
Exemple #7
0
    def get(self):
        # confirm that the X-Manual header was specified
        manual = checkXManual(request)

        outgoingList = []
        dao = OutgoingManualDAO(
            defaultConfigPath()) if manual else OutgoingAutonomousDAO(
                defaultConfigPath())
        outgoingList = dao.getAll()

        if not outgoingList:
            return {'message': 'Outgoing table is empty!'}, 404

        exportable = [
            classification.toDict() for classification in outgoingList
        ]
        return jsonify(exportable)
Exemple #8
0
    def put(self, class_id):

        # confirm that the X-Manual header was specified
        manual = checkXManual(request)

        dao = OutgoingManualDAO(
            defaultConfigPath()) if manual else OutgoingAutonomousDAO(
                defaultConfigPath())
        result = dao.updateClassification(class_id, request.get_json())
        if result is None:
            return {
                'message':
                'No image with id {} found with a classification to update or your input was invalid (or was there a server error?)'
                .format(class_id)
            }, 404
        else:
            return jsonify(result.toDict())
    def run(self):

        # wait until we get our first gps coordinate
        # remember - the ros_handler code does not insert a gps record
        #           into the table until the gps has a fix
        haveGps = False
        print("waiting for gps")
        while not haveGps and not self._should_shutdown:
            # check for any entries by just getting all
            dao = IncomingGpsDAO(defaultConfigPath())
            results = dao.getAll()
            dao.close()
            if results is None:
                time.sleep(1)
            else:
                haveGps = True  # we've got something!

        print(
            "Have gps! Using the first coordinate as our ground station. Starting geolocation..."
        )

        # get the coordinates from the first recorded gps measurement
        # this will be the coordinates we use for the groundstation
        # in geolocation
        dao = IncomingGpsDAO(defaultConfigPath())
        groundstationGps = dao.getFirst()
        dao.close()

        # now we can run stuff
        geo = targetGeolocation(groundstationGps.lat, groundstationGps.lon)
        while not self._should_shutdown:

            # lets deal with manual classifications in the queue
            dao = OutgoingManualDAO(defaultConfigPath())
            classifications = dao.getUnlocatedClassifications()
            dao.close()

            if classifications is not None:
                for classification in classifications:
                    self.processManualGeolocation(geo, classification)

            # now lets do autonomous
            dao = OutgoingAutonomousDAO(defaultConfigPath())
            classifications = dao.getUnlocatedClassifications()
            dao.close()

            if classifications is not None:
                for classification in classifications:
                    self.processAutonomousGeolocation(geo, classification)

            time.sleep(1)
Exemple #10
0
    def test(self):
        # insert some targets
        dao = OutgoingManualDAO(defaultConfigPath())

        truncateTable('outgoing_manual')

        # make sure if fails when we try and remove on empty table:
        deleteResult = dao.removeClassification(100)
        self.assertFalse(deleteResult)

        testIns = outgoing_manual()
        testIns.crop_id = 42
        testIns.latitude = 40.111
        testIns.longitude = -111.111
        testIns.orientation = 'N'
        testIns.shape = 'circle'
        testIns.background_color = 'white'
        testIns.alphanumeric = 'A'
        testIns.alphanumeric_color = 'black'
        resultingId = dao.addClassification(testIns)
        self.assertIsNot(resultingId, -1)

        testIns.crop_id = 44
        otherId = dao.addClassification(testIns)
        self.assertNotEqual(otherId, -1)

        # make sure it doesn't delete everything:
        deleteResult = dao.removeClassification(
            otherId + 5)  # give bogus id that should fail
        self.assertFalse(deleteResult)
        self.assertEqual(len(dao.getAll()),
                         2)  # make sure there's still 2 records

        deleteResult = dao.removeClassification(resultingId)
        self.assertTrue(deleteResult)
        self.assertEqual(len(dao.getAll()), 1)  # should still be 1 record left
        self.assertIsNotNone(dao.getClassification(
            otherId))  # make sure the otherId wasn't deleted on accident
Exemple #11
0
    def delete(self, class_id):

        # confirm that the X-Manual header was specified
        manual = checkXManual(request)

        dao = OutgoingManualDAO(
            defaultConfigPath()) if manual else OutgoingAutonomousDAO(
                defaultConfigPath())

        if dao.getClassification(class_id) is None:
            return {
                'message':
                'Couldnt find classification with id {}'.format(class_id)
            }, 404

        result = dao.removeClassification(class_id)
        if not result:
            return {
                'message':
                'Something went wrong while trying to delete id {} (was it delete by someone else first??)'
                .format(class_id)
            }, 500

        return {'message': 'success!', 'id': class_id}
Exemple #12
0
    def test(self):
        truncateTable('outgoing_manual')

        dao = OutgoingManualDAO(defaultConfigPath())

        testIns = outgoing_manual()
        testIns.crop_id = 42
        testIns.shape = 'circle'
        testIns.background_color = 'white'
        testIns.alphanumeric = 'A'
        testIns.alphanumeric_color = 'black'

        resultingId = dao.addClassification(testIns)
        self.assertNotEqual(resultingId, -1)
        insResult = dao.getClassification(resultingId)
        self.assertIsNotNone(insResult.target)
        self.assertNotEqual(insResult.target, -1)

        testIns.crop_id = 43
        resultingId = dao.addClassification(testIns)
        self.assertNotEqual(resultingId, -1)
        insResult2 = dao.getClassification(resultingId)
        self.assertEqual(insResult.target, insResult2.target)

        testIns.crop_id = 44
        testIns.alphanumeric = 'C'
        testIns.submitted = 'submitted'  # this wont work -> it should still be unsubmitted
        resultingId = dao.addClassification(testIns)
        self.assertNotEqual(resultingId, -1)
        insResult3 = dao.getClassification(resultingId)
        self.assertNotEqual(insResult3.target, insResult2.target)

        # the target id should change on this update
        testIns.crop_id = 42
        testIns.alphanumeric = 'C'
        testIns.submitted = 'unsubmitted'
        result = dao.updateClassificationByUID(testIns.crop_id,
                                               testIns.toDict())
        self.assertNotEqual(result.class_id, -1)
        self.assertEqual(result.target, insResult3.target)
    def processManualGeolocation(self, geolocator, classification):
        """
        Process an unlocated manual classification waiting in the queue. Basically
        this involves getting a bunch of information from a lot of the other database
        tables, and then using it as input to the actual geolocation algorithm.
        If successful, this will update the given classification with the calculated
        coordinates. Here's what we use:

            cropped_manual -> image_id, crop_coordinates
            incoming_image -> image timestamp
            incoming_gps   -> mav gps coordinates at incoming_image timestamp
            incoming_gps   -> mav state info at incoming_image timestamp

        @type geolocator: targetGeolocation
        @param geolocator: An instance of the targetGeolocation class, already 
            initialized
        
        @type classification: outgoing_manual
        @param classification: A manual classification that has no geolocation 
            coordinates yet.
        """

        # now get all the info about gps, state and crop
        # as we do this we need to check that we actually get
        # data back from our queries. if we dont, then just
        # skip this classification
        dao = CroppedManualDAO(defaultConfigPath())
        croppedImg = dao.getImage(classification.crop_id)
        dao.close()
        if croppedImg is None:
            print(
                "Failed to find cropped image {} for manual classification {}!"
                .format(classification.crop_id, classification.class_id))
            return

        updateDict = self.processGeolocation(geolocator, classification,
                                             croppedImg)

        dao = OutgoingManualDAO(defaultConfigPath())
        dao.updateClassification(classification.class_id, updateDict)
        dao.close()
Exemple #14
0
    def test(self):
        truncateTable('outgoing_manual')
        dao = OutgoingManualDAO(defaultConfigPath())

        # empty table
        self.assertIsNone(dao.getUnlocatedClassifications())

        # populate with two classifications that need geo, one that doesnt
        testIns = outgoing_manual()
        testIns.crop_id = 42
        testIns.shape = 'circle'
        testIns.background_color = 'white'
        testIns.alphanumeric = 'A'
        testIns.alphanumeric_color = 'black'

        resultingId = dao.addClassification(testIns)
        self.assertNotEqual(resultingId, -1)

        testIns.crop_id = 43
        testIns.background_color = 'orange'
        resultingId2 = dao.addClassification(testIns)
        self.assertNotEqual(resultingId2, -1)

        testIns.crop_id = 44
        testIns.latitude = 40.111
        testIns.longitude = -111.222
        resultingId3 = dao.addClassification(testIns)
        self.assertNotEqual(resultingId3, -1)

        unlocated = dao.getUnlocatedClassifications()
        self.assertIsNotNone(unlocated)
        self.assertEqual(len(unlocated), 2)
        # the two models in the list should be our first two inserts and have
        # crop ids 42 and 43
        self.assertLess(unlocated[0].crop_id, 44)
        self.assertLess(unlocated[1].crop_id, 44)
Exemple #15
0
def getClassificationDAO(isManual):
    if isManual:
        return OutgoingManualDAO(defaultConfigPath())
    else:
        return OutgoingAutonomousDAO(defaultConfigPath())
Exemple #16
0
    def test(self):
        truncateTable('cropped_manual')
        truncateTable('incoming_image')
        truncateTable('outgoing_manual')
        dao = OutgoingManualDAO(defaultConfigPath())

        testIns = outgoing_manual()
        testIns.crop_id = 42
        testIns.shape = 'circle'
        testIns.background_color = 'white'
        testIns.alphanumeric = 'A'
        testIns.alphanumeric_color = 'black'
        self.assertNotEqual(dao.addClassification(testIns), -1)

        dao = CroppedManualDAO(defaultConfigPath())
        model = cropped_manual()
        model.image_id = 123
        model.time_stamp = 1547453775.2
        model.cropped_path = '/im/a/totally/real/cropped/path/i/swear.jpg'
        model.crop_coordinate_br = "(12, 34)"
        model.crop_coordinate_tl = "(56, 78)"
        self.assertNotEqual(dao.addImage(model), -1)

        dao = IncomingImageDAO(defaultConfigPath())
        model = incoming_image()
        model.time_stamp = 1547453775.2
        model.focal_length = 16.0
        model.image_path = '/im/a/totally/real/path/i/swear.jpg'
        model.manual_tap = True
        model.autonomous_tap = False
        resultingId = dao.addImage(model)
        self.assertNotEqual(resultingId, -1)

        util = UtilDAO(defaultConfigPath())
        util.resetManualDB()

        resultingModel = dao.getImage(resultingId)
        self.assertIsNotNone(resultingModel)
        self.assertFalse(resultingModel.manual_tap)
        self.assertEqual(resultingModel.image_path, model.image_path)
        self.assertEqual(resultingModel.focal_length, model.focal_length)

        dao = CroppedManualDAO(defaultConfigPath())
        self.assertEqual(len(dao.getAll()), 0)

        dao = OutgoingManualDAO(defaultConfigPath())
        self.assertEqual(len(dao.getAll()), 0)
Exemple #17
0
    def test(self):
        toAvg = [[0, 1.0], [1, 1.1], [2, 1.4]]

        dao = OutgoingManualDAO(defaultConfigPath())
        self.assertAlmostEqual(dao.calcClmnAvg(toAvg, 1), 1.166666667)
Exemple #18
0
    def test(self):
        truncateTable('outgoing_manual')
        dao = OutgoingManualDAO(defaultConfigPath())

        # at this point we should've already passed a bunch of tests
        # relating to target submission above, so we can just test the
        # classification specification feature here

        testIns = outgoing_manual()
        testIns.crop_id = 42
        testIns.latitude = 40.111
        testIns.longitude = -111.111
        testIns.orientation = 'N'
        testIns.shape = 'circle'
        testIns.background_color = 'white'
        testIns.alphanumeric = 'A'
        testIns.alphanumeric_color = 'black'
        firstClass = dao.addClassification(testIns)
        self.assertNotEqual(firstClass, -1)

        testIns.crop_id = 43
        testIns.latitude = 40.222
        testIns.longitude = -111.222
        testIns.orientation = 'NE'
        testIns.background_color = 'orange'
        secondClass = dao.addClassification(testIns)
        self.assertNotEqual(secondClass, -1)

        testIns.crop_id = 44
        testIns.latitude = 40.333
        testIns.longitude = -111.333
        testIns.alphanumeric_color = 'white'
        thirdClass = dao.addClassification(testIns)
        self.assertNotEqual(thirdClass, -1)

        specs = {
            'orientation': secondClass,
            'crop_id': firstClass,
            'alphanumeric_color': thirdClass
        }

        classResult = dao.getClassification(secondClass)
        submissionResult = dao.submitPendingTarget(classResult.target, specs)

        self.assertIsNotNone(submissionResult)

        self.assertEqual(submissionResult.orientation, 'NE')
        self.assertEqual(submissionResult.crop_id, 42)
        self.assertEqual(submissionResult.alphanumeric_color, 'white')
        self.assertEqual(submissionResult.background_color, 'orange')
        self.assertEqual(submissionResult.alphanumeric, 'A')

        truncateTable('outgoing_manual')
        ############################################
        # test what happens when we put garbage in specs:
        ############################################
        testIns = outgoing_manual()
        testIns.crop_id = 42
        testIns.latitude = 40.111
        testIns.longitude = -111.111
        testIns.orientation = 'S'
        testIns.shape = 'circle'
        testIns.background_color = 'white'
        testIns.alphanumeric = 'Q'
        testIns.alphanumeric_color = 'black'
        self.assertNotEqual(dao.addClassification(testIns), -1)

        testIns.crop_id = 43
        testIns.latitude = 40.222
        testIns.longitude = -111.222
        testIns.orientation = 'W'
        testIns.background_color = 'orange'
        secondClass = dao.addClassification(testIns)
        self.assertNotEqual(secondClass, -1)

        testIns.crop_id = 44
        testIns.latitude = 40.333
        testIns.longitude = -111.333
        testIns.alphanumeric_color = 'white'
        self.assertNotEqual(dao.addClassification(testIns), -1)

        specs = {
            'orientation': secondClass,
            'crop_id': None,
            'alphanumeric_color': 'wasdf'
        }

        classResult = dao.getClassification(secondClass)
        submissionResult = dao.submitPendingTarget(classResult.target, specs)

        # Even though we fed a bunch of garbage in specs, submission should
        # still succeed, defaulting to most common value, for the garbage stuff
        self.assertIsNotNone(submissionResult)

        self.assertEqual(submissionResult.orientation, 'W')
        self.assertEqual(submissionResult.alphanumeric_color, 'black')
        self.assertEqual(submissionResult.background_color, 'orange')
        self.assertEqual(submissionResult.alphanumeric, 'Q')
Exemple #19
0
    def test(self):
        toMostCommon = [[0, 'A'], [1, 'B'], [3, 'B'], [4, 'C']]
        dao = OutgoingManualDAO(defaultConfigPath())

        self.assertEqual(dao.findMostCommonValue(toMostCommon, 1), 'B')
        self.assertIsNone(dao.findMostCommonValue([[0, None], [1, None]], 1))
Exemple #20
0
 def test(self):
     dao = OutgoingManualDAO(defaultConfigPath())
     self.assertIsNotNone(dao)
     self.assertIsNotNone(dao.conn)