├── ReadmeResources ├── Gesture1.gif ├── Gesture2.gif └── Gesture3.gif ├── .gitmodules ├── GRTiOSFramework ├── GRTiOS.xcodeproj │ └── project.xcworkspace │ │ └── contents.xcworkspacedata ├── BridgingHeader.h ├── VectorDouble.h ├── VectorFloat.h ├── GRTiOSFramework │ ├── GRTiOS.h │ └── Info.plist ├── GRTiOSFrameworkTests │ ├── Info.plist │ └── GRTiOSFrameworkTests.swift ├── GestureRecognitionPipeline.h ├── VectorDouble.mm ├── VectorFloat.mm └── GestureRecognitionPipeline.mm ├── GRT-iOS-HelloWorld ├── GRT-iOS-HelloWorld.xcodeproj │ ├── project.xcworkspace │ │ └── contents.xcworkspacedata │ └── project.pbxproj ├── GRT-iOS-HelloWorld-Bridging-Header.h ├── GRT-iOS-HelloWorldTests │ ├── Info.plist │ └── GRT_iOS_HelloWorldTests.swift ├── GRT-iOS-HelloWorldUITests │ ├── Info.plist │ └── GRT_iOS_HelloWorldUITests.swift ├── AcceleremoterManager.swift └── GRT-iOS-HelloWorld │ ├── Info.plist │ ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard │ ├── Assets.xcassets │ └── AppIcon.appiconset │ │ └── Contents.json │ ├── AppDelegate.swift │ ├── TrainingViewController.swift │ └── PredictionViewController.swift ├── GRT-HelloWorld.xcworkspace └── contents.xcworkspacedata ├── .gitignore └── README.md /ReadmeResources/Gesture1.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narner/GRT-iOS-HelloWorld/HEAD/ReadmeResources/Gesture1.gif -------------------------------------------------------------------------------- /ReadmeResources/Gesture2.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narner/GRT-iOS-HelloWorld/HEAD/ReadmeResources/Gesture2.gif -------------------------------------------------------------------------------- /ReadmeResources/Gesture3.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/narner/GRT-iOS-HelloWorld/HEAD/ReadmeResources/Gesture3.gif -------------------------------------------------------------------------------- /.gitmodules: -------------------------------------------------------------------------------- 1 | [submodule "grt"] 2 | path = grt 3 | url = https://github.com/nickgillian/grt.git 4 | [submodule "SwiftR"] 5 | path = SwiftR 6 | url = https://github.com/kalanyuz/SwiftR.git 7 | -------------------------------------------------------------------------------- /GRTiOSFramework/GRTiOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /GRT-iOS-HelloWorld/GRT-iOS-HelloWorld.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /GRTiOSFramework/BridgingHeader.h: -------------------------------------------------------------------------------- 1 | // 2 | // BridgingHeader.h 3 | // grt 4 | // 5 | // Created by mjahnen on 18/11/15. 6 | // Copyright © 2015 jahnen. All rights reserved. 7 | // 8 | 9 | #ifndef BridgingHeader_h 10 | #define BridgingHeader_h 11 | 12 | #import "GestureRecognitionPipeline.h" 13 | 14 | 15 | #endif /* BridgingHeader_h */ 16 | -------------------------------------------------------------------------------- /GRT-iOS-HelloWorld/GRT-iOS-HelloWorld-Bridging-Header.h: -------------------------------------------------------------------------------- 1 | // 2 | // GRT-iOS-HelloWorld-Bridging-Header.h 3 | // GRT-iOS-HelloWorld 4 | // 5 | // Created by Nicholas Arner on 8/17/17. 6 | // Copyright © 2017 Nicholas Arner. All rights reserved. 7 | // 8 | 9 | #ifndef GRT_iOS_HelloWorld_Bridging_Header_h 10 | #define GRT_iOS_HelloWorld_Bridging_Header_h 11 | 12 | #import 13 | 14 | #endif /* GRT_iOS_HelloWorld_Bridging_Header_h */ 15 | -------------------------------------------------------------------------------- /GRTiOSFramework/VectorDouble.h: -------------------------------------------------------------------------------- 1 | // 2 | // VectorDouble.h 3 | // grt 4 | // 5 | // Created by M J on 09/12/15. 6 | // Copyright © 2015 jahnen. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface VectorDouble : NSObject 12 | 13 | - (instancetype)initWithSize:(NSInteger) size; 14 | 15 | - (void)pushBack:(double)value; 16 | - (void)clear; 17 | 18 | #ifdef __cplusplus 19 | - (GRT::VectorDouble *)cppInstance; 20 | #endif 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /GRTiOSFramework/VectorFloat.h: -------------------------------------------------------------------------------- 1 | // 2 | // VectorFloat.h 3 | // GRTiOS 4 | // 5 | // Created by Nicholas Arner on 8/22/17. 6 | // Copyright © 2017 Nicholas Arner. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface VectorFloat : NSObject 12 | 13 | - (instancetype)initWithSize:(NSInteger) size; 14 | 15 | - (void)pushBack:(double)value; 16 | - (void)clear; 17 | 18 | #ifdef __cplusplus 19 | - (GRT::VectorFloat *)cppInstance; 20 | #endif 21 | 22 | @end 23 | -------------------------------------------------------------------------------- /GRT-HelloWorld.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 9 | 10 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /GRTiOSFramework/GRTiOSFramework/GRTiOS.h: -------------------------------------------------------------------------------- 1 | // 2 | // GRTiOS.h 3 | // GRTiOS 4 | // 5 | // Created by Nicholas Arner on 8/16/17. 6 | // Copyright © 2017 Nicholas Arner. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | 12 | //! Project version number for GRTiOSFramework. 13 | FOUNDATION_EXPORT double GRTiOSFrameworkVersionNumber; 14 | 15 | //! Project version string for GRTiOSFramework. 16 | FOUNDATION_EXPORT const unsigned char GRTiOSFrameworkVersionString[]; 17 | 18 | 19 | 20 | 21 | 22 | -------------------------------------------------------------------------------- /GRTiOSFramework/GRTiOSFrameworkTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /GRT-iOS-HelloWorld/GRT-iOS-HelloWorldTests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /GRT-iOS-HelloWorld/GRT-iOS-HelloWorldUITests/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | BNDL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | 22 | 23 | -------------------------------------------------------------------------------- /GRTiOSFramework/GRTiOSFramework/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | FMWK 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | $(CURRENT_PROJECT_VERSION) 21 | NSPrincipalClass 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /GRTiOSFramework/GestureRecognitionPipeline.h: -------------------------------------------------------------------------------- 1 | // 2 | // GestureRecognitionPipeline.h 3 | // grt 4 | // 5 | // Created by mjahnen on 25/11/15. 6 | // Copyright © 2015 jahnen. All rights reserved. 7 | // Modified by Nick Arner, 2017 8 | // 9 | 10 | #import 11 | #import "VectorDouble.h" 12 | #import "VectorFloat.h" 13 | 14 | @interface GestureRecognitionPipeline : NSObject 15 | 16 | @property (readonly, getter = predictedClassLabel) NSUInteger predictedClassLabel; 17 | @property (readonly, getter = maximumLikelihood) double maximumLikelihood; 18 | 19 | - (BOOL)savePipeline:(NSURL *)url; 20 | - (BOOL)loadPipeline:(NSURL *)url; 21 | - (BOOL)saveClassificationData:(NSURL *)url; 22 | - (BOOL)loadClassificationData:(NSURL *)url; 23 | - (BOOL)setClassifier:(NSString *)classifier; 24 | - (BOOL)predict:(VectorDouble *)inputVector; 25 | - (void)addSamplesToClassificationDataForGesture:(NSUInteger)gesture :(VectorFloat*)vectorData; 26 | - (BOOL)trainPipeline; 27 | 28 | @end 29 | -------------------------------------------------------------------------------- /GRTiOSFramework/VectorDouble.mm: -------------------------------------------------------------------------------- 1 | // 2 | // VectorDouble.m 3 | // grt 4 | // 5 | // Created by M J on 09/12/15. 6 | // Copyright © 2015 jahnen. All rights reserved. 7 | // 8 | 9 | #ifdef __cplusplus 10 | #include "grt.h" 11 | #endif 12 | 13 | #import "VectorDouble.h" 14 | 15 | @interface VectorDouble() 16 | @property GRT::VectorDouble *instance; 17 | @end 18 | 19 | @implementation VectorDouble 20 | 21 | - (instancetype)init 22 | { 23 | self = [super init]; 24 | if (self) { 25 | self.instance = new GRT::VectorDouble; 26 | } 27 | return self; 28 | } 29 | 30 | - (instancetype)initWithSize:(NSInteger) size 31 | { 32 | self = [super init]; 33 | if (self) { 34 | self.instance = new GRT::VectorDouble(size); 35 | } 36 | return self; 37 | } 38 | 39 | - (void)dealloc 40 | { 41 | delete self.instance; 42 | } 43 | 44 | - (void)pushBack:(double) value 45 | { 46 | self.instance->push_back(value); 47 | } 48 | 49 | - (void)clear 50 | { 51 | self.instance->clear(); 52 | } 53 | 54 | - (GRT::VectorDouble *)cppInstance 55 | { 56 | return self.instance; 57 | } 58 | 59 | @end 60 | -------------------------------------------------------------------------------- /GRTiOSFramework/VectorFloat.mm: -------------------------------------------------------------------------------- 1 | // 2 | // VectorFloat.m 3 | // GRTiOS 4 | // 5 | // Created by Nicholas Arner on 8/22/17. 6 | // Copyright © 2017 Nicholas Arner. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #ifdef __cplusplus 12 | #include "grt.h" 13 | #endif 14 | 15 | #import "VectorFloat.h" 16 | 17 | @interface VectorFloat() 18 | @property GRT::VectorFloat *instance; 19 | @end 20 | 21 | @implementation VectorFloat 22 | 23 | - (instancetype)init 24 | { 25 | self = [super init]; 26 | if (self) { 27 | self.instance = new GRT::VectorFloat; 28 | } 29 | return self; 30 | } 31 | 32 | - (instancetype)initWithSize:(NSInteger) size 33 | { 34 | self = [super init]; 35 | if (self) { 36 | self.instance = new GRT::VectorFloat(size); 37 | } 38 | return self; 39 | } 40 | 41 | - (void)dealloc 42 | { 43 | delete self.instance; 44 | } 45 | 46 | - (void)pushBack:(double) value 47 | { 48 | self.instance->push_back(value); 49 | } 50 | 51 | - (void)clear 52 | { 53 | self.instance->clear(); 54 | } 55 | 56 | - (GRT::VectorFloat *)cppInstance 57 | { 58 | return self.instance; 59 | } 60 | 61 | @end 62 | -------------------------------------------------------------------------------- /GRTiOSFramework/GRTiOSFrameworkTests/GRTiOSFrameworkTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GRTiOSFrameworkTests.swift 3 | // GRTiOSFrameworkTests 4 | // 5 | // Created by Nicholas Arner on 8/16/17. 6 | // Copyright © 2017 Nicholas Arner. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import GRTiOSFramework 11 | 12 | class GRTiOSFrameworkTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measure { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /GRT-iOS-HelloWorld/GRT-iOS-HelloWorldTests/GRT_iOS_HelloWorldTests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GRT_iOS_HelloWorldTests.swift 3 | // GRT-iOS-HelloWorldTests 4 | // 5 | // Created by Nicholas Arner on 8/17/17. 6 | // Copyright © 2017 Nicholas Arner. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | @testable import GRT_iOS_HelloWorld 11 | 12 | class GRT_iOS_HelloWorldTests: XCTestCase { 13 | 14 | override func setUp() { 15 | super.setUp() 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | } 18 | 19 | override func tearDown() { 20 | // Put teardown code here. This method is called after the invocation of each test method in the class. 21 | super.tearDown() 22 | } 23 | 24 | func testExample() { 25 | // This is an example of a functional test case. 26 | // Use XCTAssert and related functions to verify your tests produce the correct results. 27 | } 28 | 29 | func testPerformanceExample() { 30 | // This is an example of a performance test case. 31 | self.measure { 32 | // Put the code you want to measure the time of here. 33 | } 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /GRT-iOS-HelloWorld/AcceleremoterManager.swift: -------------------------------------------------------------------------------- 1 | // 2 | // CoreMotionManager.swift 3 | // WatchGRT 4 | // 5 | // Created by M J on 02/12/15. 6 | // Copyright © 2015 jahnen. All rights reserved. 7 | // Modified by Nick Arner 8 | // 9 | 10 | import Foundation 11 | import CoreMotion 12 | 13 | class AccelerometerManager { 14 | private let motionManager = CMMotionManager() 15 | private let motionQueue = OperationQueue() 16 | 17 | init() { 18 | motionQueue.name = "CoreMotion" 19 | 20 | motionManager.accelerometerUpdateInterval = 1/60.0 21 | } 22 | 23 | func start(accHandler: @escaping (_ x: Double, _ y: Double, _ z: Double) -> Void) { 24 | let handler: CMAccelerometerHandler = {(data: CMAccelerometerData?, error: Error?) -> Void in 25 | guard let acceleration = data?.acceleration else { 26 | print("Error: data is nil: \(String(describing: error))") 27 | return 28 | } 29 | 30 | accHandler(acceleration.x, acceleration.y, acceleration.z) 31 | } 32 | motionManager.startAccelerometerUpdates(to: motionQueue, withHandler: handler) 33 | } 34 | 35 | func stop() { 36 | motionManager.stopAccelerometerUpdates() 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /GRT-iOS-HelloWorld/GRT-iOS-HelloWorldUITests/GRT_iOS_HelloWorldUITests.swift: -------------------------------------------------------------------------------- 1 | // 2 | // GRT_iOS_HelloWorldUITests.swift 3 | // GRT-iOS-HelloWorldUITests 4 | // 5 | // Created by Nicholas Arner on 8/17/17. 6 | // Copyright © 2017 Nicholas Arner. All rights reserved. 7 | // 8 | 9 | import XCTest 10 | 11 | class GRT_iOS_HelloWorldUITests: XCTestCase { 12 | 13 | override func setUp() { 14 | super.setUp() 15 | 16 | // Put setup code here. This method is called before the invocation of each test method in the class. 17 | 18 | // In UI tests it is usually best to stop immediately when a failure occurs. 19 | continueAfterFailure = false 20 | // UI tests must launch the application that they test. Doing this in setup will make sure it happens for each test method. 21 | XCUIApplication().launch() 22 | 23 | // In UI tests it’s important to set the initial state - such as interface orientation - required for your tests before they run. The setUp method is a good place to do this. 24 | } 25 | 26 | override func tearDown() { 27 | // Put teardown code here. This method is called after the invocation of each test method in the class. 28 | super.tearDown() 29 | } 30 | 31 | func testExample() { 32 | // Use recording to get started writing UI tests. 33 | // Use XCTAssert and related functions to verify your tests produce the correct results. 34 | } 35 | 36 | } 37 | -------------------------------------------------------------------------------- /GRT-iOS-HelloWorld/GRT-iOS-HelloWorld/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleExecutable 8 | $(EXECUTABLE_NAME) 9 | CFBundleIdentifier 10 | $(PRODUCT_BUNDLE_IDENTIFIER) 11 | CFBundleInfoDictionaryVersion 12 | 6.0 13 | CFBundleName 14 | $(PRODUCT_NAME) 15 | CFBundlePackageType 16 | APPL 17 | CFBundleShortVersionString 18 | 1.0 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | UILaunchStoryboardName 24 | LaunchScreen 25 | UIMainStoryboardFile 26 | Main 27 | UIRequiredDeviceCapabilities 28 | 29 | armv7 30 | 31 | UISupportedInterfaceOrientations 32 | 33 | UIInterfaceOrientationPortrait 34 | 35 | UISupportedInterfaceOrientations~ipad 36 | 37 | UIInterfaceOrientationPortrait 38 | UIInterfaceOrientationPortraitUpsideDown 39 | UIInterfaceOrientationLandscapeLeft 40 | UIInterfaceOrientationLandscapeRight 41 | 42 | 43 | 44 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Xcode 2 | # 3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore 4 | 5 | ## Build generated 6 | build/ 7 | DerivedData/ 8 | 9 | ## Various settings 10 | *.pbxuser 11 | !default.pbxuser 12 | *.mode1v3 13 | !default.mode1v3 14 | *.mode2v3 15 | !default.mode2v3 16 | *.perspectivev3 17 | !default.perspectivev3 18 | xcuserdata/ 19 | 20 | ## Other 21 | *.moved-aside 22 | *.xccheckout 23 | *.xcscmblueprint 24 | 25 | ## Obj-C/Swift specific 26 | *.hmap 27 | *.ipa 28 | *.dSYM.zip 29 | *.dSYM 30 | 31 | # CocoaPods 32 | # 33 | # We recommend against adding the Pods directory to your .gitignore. However 34 | # you should judge for yourself, the pros and cons are mentioned at: 35 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control 36 | # 37 | # Pods/ 38 | 39 | # Carthage 40 | # 41 | # Add this line if you want to avoid checking in source code from Carthage dependencies. 42 | # Carthage/Checkouts 43 | 44 | Carthage/Build 45 | 46 | # fastlane 47 | # 48 | # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the 49 | # screenshots whenever they are needed. 50 | # For more information about the recommended setup visit: 51 | # https://docs.fastlane.tools/best-practices/source-control/#source-control 52 | 53 | fastlane/report.xml 54 | fastlane/Preview.html 55 | fastlane/screenshots 56 | fastlane/test_output 57 | 58 | # Code Injection 59 | # 60 | # After new code Injection tools there's a generated folder /iOSInjectionProject 61 | # https://github.com/johnno1962/injectionforxcode 62 | 63 | iOSInjectionProject/ 64 | -------------------------------------------------------------------------------- /GRT-iOS-HelloWorld/GRT-iOS-HelloWorld/Base.lproj/LaunchScreen.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # GRT-iOS-HelloWorld 2 | An example of how to integrate the Gesture Recognition Toolkit into an 3 | iPhone app 4 | 5 | 6 | The [Gesture Recognition Toolkit](https://github.com/nickgillian/grt) is a "cross-platform, open-source, C++ machine learning library 7 | designed for real-time gesture recognition". This repository contains the project outlined in my blog posts, [Integrating the GRT into an 8 | iPhone app](https://nickarner.com/notes/integrating-the-grt-into-an-iphone-project-august-29-2017/) and [Machine-Learning powered Gesture Recognition on iOS](https://nickarner.com/notes/machine-learning-powered-gesture-recognition-on-ios-october-7-2017/). 9 | 10 | Here are some of the gestures I was able to train the system to 11 | recognize: 12 | 13 | ![Alt Text](https://github.com/narner/GRT-iOS-HelloWorld/raw/master/ReadmeResources/Gesture1.gif) 14 | 15 | ![Alt Text](https://github.com/narner/GRT-iOS-HelloWorld/raw/master/ReadmeResources/Gesture2.gif) 16 | 17 | ![Alt Text](https://github.com/narner/GRT-iOS-HelloWorld/raw/master/ReadmeResources/Gesture3.gif) 18 | 19 | [SwiftR](https://github.com/kalanyuz/SwiftR) is used for visualizing 20 | the acellerometer data. 21 | 22 | 23 | ## NOTE: 24 | Since I worked on this project, there's been a lot of advancemenrts in [Apple's CoreML framework](https://developer.apple.com/documentation/coreml), including the ability to [create Motion Activity Classifiers using CreateML](https://developer.apple.com/videos/play/wwdc2019/426/). If you're looking to create a gestural recognition system for iOS from scratch, I would recommend taking a look at the linked Apple talk. 25 | 26 | Additional resources: 27 | * [Activity Classification with Create ML, CoreML3, and Skafos: Part 1](https://medium.com/skafosai/activity-classification-with-create-ml-coreml3-and-skafos-part-1-8f130b5701f6) 28 | 29 | * [GestureAI-CoreML-iOS](https://github.com/akimach/GestureAI-CoreML-iOS) 30 | -------------------------------------------------------------------------------- /GRT-iOS-HelloWorld/GRT-iOS-HelloWorld/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "20x20", 6 | "scale" : "2x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "20x20", 11 | "scale" : "3x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "2x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "29x29", 21 | "scale" : "3x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "2x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "40x40", 31 | "scale" : "3x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "60x60", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "3x" 42 | }, 43 | { 44 | "idiom" : "ipad", 45 | "size" : "20x20", 46 | "scale" : "1x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "20x20", 51 | "scale" : "2x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "1x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "29x29", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "1x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "40x40", 71 | "scale" : "2x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "76x76", 76 | "scale" : "1x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "76x76", 81 | "scale" : "2x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "83.5x83.5", 86 | "scale" : "2x" 87 | } 88 | ], 89 | "info" : { 90 | "version" : 1, 91 | "author" : "xcode" 92 | } 93 | } -------------------------------------------------------------------------------- /GRT-iOS-HelloWorld/GRT-iOS-HelloWorld/AppDelegate.swift: -------------------------------------------------------------------------------- 1 | // 2 | // AppDelegate.swift 3 | // GRT-iOS-HelloWorld 4 | // 5 | // Created by Nicholas Arner on 8/17/17. 6 | // Copyright © 2017 Nicholas Arner. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | 11 | @UIApplicationMain 12 | class AppDelegate: UIResponder, UIApplicationDelegate { 13 | 14 | var window: UIWindow? 15 | var pipeline: GestureRecognitionPipeline? 16 | 17 | func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { 18 | 19 | //Create an instance of a gesture recognition pipeline to be used as a global variable, accesible by both our training and prediction view controllers 20 | self.pipeline = GestureRecognitionPipeline() 21 | 22 | return true 23 | } 24 | 25 | func applicationWillResignActive(_ application: UIApplication) { 26 | // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 27 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 28 | } 29 | 30 | func applicationDidEnterBackground(_ application: UIApplication) { 31 | // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 32 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 33 | } 34 | 35 | func applicationWillEnterForeground(_ application: UIApplication) { 36 | // Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background. 37 | } 38 | 39 | func applicationDidBecomeActive(_ application: UIApplication) { 40 | // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 41 | } 42 | 43 | func applicationWillTerminate(_ application: UIApplication) { 44 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 45 | } 46 | 47 | 48 | } 49 | 50 | -------------------------------------------------------------------------------- /GRT-iOS-HelloWorld/GRT-iOS-HelloWorld/TrainingViewController.swift: -------------------------------------------------------------------------------- 1 | // 2 | // TrainingViewController.swift 3 | // GRT-iOS-HelloWorld 4 | // 5 | // Created by Nicholas Arner on 8/17/17. 6 | // Copyright © 2017 Nicholas Arner. All rights reserved. 7 | // 8 | 9 | import UIKit 10 | import GRTiOS 11 | import SwiftR 12 | 13 | class TrainingViewController: UIViewController { 14 | 15 | @IBOutlet var gestureSelector: UISegmentedControl! 16 | @IBOutlet var trainButton: UIButton! 17 | @IBOutlet weak var graphView: SRMergePlotView! { 18 | didSet { 19 | graphView.title = "Accelerometer Data" 20 | graphView.totalSecondsToDisplay = 0.5 21 | } 22 | } 23 | 24 | fileprivate let accelerometerManager = AccelerometerManager() 25 | fileprivate var currentFilePath: String! 26 | fileprivate var currentFileHandle: FileHandle? 27 | 28 | var trainButtonSelected:Bool = false 29 | var pipeline: GestureRecognitionPipeline? 30 | 31 | fileprivate var anotherDataTimer: Timer? 32 | 33 | override func viewDidLoad() { 34 | super.viewDidLoad() 35 | // Do any additional setup after loading the view, typically from a nib. 36 | let appDelegate = UIApplication.shared.delegate as! AppDelegate 37 | 38 | trainButton.addTarget(self, action:#selector(TrainBtnPressed(_:)), for: .touchDown); 39 | trainButton.addTarget(self, action:#selector(TrainBtnReleased(_:)), for: .touchUpInside); 40 | 41 | graphView.totalChannelsToDisplay = 3 42 | 43 | //Create an instance of a GRT pipeline 44 | self.pipeline = appDelegate.pipeline! 45 | } 46 | 47 | override func viewWillAppear(_ animated: Bool) { 48 | startAccellerometer() 49 | } 50 | 51 | override func viewWillDisappear(_ animated: Bool) { 52 | accelerometerManager.stop() 53 | } 54 | 55 | func startAccellerometer() { 56 | 57 | accelerometerManager.start( accHandler: { (x, y, z) -> Void in 58 | let gestureClass = self.gestureSelector.selectedSegmentIndex 59 | 60 | //Add the accellerometer data to a vector, which is how we'll store the classification data 61 | let vector = VectorFloat() 62 | vector.clear() 63 | vector.pushBack(x) 64 | vector.pushBack(y) 65 | vector.pushBack(z) 66 | 67 | print("x", x) 68 | print("y", y) 69 | print("z", z) 70 | print("Gesture class is %@", gestureClass); 71 | self.graphView.addData([x, y, z]) 72 | 73 | if (self.trainButton.isSelected == true) { 74 | self.pipeline!.addSamplesToClassificationData(forGesture: UInt(gestureClass), vector) 75 | } 76 | 77 | }) 78 | } 79 | 80 | func TrainBtnPressed(_ sender: Any) { 81 | trainButton.isSelected = true 82 | } 83 | 84 | func TrainBtnReleased(_ sender: Any) { 85 | trainButton.isSelected = false 86 | } 87 | 88 | 89 | @IBAction func savePipeline(_ sender: Any) { 90 | // Set URL for saving the pipeline to 91 | let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] 92 | let pipelineURL = documentsUrl.appendingPathComponent("train.grt") 93 | 94 | // Remove the pipeline if it already exists 95 | let _ = try? FileManager.default.removeItem(at: pipelineURL) 96 | 97 | let pipelineSaveResult = self.pipeline?.save(pipelineURL) 98 | if !pipelineSaveResult! { 99 | let userAlert = UIAlertController(title: "Error", message: "Failed to save pipeline", preferredStyle: .alert) 100 | self.present(userAlert, animated: true, completion: { _ in }) 101 | let cancel = UIAlertAction(title: "Dismiss", style: .cancel, handler: nil) 102 | userAlert.addAction(cancel) 103 | } 104 | 105 | // Save the training data as a CSV file 106 | let classificiationDataURL = documentsUrl.appendingPathComponent("trainingData.csv") 107 | 108 | let _ = try? FileManager.default.removeItem(at: classificiationDataURL) 109 | 110 | let classificationSaveResult = self.pipeline?.saveClassificationData(classificiationDataURL) 111 | 112 | if !classificationSaveResult! { 113 | let userAlert = UIAlertController(title: "Error", message: "Failed to save classification data", preferredStyle: .alert) 114 | self.present(userAlert, animated: true, completion: { _ in }) 115 | let cancel = UIAlertAction(title: "Dismiss", style: .cancel, handler: nil) 116 | userAlert.addAction(cancel) 117 | } 118 | } 119 | 120 | override func didReceiveMemoryWarning() { 121 | super.didReceiveMemoryWarning() 122 | // Dispose of any resources that can be recreated. 123 | } 124 | 125 | } 126 | 127 | -------------------------------------------------------------------------------- /GRTiOSFramework/GestureRecognitionPipeline.mm: -------------------------------------------------------------------------------- 1 | // 2 | // GestureRecognitionPipeline.m 3 | // grt 4 | // 5 | // Created by mjahnen on 25/11/15. 6 | // Copyright © 2015 jahnen. All rights reserved. 7 | // Modified by Nick Arner, 2017 8 | // 9 | 10 | #ifdef __cplusplus 11 | #include "GRT.h" 12 | #include 13 | #include 14 | #endif 15 | 16 | #import "GestureRecognitionPipeline.h" 17 | 18 | class NSLogStream: public std::streambuf { 19 | public: 20 | NSLogStream(std::ostream& stream) : 21 | orgStream(stream) 22 | { 23 | // Swap the the old buffer in ostream with this buffer. 24 | orgBuf = orgStream.rdbuf(this); 25 | } 26 | 27 | ~NSLogStream(){ 28 | orgStream.rdbuf(orgBuf); // Restore old buffer 29 | } 30 | 31 | protected: 32 | int_type overflow(int_type c) { 33 | if(!traits_type::eq_int_type(c, traits_type::eof())) 34 | { 35 | char_type const t = traits_type::to_char_type(c); 36 | this->xsputn(&t, 1); 37 | } 38 | return !traits_type::eof(); 39 | } 40 | 41 | int sync() { 42 | return 0; 43 | } 44 | 45 | virtual std::streamsize xsputn(const char *msg, std::streamsize count){ 46 | std::string s(msg,count); 47 | NSLog(@"GRT cout: %@", @(s.c_str())); 48 | return count; 49 | } 50 | 51 | private: 52 | std::streambuf *orgBuf; 53 | std::ostream& orgStream; 54 | }; 55 | 56 | @interface GestureRecognitionPipeline() 57 | @property GRT::GestureRecognitionPipeline *instance; 58 | @property GRT::ClassificationData *classificationData; 59 | @property GRT::ClassificationData *trainingData; 60 | @property GRT::VectorFloat *sampleData; 61 | 62 | @property NSLogStream *nsLogStream; 63 | @end 64 | 65 | @implementation GestureRecognitionPipeline 66 | 67 | 68 | - (instancetype)init { 69 | self = [super init]; 70 | if (self) { 71 | self.instance = new GRT::GestureRecognitionPipeline; 72 | self.classificationData = new GRT::ClassificationData; 73 | self.trainingData = new GRT::ClassificationData; 74 | [self setClassifier]; 75 | // Redirect cout to NSLog 76 | self.nsLogStream = new NSLogStream(std::cout); 77 | } 78 | return self; 79 | } 80 | 81 | - (void)dealloc { 82 | delete self.instance; 83 | delete self.nsLogStream; 84 | } 85 | 86 | //// pipeline configuration 87 | - (void)setClassifier { 88 | GRT::RandomForests classifier; 89 | self.instance->setClassifier(classifier); 90 | classifier.enableNullRejection(true); 91 | self.instance->addPostProcessingModule(GRT::ClassLabelTimeoutFilter(500, GRT::ClassLabelTimeoutFilter::ALL_CLASS_LABELS)); 92 | self.classificationData->setNumDimensions(3); 93 | } 94 | 95 | //// save and load pipeline 96 | - (BOOL)savePipeline:(NSURL *)url { 97 | BOOL result = self.instance->savePipelineToFile(std::string([url fileSystemRepresentation])); 98 | return result; 99 | } 100 | 101 | - (BOOL)loadPipeline:(NSURL *)url { 102 | 103 | BOOL result = self.instance->load(std::string([url fileSystemRepresentation])); 104 | 105 | if (result) { 106 | std::cout << "GRT config"; 107 | std::cout << self.instance->getModelAsString(); 108 | std::cout << "GRT info: " << self.instance->getInfo(); 109 | } 110 | 111 | return result; 112 | } 113 | 114 | //// and load classification data 115 | - (BOOL)saveClassificationData:(NSURL *)url { 116 | 117 | BOOL result = self.classificationData->save(std::string([url fileSystemRepresentation])); 118 | 119 | return result; 120 | } 121 | 122 | - (BOOL)loadClassificationData:(NSURL *)url { 123 | 124 | BOOL result = self.classificationData->load(std::string([url fileSystemRepresentation])); 125 | return result; 126 | } 127 | 128 | - (void)addSamplesToClassificationDataForGesture:(NSUInteger)gesture :(VectorFloat*)vectorData { 129 | 130 | self.classificationData->addSample(gesture, *[vectorData cppInstance]); 131 | } 132 | 133 | - (BOOL)trainPipeline { 134 | *self.trainingData = self.classificationData->split(80); 135 | BOOL trainSuccess = self.instance->train( *(self.trainingData) ); 136 | 137 | std::cout << "STATS " << self.classificationData->getStatsAsString(); 138 | 139 | 140 | GRT::TestResult testResults = self.instance->getTestResults(); 141 | 142 | std::cout << "Pipeline Test Accuracy: " << self.instance->getTestAccuracy() << std::endl; 143 | 144 | 145 | GRT::Vector< GRT::UINT > classLabels = self.instance->getClassLabels(); 146 | 147 | std::cout << "Precision: "; 148 | for (GRT::UINT k=0; kgetNumClassesInModel(); k++) { 149 | std::cout << "\t" << self.instance->getTestPrecision(classLabels[k]); 150 | }std::cout << std::endl; 151 | 152 | return trainSuccess; 153 | } 154 | 155 | - (NSUInteger)predictedClassLabel { 156 | return self.instance->getPredictedClassLabel(); 157 | } 158 | 159 | - (double)maximumLikelihood { 160 | return self.instance->getMaximumLikelihood(); 161 | } 162 | 163 | - (BOOL)predict:(VectorDouble *) inputVector { 164 | return self.instance->predict(*[inputVector cppInstance]); 165 | } 166 | 167 | @end 168 | -------------------------------------------------------------------------------- /GRT-iOS-HelloWorld/GRT-iOS-HelloWorld/PredictionViewController.swift: -------------------------------------------------------------------------------- 1 | 2 | // 3 | // PredictionViewController.swift 4 | // GRT-iOS-HelloWorld 5 | // 6 | // Created by Nicholas Arner on 8/22/17. 7 | // Copyright © 2017 Nicholas Arner. All rights reserved. 8 | // 9 | 10 | import UIKit 11 | import GRTiOS 12 | import SwiftR 13 | 14 | class PredictionViewController: UIViewController { 15 | 16 | @IBOutlet var gestureOneCountLabel: UILabel! 17 | @IBOutlet var gestureTwoCountLabel: UILabel! 18 | @IBOutlet var gestureThreeCountLabel: UILabel! 19 | 20 | @IBOutlet weak var graphView: SRMergePlotView! { 21 | didSet { 22 | graphView.title = "Accelerometer Data" 23 | graphView.totalSecondsToDisplay = 0.5 24 | } 25 | } 26 | 27 | var gestureOneCount: UInt = 0 28 | var gestureTwoCount: UInt = 0 29 | var gestureThreeCount: UInt = 0 30 | 31 | fileprivate let accelerometerManager = AccelerometerManager() 32 | 33 | var currentClassLabel = 0 as UInt 34 | var labelUpdateTime = Date.timeIntervalSinceReferenceDate 35 | let vector = VectorDouble() 36 | var pipeline: GestureRecognitionPipeline? 37 | 38 | override func viewDidLoad() { 39 | let appDelegate = UIApplication.shared.delegate as! AppDelegate 40 | self.pipeline = appDelegate.pipeline! 41 | 42 | initPipeline() 43 | graphView.totalChannelsToDisplay = 3 44 | } 45 | 46 | override func viewWillDisappear(_ animated: Bool) { 47 | accelerometerManager.stop() 48 | resetGestureCount() 49 | } 50 | 51 | func resetGestureCount() { 52 | gestureOneCountLabel.text = "Gesture 1 count: " 53 | gestureTwoCountLabel.text = "Gesture 2 count: " 54 | gestureThreeCountLabel.text = "Gesture 3 count: " 55 | gestureOneCount = 0 56 | gestureTwoCount = 0 57 | gestureThreeCount = 0 58 | } 59 | 60 | func initPipeline(){ 61 | 62 | //Load the GRT pipeline and the training data files from the documents directory 63 | let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0] 64 | 65 | let pipelineURL = documentsUrl.appendingPathComponent("train.grt") 66 | let classificiationDataURL = documentsUrl.appendingPathComponent("trainingData.csv") 67 | 68 | let pipelineResult:Bool = pipeline!.load(pipelineURL) 69 | let classificationDataResult:Bool = pipeline!.loadClassificationData(classificiationDataURL) 70 | 71 | if pipelineResult == false { 72 | let userAlert = UIAlertController(title: "Error", message: "Couldn't load pipeline", preferredStyle: .alert) 73 | let cancel = UIAlertAction(title: "Dismiss", style: .cancel, handler: nil) 74 | userAlert.addAction(cancel) 75 | self.present(userAlert, animated: true, completion: { _ in }) 76 | } 77 | 78 | if classificationDataResult == false { 79 | let userAlert = UIAlertController(title: "Error", message: "Couldn't load classification data", preferredStyle: .alert) 80 | self.present(userAlert, animated: true, completion: { _ in }) 81 | let cancel = UIAlertAction(title: "Dismiss", style: .cancel, handler: nil) 82 | userAlert.addAction(cancel) 83 | } 84 | 85 | //If the files have been loaded successfully, we can train the pipeline, and then start real-time gesture prediction 86 | else if (classificationDataResult && pipelineResult) { 87 | pipeline?.train() 88 | performGesturePrediction() 89 | } 90 | } 91 | 92 | func performGesturePrediction() { 93 | accelerometerManager.start { (x, y, z) -> Void in 94 | self.vector.clear() 95 | self.vector.pushBack(x) 96 | self.vector.pushBack(y) 97 | self.vector.pushBack(z) 98 | //Use the incoming accellerometer data to predict what the performed gesture class is 99 | self.pipeline?.predict(self.vector) 100 | 101 | DispatchQueue.main.async { 102 | self.updateGestureCountLabels(gesture: (self.pipeline?.predictedClassLabel)!) 103 | print("PRECITED GESTURE", self.pipeline?.predictedClassLabel ?? 0); 104 | self.graphView.addData([x, y, z]) 105 | } 106 | 107 | } 108 | } 109 | 110 | func updateGestureCountLabels(gesture: UInt){ 111 | 112 | if gesture == 0 { 113 | //do nothing 114 | } else if (gesture == 1){ 115 | gestureOneCount = gestureOneCount + 1 116 | let gestureOneCountVal = String(gestureOneCount) 117 | gestureOneCountLabel.text = ("Gesture 1 count: " + gestureOneCountVal) 118 | } else if (gesture == 2){ 119 | gestureTwoCount = gestureTwoCount + 1 120 | let gestureTwoCountVal = String(gestureTwoCount) 121 | gestureTwoCountLabel.text = ("Gesture 2 count: " + gestureTwoCountVal) 122 | } else if (gesture == 3){ 123 | gestureThreeCount = gestureThreeCount + 1 124 | let gestureThreeCountVal = String(gestureThreeCount) 125 | gestureThreeCountLabel.text = ("Gesture 3 count: " + gestureThreeCountVal) 126 | } 127 | 128 | } 129 | 130 | } 131 | -------------------------------------------------------------------------------- /GRT-iOS-HelloWorld/GRT-iOS-HelloWorld/Base.lproj/Main.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 32 | 33 | 34 | 35 | 36 | 42 | 48 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 117 | 123 | 129 | 135 | 136 | 137 | 138 | 139 | 140 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | -------------------------------------------------------------------------------- /GRT-iOS-HelloWorld/GRT-iOS-HelloWorld.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | E4775E7A1F5EF5D500D306FD /* TrainingViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4775E791F5EF5D500D306FD /* TrainingViewController.swift */; }; 11 | E488D4A21F4C8DD2004A5CC6 /* PredictionViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = E488D4A11F4C8DD2004A5CC6 /* PredictionViewController.swift */; }; 12 | E4AB6D371F5EF38A00917F2B /* AcceleremoterManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4AB6D361F5EF38A00917F2B /* AcceleremoterManager.swift */; }; 13 | E4C972DA1F45DA0400406BCF /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4C972D91F45DA0400406BCF /* AppDelegate.swift */; }; 14 | E4C972DF1F45DA0400406BCF /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E4C972DD1F45DA0400406BCF /* Main.storyboard */; }; 15 | E4C972E11F45DA0400406BCF /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = E4C972E01F45DA0400406BCF /* Assets.xcassets */; }; 16 | E4C972E41F45DA0400406BCF /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = E4C972E21F45DA0400406BCF /* LaunchScreen.storyboard */; }; 17 | E4C972EF1F45DA0400406BCF /* GRT_iOS_HelloWorldTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4C972EE1F45DA0400406BCF /* GRT_iOS_HelloWorldTests.swift */; }; 18 | E4C972FA1F45DA0400406BCF /* GRT_iOS_HelloWorldUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = E4C972F91F45DA0400406BCF /* GRT_iOS_HelloWorldUITests.swift */; }; 19 | E4F789791F460C5C00683570 /* GRTiOS.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = E4F7895B1F45E7D900683570 /* GRTiOS.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 20 | E4F8BFDD1F7C337200415AF3 /* SwiftR.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E4F8BFDE1F7C337200415AF3 /* SwiftR.framework */; }; 21 | E4F8BFE11F7C36BE00415AF3 /* SwiftR.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = E4F8BFDE1F7C337200415AF3 /* SwiftR.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 22 | /* End PBXBuildFile section */ 23 | 24 | /* Begin PBXContainerItemProxy section */ 25 | E4C972EB1F45DA0400406BCF /* PBXContainerItemProxy */ = { 26 | isa = PBXContainerItemProxy; 27 | containerPortal = E4C972CE1F45DA0400406BCF /* Project object */; 28 | proxyType = 1; 29 | remoteGlobalIDString = E4C972D51F45DA0400406BCF; 30 | remoteInfo = "GRT-iOS-HelloWorld"; 31 | }; 32 | E4C972F61F45DA0400406BCF /* PBXContainerItemProxy */ = { 33 | isa = PBXContainerItemProxy; 34 | containerPortal = E4C972CE1F45DA0400406BCF /* Project object */; 35 | proxyType = 1; 36 | remoteGlobalIDString = E4C972D51F45DA0400406BCF; 37 | remoteInfo = "GRT-iOS-HelloWorld"; 38 | }; 39 | E4F7895A1F45E7D900683570 /* PBXContainerItemProxy */ = { 40 | isa = PBXContainerItemProxy; 41 | containerPortal = E4F789491F45E7D800683570 /* GRTiOS.xcodeproj */; 42 | proxyType = 2; 43 | remoteGlobalIDString = E4065B251F44930300990FA4; 44 | remoteInfo = GRTiOS; 45 | }; 46 | E4F7895C1F45E7D900683570 /* PBXContainerItemProxy */ = { 47 | isa = PBXContainerItemProxy; 48 | containerPortal = E4F789491F45E7D800683570 /* GRTiOS.xcodeproj */; 49 | proxyType = 2; 50 | remoteGlobalIDString = E4065B2E1F44930300990FA4; 51 | remoteInfo = GRTiOSTests; 52 | }; 53 | E4F7897A1F460C5C00683570 /* PBXContainerItemProxy */ = { 54 | isa = PBXContainerItemProxy; 55 | containerPortal = E4F789491F45E7D800683570 /* GRTiOS.xcodeproj */; 56 | proxyType = 1; 57 | remoteGlobalIDString = E4065B241F44930300990FA4; 58 | remoteInfo = GRTiOS; 59 | }; 60 | /* End PBXContainerItemProxy section */ 61 | 62 | /* Begin PBXCopyFilesBuildPhase section */ 63 | E4F7897C1F460C5D00683570 /* Embed Frameworks */ = { 64 | isa = PBXCopyFilesBuildPhase; 65 | buildActionMask = 2147483647; 66 | dstPath = ""; 67 | dstSubfolderSpec = 10; 68 | files = ( 69 | E4F8BFE11F7C36BE00415AF3 /* SwiftR.framework in Embed Frameworks */, 70 | E4F789791F460C5C00683570 /* GRTiOS.framework in Embed Frameworks */, 71 | ); 72 | name = "Embed Frameworks"; 73 | runOnlyForDeploymentPostprocessing = 0; 74 | }; 75 | /* End PBXCopyFilesBuildPhase section */ 76 | 77 | /* Begin PBXFileReference section */ 78 | E41951FF1F4B6D3E0016E511 /* CoreMotion.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMotion.framework; path = System/Library/Frameworks/CoreMotion.framework; sourceTree = SDKROOT; }; 79 | E4775E791F5EF5D500D306FD /* TrainingViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TrainingViewController.swift; sourceTree = ""; }; 80 | E488D4A11F4C8DD2004A5CC6 /* PredictionViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = PredictionViewController.swift; sourceTree = ""; }; 81 | E4AB6D361F5EF38A00917F2B /* AcceleremoterManager.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; name = AcceleremoterManager.swift; path = ../AcceleremoterManager.swift; sourceTree = ""; }; 82 | E4C972D61F45DA0400406BCF /* GRT-iOS-HelloWorld.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "GRT-iOS-HelloWorld.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 83 | E4C972D91F45DA0400406BCF /* AppDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 84 | E4C972DE1F45DA0400406BCF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 85 | E4C972E01F45DA0400406BCF /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 86 | E4C972E31F45DA0400406BCF /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 87 | E4C972E51F45DA0400406BCF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 88 | E4C972EA1F45DA0400406BCF /* GRT-iOS-HelloWorldTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "GRT-iOS-HelloWorldTests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 89 | E4C972EE1F45DA0400406BCF /* GRT_iOS_HelloWorldTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GRT_iOS_HelloWorldTests.swift; sourceTree = ""; }; 90 | E4C972F01F45DA0400406BCF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 91 | E4C972F51F45DA0400406BCF /* GRT-iOS-HelloWorldUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "GRT-iOS-HelloWorldUITests.xctest"; sourceTree = BUILT_PRODUCTS_DIR; }; 92 | E4C972F91F45DA0400406BCF /* GRT_iOS_HelloWorldUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GRT_iOS_HelloWorldUITests.swift; sourceTree = ""; }; 93 | E4C972FB1F45DA0400406BCF /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 94 | E4F7892C1F45DB0500683570 /* GRTiOSFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GRTiOSFramework.framework; path = "../GRTiOSFramework/build/Debug-iphoneos/GRTiOSFramework.framework"; sourceTree = ""; }; 95 | E4F7892E1F45DCDA00683570 /* GRTiOSFramework.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GRTiOSFramework.framework; path = "../../../../Library/Developer/Xcode/DerivedData/GRT-HelloWorld-gjbanovjypsdbdgdyuofejqirqpd/Build/Products/Debug-iphonesimulator/GRTiOSFramework.framework"; sourceTree = ""; }; 96 | E4F789301F45DEAC00683570 /* GRTiOS.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = GRTiOS.framework; path = "../../../../Library/Developer/Xcode/DerivedData/GRT-HelloWorld-gjbanovjypsdbdgdyuofejqirqpd/Build/Products/Debug-iphonesimulator/GRTiOS.framework"; sourceTree = ""; }; 97 | E4F789371F45E2BE00683570 /* GRT-iOS-HelloWorld-Bridging-Header.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "GRT-iOS-HelloWorld-Bridging-Header.h"; sourceTree = ""; }; 98 | E4F789461F45E7D800683570 /* BridgingHeader.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BridgingHeader.h; sourceTree = ""; }; 99 | E4F789471F45E7D800683570 /* GestureRecognitionPipeline.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GestureRecognitionPipeline.h; sourceTree = ""; }; 100 | E4F789481F45E7D800683570 /* GestureRecognitionPipeline.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = GestureRecognitionPipeline.mm; sourceTree = ""; }; 101 | E4F789491F45E7D800683570 /* GRTiOS.xcodeproj */ = {isa = PBXFileReference; lastKnownFileType = "wrapper.pb-project"; path = GRTiOS.xcodeproj; sourceTree = ""; }; 102 | E4F7894D1F45E7D900683570 /* GRTiOS.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GRTiOS.h; sourceTree = ""; }; 103 | E4F7894E1F45E7D900683570 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 104 | E4F789501F45E7D900683570 /* GRTiOSFrameworkTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GRTiOSFrameworkTests.swift; sourceTree = ""; }; 105 | E4F789511F45E7D900683570 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 106 | E4F789531F45E7D900683570 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 107 | E4F789561F45E7D900683570 /* VectorDouble.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = VectorDouble.h; sourceTree = ""; }; 108 | E4F789571F45E7D900683570 /* VectorDouble.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = VectorDouble.mm; sourceTree = ""; }; 109 | E4F8BFDE1F7C337200415AF3 /* SwiftR.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = SwiftR.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 110 | /* End PBXFileReference section */ 111 | 112 | /* Begin PBXFrameworksBuildPhase section */ 113 | E4C972D31F45DA0400406BCF /* Frameworks */ = { 114 | isa = PBXFrameworksBuildPhase; 115 | buildActionMask = 2147483647; 116 | files = ( 117 | E4F8BFDD1F7C337200415AF3 /* SwiftR.framework in Frameworks */, 118 | ); 119 | runOnlyForDeploymentPostprocessing = 0; 120 | }; 121 | E4C972E71F45DA0400406BCF /* Frameworks */ = { 122 | isa = PBXFrameworksBuildPhase; 123 | buildActionMask = 2147483647; 124 | files = ( 125 | ); 126 | runOnlyForDeploymentPostprocessing = 0; 127 | }; 128 | E4C972F21F45DA0400406BCF /* Frameworks */ = { 129 | isa = PBXFrameworksBuildPhase; 130 | buildActionMask = 2147483647; 131 | files = ( 132 | ); 133 | runOnlyForDeploymentPostprocessing = 0; 134 | }; 135 | /* End PBXFrameworksBuildPhase section */ 136 | 137 | /* Begin PBXGroup section */ 138 | E4C972CD1F45DA0400406BCF = { 139 | isa = PBXGroup; 140 | children = ( 141 | E4F789371F45E2BE00683570 /* GRT-iOS-HelloWorld-Bridging-Header.h */, 142 | E4C972D81F45DA0400406BCF /* GRT-iOS-HelloWorld */, 143 | E4C972ED1F45DA0400406BCF /* GRT-iOS-HelloWorldTests */, 144 | E4C972F81F45DA0400406BCF /* GRT-iOS-HelloWorldUITests */, 145 | E4C972D71F45DA0400406BCF /* Products */, 146 | E4F7892B1F45DB0500683570 /* Frameworks */, 147 | ); 148 | sourceTree = ""; 149 | }; 150 | E4C972D71F45DA0400406BCF /* Products */ = { 151 | isa = PBXGroup; 152 | children = ( 153 | E4C972D61F45DA0400406BCF /* GRT-iOS-HelloWorld.app */, 154 | E4C972EA1F45DA0400406BCF /* GRT-iOS-HelloWorldTests.xctest */, 155 | E4C972F51F45DA0400406BCF /* GRT-iOS-HelloWorldUITests.xctest */, 156 | ); 157 | name = Products; 158 | sourceTree = ""; 159 | }; 160 | E4C972D81F45DA0400406BCF /* GRT-iOS-HelloWorld */ = { 161 | isa = PBXGroup; 162 | children = ( 163 | E4775E791F5EF5D500D306FD /* TrainingViewController.swift */, 164 | E488D4A11F4C8DD2004A5CC6 /* PredictionViewController.swift */, 165 | E4C972D91F45DA0400406BCF /* AppDelegate.swift */, 166 | E4AB6D361F5EF38A00917F2B /* AcceleremoterManager.swift */, 167 | E4C972DD1F45DA0400406BCF /* Main.storyboard */, 168 | E4C972E01F45DA0400406BCF /* Assets.xcassets */, 169 | E4C972E21F45DA0400406BCF /* LaunchScreen.storyboard */, 170 | E4C972E51F45DA0400406BCF /* Info.plist */, 171 | ); 172 | path = "GRT-iOS-HelloWorld"; 173 | sourceTree = ""; 174 | }; 175 | E4C972ED1F45DA0400406BCF /* GRT-iOS-HelloWorldTests */ = { 176 | isa = PBXGroup; 177 | children = ( 178 | E4C972EE1F45DA0400406BCF /* GRT_iOS_HelloWorldTests.swift */, 179 | E4C972F01F45DA0400406BCF /* Info.plist */, 180 | ); 181 | path = "GRT-iOS-HelloWorldTests"; 182 | sourceTree = ""; 183 | }; 184 | E4C972F81F45DA0400406BCF /* GRT-iOS-HelloWorldUITests */ = { 185 | isa = PBXGroup; 186 | children = ( 187 | E4C972F91F45DA0400406BCF /* GRT_iOS_HelloWorldUITests.swift */, 188 | E4C972FB1F45DA0400406BCF /* Info.plist */, 189 | ); 190 | path = "GRT-iOS-HelloWorldUITests"; 191 | sourceTree = ""; 192 | }; 193 | E4F7892B1F45DB0500683570 /* Frameworks */ = { 194 | isa = PBXGroup; 195 | children = ( 196 | E4F8BFDE1F7C337200415AF3 /* SwiftR.framework */, 197 | E41951FF1F4B6D3E0016E511 /* CoreMotion.framework */, 198 | E4F789451F45E7D800683570 /* GRTiOSFramework */, 199 | E4F789301F45DEAC00683570 /* GRTiOS.framework */, 200 | E4F7892E1F45DCDA00683570 /* GRTiOSFramework.framework */, 201 | E4F7892C1F45DB0500683570 /* GRTiOSFramework.framework */, 202 | ); 203 | name = Frameworks; 204 | sourceTree = ""; 205 | }; 206 | E4F789451F45E7D800683570 /* GRTiOSFramework */ = { 207 | isa = PBXGroup; 208 | children = ( 209 | E4F789461F45E7D800683570 /* BridgingHeader.h */, 210 | E4F789471F45E7D800683570 /* GestureRecognitionPipeline.h */, 211 | E4F789481F45E7D800683570 /* GestureRecognitionPipeline.mm */, 212 | E4F789491F45E7D800683570 /* GRTiOS.xcodeproj */, 213 | E4F7894C1F45E7D900683570 /* GRTiOSFramework */, 214 | E4F7894F1F45E7D900683570 /* GRTiOSFrameworkTests */, 215 | E4F789521F45E7D900683570 /* iOS-GRT-HelloWorld */, 216 | E4F789541F45E7D900683570 /* iOS-GRT-HelloWorldTests */, 217 | E4F789551F45E7D900683570 /* iOS-GRT-HelloWorldUITests */, 218 | E4F789561F45E7D900683570 /* VectorDouble.h */, 219 | E4F789571F45E7D900683570 /* VectorDouble.mm */, 220 | ); 221 | name = GRTiOSFramework; 222 | path = ../GRTiOSFramework; 223 | sourceTree = ""; 224 | }; 225 | E4F7894A1F45E7D800683570 /* Products */ = { 226 | isa = PBXGroup; 227 | children = ( 228 | E4F7895B1F45E7D900683570 /* GRTiOS.framework */, 229 | E4F7895D1F45E7D900683570 /* GRTiOSTests.xctest */, 230 | ); 231 | name = Products; 232 | sourceTree = ""; 233 | }; 234 | E4F7894C1F45E7D900683570 /* GRTiOSFramework */ = { 235 | isa = PBXGroup; 236 | children = ( 237 | E4F7894D1F45E7D900683570 /* GRTiOS.h */, 238 | E4F7894E1F45E7D900683570 /* Info.plist */, 239 | ); 240 | path = GRTiOSFramework; 241 | sourceTree = ""; 242 | }; 243 | E4F7894F1F45E7D900683570 /* GRTiOSFrameworkTests */ = { 244 | isa = PBXGroup; 245 | children = ( 246 | E4F789501F45E7D900683570 /* GRTiOSFrameworkTests.swift */, 247 | E4F789511F45E7D900683570 /* Info.plist */, 248 | ); 249 | path = GRTiOSFrameworkTests; 250 | sourceTree = ""; 251 | }; 252 | E4F789521F45E7D900683570 /* iOS-GRT-HelloWorld */ = { 253 | isa = PBXGroup; 254 | children = ( 255 | E4F789531F45E7D900683570 /* Assets.xcassets */, 256 | ); 257 | path = "iOS-GRT-HelloWorld"; 258 | sourceTree = ""; 259 | }; 260 | E4F789541F45E7D900683570 /* iOS-GRT-HelloWorldTests */ = { 261 | isa = PBXGroup; 262 | children = ( 263 | ); 264 | path = "iOS-GRT-HelloWorldTests"; 265 | sourceTree = ""; 266 | }; 267 | E4F789551F45E7D900683570 /* iOS-GRT-HelloWorldUITests */ = { 268 | isa = PBXGroup; 269 | children = ( 270 | ); 271 | path = "iOS-GRT-HelloWorldUITests"; 272 | sourceTree = ""; 273 | }; 274 | /* End PBXGroup section */ 275 | 276 | /* Begin PBXNativeTarget section */ 277 | E4C972D51F45DA0400406BCF /* GRT-iOS-HelloWorld */ = { 278 | isa = PBXNativeTarget; 279 | buildConfigurationList = E4C972FE1F45DA0400406BCF /* Build configuration list for PBXNativeTarget "GRT-iOS-HelloWorld" */; 280 | buildPhases = ( 281 | E4C972D21F45DA0400406BCF /* Sources */, 282 | E4C972D31F45DA0400406BCF /* Frameworks */, 283 | E4C972D41F45DA0400406BCF /* Resources */, 284 | E4F7897C1F460C5D00683570 /* Embed Frameworks */, 285 | ); 286 | buildRules = ( 287 | ); 288 | dependencies = ( 289 | E4F7897B1F460C5C00683570 /* PBXTargetDependency */, 290 | ); 291 | name = "GRT-iOS-HelloWorld"; 292 | productName = "GRT-iOS-HelloWorld"; 293 | productReference = E4C972D61F45DA0400406BCF /* GRT-iOS-HelloWorld.app */; 294 | productType = "com.apple.product-type.application"; 295 | }; 296 | E4C972E91F45DA0400406BCF /* GRT-iOS-HelloWorldTests */ = { 297 | isa = PBXNativeTarget; 298 | buildConfigurationList = E4C973011F45DA0400406BCF /* Build configuration list for PBXNativeTarget "GRT-iOS-HelloWorldTests" */; 299 | buildPhases = ( 300 | E4C972E61F45DA0400406BCF /* Sources */, 301 | E4C972E71F45DA0400406BCF /* Frameworks */, 302 | E4C972E81F45DA0400406BCF /* Resources */, 303 | ); 304 | buildRules = ( 305 | ); 306 | dependencies = ( 307 | E4C972EC1F45DA0400406BCF /* PBXTargetDependency */, 308 | ); 309 | name = "GRT-iOS-HelloWorldTests"; 310 | productName = "GRT-iOS-HelloWorldTests"; 311 | productReference = E4C972EA1F45DA0400406BCF /* GRT-iOS-HelloWorldTests.xctest */; 312 | productType = "com.apple.product-type.bundle.unit-test"; 313 | }; 314 | E4C972F41F45DA0400406BCF /* GRT-iOS-HelloWorldUITests */ = { 315 | isa = PBXNativeTarget; 316 | buildConfigurationList = E4C973041F45DA0400406BCF /* Build configuration list for PBXNativeTarget "GRT-iOS-HelloWorldUITests" */; 317 | buildPhases = ( 318 | E4C972F11F45DA0400406BCF /* Sources */, 319 | E4C972F21F45DA0400406BCF /* Frameworks */, 320 | E4C972F31F45DA0400406BCF /* Resources */, 321 | ); 322 | buildRules = ( 323 | ); 324 | dependencies = ( 325 | E4C972F71F45DA0400406BCF /* PBXTargetDependency */, 326 | ); 327 | name = "GRT-iOS-HelloWorldUITests"; 328 | productName = "GRT-iOS-HelloWorldUITests"; 329 | productReference = E4C972F51F45DA0400406BCF /* GRT-iOS-HelloWorldUITests.xctest */; 330 | productType = "com.apple.product-type.bundle.ui-testing"; 331 | }; 332 | /* End PBXNativeTarget section */ 333 | 334 | /* Begin PBXProject section */ 335 | E4C972CE1F45DA0400406BCF /* Project object */ = { 336 | isa = PBXProject; 337 | attributes = { 338 | LastSwiftUpdateCheck = 0830; 339 | LastUpgradeCheck = 0830; 340 | ORGANIZATIONNAME = "Nicholas Arner"; 341 | TargetAttributes = { 342 | E4C972D51F45DA0400406BCF = { 343 | CreatedOnToolsVersion = 8.3.3; 344 | DevelopmentTeam = MCCU4CZ5B9; 345 | ProvisioningStyle = Automatic; 346 | }; 347 | E4C972E91F45DA0400406BCF = { 348 | CreatedOnToolsVersion = 8.3.3; 349 | ProvisioningStyle = Automatic; 350 | TestTargetID = E4C972D51F45DA0400406BCF; 351 | }; 352 | E4C972F41F45DA0400406BCF = { 353 | CreatedOnToolsVersion = 8.3.3; 354 | ProvisioningStyle = Automatic; 355 | TestTargetID = E4C972D51F45DA0400406BCF; 356 | }; 357 | }; 358 | }; 359 | buildConfigurationList = E4C972D11F45DA0400406BCF /* Build configuration list for PBXProject "GRT-iOS-HelloWorld" */; 360 | compatibilityVersion = "Xcode 3.2"; 361 | developmentRegion = English; 362 | hasScannedForEncodings = 0; 363 | knownRegions = ( 364 | en, 365 | Base, 366 | ); 367 | mainGroup = E4C972CD1F45DA0400406BCF; 368 | productRefGroup = E4C972D71F45DA0400406BCF /* Products */; 369 | projectDirPath = ""; 370 | projectReferences = ( 371 | { 372 | ProductGroup = E4F7894A1F45E7D800683570 /* Products */; 373 | ProjectRef = E4F789491F45E7D800683570 /* GRTiOS.xcodeproj */; 374 | }, 375 | ); 376 | projectRoot = ""; 377 | targets = ( 378 | E4C972D51F45DA0400406BCF /* GRT-iOS-HelloWorld */, 379 | E4C972E91F45DA0400406BCF /* GRT-iOS-HelloWorldTests */, 380 | E4C972F41F45DA0400406BCF /* GRT-iOS-HelloWorldUITests */, 381 | ); 382 | }; 383 | /* End PBXProject section */ 384 | 385 | /* Begin PBXReferenceProxy section */ 386 | E4F7895B1F45E7D900683570 /* GRTiOS.framework */ = { 387 | isa = PBXReferenceProxy; 388 | fileType = wrapper.framework; 389 | path = GRTiOS.framework; 390 | remoteRef = E4F7895A1F45E7D900683570 /* PBXContainerItemProxy */; 391 | sourceTree = BUILT_PRODUCTS_DIR; 392 | }; 393 | E4F7895D1F45E7D900683570 /* GRTiOSTests.xctest */ = { 394 | isa = PBXReferenceProxy; 395 | fileType = wrapper.cfbundle; 396 | path = GRTiOSTests.xctest; 397 | remoteRef = E4F7895C1F45E7D900683570 /* PBXContainerItemProxy */; 398 | sourceTree = BUILT_PRODUCTS_DIR; 399 | }; 400 | /* End PBXReferenceProxy section */ 401 | 402 | /* Begin PBXResourcesBuildPhase section */ 403 | E4C972D41F45DA0400406BCF /* Resources */ = { 404 | isa = PBXResourcesBuildPhase; 405 | buildActionMask = 2147483647; 406 | files = ( 407 | E4C972E41F45DA0400406BCF /* LaunchScreen.storyboard in Resources */, 408 | E4C972E11F45DA0400406BCF /* Assets.xcassets in Resources */, 409 | E4C972DF1F45DA0400406BCF /* Main.storyboard in Resources */, 410 | ); 411 | runOnlyForDeploymentPostprocessing = 0; 412 | }; 413 | E4C972E81F45DA0400406BCF /* Resources */ = { 414 | isa = PBXResourcesBuildPhase; 415 | buildActionMask = 2147483647; 416 | files = ( 417 | ); 418 | runOnlyForDeploymentPostprocessing = 0; 419 | }; 420 | E4C972F31F45DA0400406BCF /* Resources */ = { 421 | isa = PBXResourcesBuildPhase; 422 | buildActionMask = 2147483647; 423 | files = ( 424 | ); 425 | runOnlyForDeploymentPostprocessing = 0; 426 | }; 427 | /* End PBXResourcesBuildPhase section */ 428 | 429 | /* Begin PBXSourcesBuildPhase section */ 430 | E4C972D21F45DA0400406BCF /* Sources */ = { 431 | isa = PBXSourcesBuildPhase; 432 | buildActionMask = 2147483647; 433 | files = ( 434 | E488D4A21F4C8DD2004A5CC6 /* PredictionViewController.swift in Sources */, 435 | E4AB6D371F5EF38A00917F2B /* AcceleremoterManager.swift in Sources */, 436 | E4775E7A1F5EF5D500D306FD /* TrainingViewController.swift in Sources */, 437 | E4C972DA1F45DA0400406BCF /* AppDelegate.swift in Sources */, 438 | ); 439 | runOnlyForDeploymentPostprocessing = 0; 440 | }; 441 | E4C972E61F45DA0400406BCF /* Sources */ = { 442 | isa = PBXSourcesBuildPhase; 443 | buildActionMask = 2147483647; 444 | files = ( 445 | E4C972EF1F45DA0400406BCF /* GRT_iOS_HelloWorldTests.swift in Sources */, 446 | ); 447 | runOnlyForDeploymentPostprocessing = 0; 448 | }; 449 | E4C972F11F45DA0400406BCF /* Sources */ = { 450 | isa = PBXSourcesBuildPhase; 451 | buildActionMask = 2147483647; 452 | files = ( 453 | E4C972FA1F45DA0400406BCF /* GRT_iOS_HelloWorldUITests.swift in Sources */, 454 | ); 455 | runOnlyForDeploymentPostprocessing = 0; 456 | }; 457 | /* End PBXSourcesBuildPhase section */ 458 | 459 | /* Begin PBXTargetDependency section */ 460 | E4C972EC1F45DA0400406BCF /* PBXTargetDependency */ = { 461 | isa = PBXTargetDependency; 462 | target = E4C972D51F45DA0400406BCF /* GRT-iOS-HelloWorld */; 463 | targetProxy = E4C972EB1F45DA0400406BCF /* PBXContainerItemProxy */; 464 | }; 465 | E4C972F71F45DA0400406BCF /* PBXTargetDependency */ = { 466 | isa = PBXTargetDependency; 467 | target = E4C972D51F45DA0400406BCF /* GRT-iOS-HelloWorld */; 468 | targetProxy = E4C972F61F45DA0400406BCF /* PBXContainerItemProxy */; 469 | }; 470 | E4F7897B1F460C5C00683570 /* PBXTargetDependency */ = { 471 | isa = PBXTargetDependency; 472 | name = GRTiOS; 473 | targetProxy = E4F7897A1F460C5C00683570 /* PBXContainerItemProxy */; 474 | }; 475 | /* End PBXTargetDependency section */ 476 | 477 | /* Begin PBXVariantGroup section */ 478 | E4C972DD1F45DA0400406BCF /* Main.storyboard */ = { 479 | isa = PBXVariantGroup; 480 | children = ( 481 | E4C972DE1F45DA0400406BCF /* Base */, 482 | ); 483 | name = Main.storyboard; 484 | sourceTree = ""; 485 | }; 486 | E4C972E21F45DA0400406BCF /* LaunchScreen.storyboard */ = { 487 | isa = PBXVariantGroup; 488 | children = ( 489 | E4C972E31F45DA0400406BCF /* Base */, 490 | ); 491 | name = LaunchScreen.storyboard; 492 | sourceTree = ""; 493 | }; 494 | /* End PBXVariantGroup section */ 495 | 496 | /* Begin XCBuildConfiguration section */ 497 | E4C972FC1F45DA0400406BCF /* Debug */ = { 498 | isa = XCBuildConfiguration; 499 | buildSettings = { 500 | ALWAYS_SEARCH_USER_PATHS = NO; 501 | CLANG_ANALYZER_NONNULL = YES; 502 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 503 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 504 | CLANG_CXX_LIBRARY = "libc++"; 505 | CLANG_ENABLE_MODULES = YES; 506 | CLANG_ENABLE_OBJC_ARC = YES; 507 | CLANG_WARN_BOOL_CONVERSION = YES; 508 | CLANG_WARN_CONSTANT_CONVERSION = YES; 509 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 510 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 511 | CLANG_WARN_EMPTY_BODY = YES; 512 | CLANG_WARN_ENUM_CONVERSION = YES; 513 | CLANG_WARN_INFINITE_RECURSION = YES; 514 | CLANG_WARN_INT_CONVERSION = YES; 515 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 516 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 517 | CLANG_WARN_UNREACHABLE_CODE = YES; 518 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 519 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 520 | COPY_PHASE_STRIP = NO; 521 | DEBUG_INFORMATION_FORMAT = dwarf; 522 | ENABLE_STRICT_OBJC_MSGSEND = YES; 523 | ENABLE_TESTABILITY = YES; 524 | GCC_C_LANGUAGE_STANDARD = gnu99; 525 | GCC_DYNAMIC_NO_PIC = NO; 526 | GCC_NO_COMMON_BLOCKS = YES; 527 | GCC_OPTIMIZATION_LEVEL = 0; 528 | GCC_PREPROCESSOR_DEFINITIONS = ( 529 | "DEBUG=1", 530 | "$(inherited)", 531 | ); 532 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 533 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 534 | GCC_WARN_UNDECLARED_SELECTOR = YES; 535 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 536 | GCC_WARN_UNUSED_FUNCTION = YES; 537 | GCC_WARN_UNUSED_VARIABLE = YES; 538 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 539 | MTL_ENABLE_DEBUG_INFO = YES; 540 | ONLY_ACTIVE_ARCH = YES; 541 | SDKROOT = iphoneos; 542 | SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG; 543 | SWIFT_OPTIMIZATION_LEVEL = "-Onone"; 544 | TARGETED_DEVICE_FAMILY = "1,2"; 545 | }; 546 | name = Debug; 547 | }; 548 | E4C972FD1F45DA0400406BCF /* Release */ = { 549 | isa = XCBuildConfiguration; 550 | buildSettings = { 551 | ALWAYS_SEARCH_USER_PATHS = NO; 552 | CLANG_ANALYZER_NONNULL = YES; 553 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 554 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 555 | CLANG_CXX_LIBRARY = "libc++"; 556 | CLANG_ENABLE_MODULES = YES; 557 | CLANG_ENABLE_OBJC_ARC = YES; 558 | CLANG_WARN_BOOL_CONVERSION = YES; 559 | CLANG_WARN_CONSTANT_CONVERSION = YES; 560 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 561 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 562 | CLANG_WARN_EMPTY_BODY = YES; 563 | CLANG_WARN_ENUM_CONVERSION = YES; 564 | CLANG_WARN_INFINITE_RECURSION = YES; 565 | CLANG_WARN_INT_CONVERSION = YES; 566 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 567 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 568 | CLANG_WARN_UNREACHABLE_CODE = YES; 569 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 570 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 571 | COPY_PHASE_STRIP = NO; 572 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 573 | ENABLE_NS_ASSERTIONS = NO; 574 | ENABLE_STRICT_OBJC_MSGSEND = YES; 575 | GCC_C_LANGUAGE_STANDARD = gnu99; 576 | GCC_NO_COMMON_BLOCKS = YES; 577 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 578 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 579 | GCC_WARN_UNDECLARED_SELECTOR = YES; 580 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 581 | GCC_WARN_UNUSED_FUNCTION = YES; 582 | GCC_WARN_UNUSED_VARIABLE = YES; 583 | IPHONEOS_DEPLOYMENT_TARGET = 10.3; 584 | MTL_ENABLE_DEBUG_INFO = NO; 585 | SDKROOT = iphoneos; 586 | SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; 587 | TARGETED_DEVICE_FAMILY = "1,2"; 588 | VALIDATE_PRODUCT = YES; 589 | }; 590 | name = Release; 591 | }; 592 | E4C972FF1F45DA0400406BCF /* Debug */ = { 593 | isa = XCBuildConfiguration; 594 | buildSettings = { 595 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 596 | DEVELOPMENT_TEAM = MCCU4CZ5B9; 597 | INFOPLIST_FILE = "GRT-iOS-HelloWorld/Info.plist"; 598 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 599 | PRODUCT_BUNDLE_IDENTIFIER = "embodiedMediaSystems.GRT-iOS-HelloWorld"; 600 | PRODUCT_NAME = "$(TARGET_NAME)"; 601 | SWIFT_OBJC_BRIDGING_HEADER = "GRT-iOS-HelloWorld-Bridging-Header.h"; 602 | SWIFT_VERSION = 3.0; 603 | }; 604 | name = Debug; 605 | }; 606 | E4C973001F45DA0400406BCF /* Release */ = { 607 | isa = XCBuildConfiguration; 608 | buildSettings = { 609 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 610 | DEVELOPMENT_TEAM = MCCU4CZ5B9; 611 | INFOPLIST_FILE = "GRT-iOS-HelloWorld/Info.plist"; 612 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; 613 | PRODUCT_BUNDLE_IDENTIFIER = "embodiedMediaSystems.GRT-iOS-HelloWorld"; 614 | PRODUCT_NAME = "$(TARGET_NAME)"; 615 | SWIFT_OBJC_BRIDGING_HEADER = "GRT-iOS-HelloWorld-Bridging-Header.h"; 616 | SWIFT_VERSION = 3.0; 617 | }; 618 | name = Release; 619 | }; 620 | E4C973021F45DA0400406BCF /* Debug */ = { 621 | isa = XCBuildConfiguration; 622 | buildSettings = { 623 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 624 | BUNDLE_LOADER = "$(TEST_HOST)"; 625 | INFOPLIST_FILE = "GRT-iOS-HelloWorldTests/Info.plist"; 626 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 627 | PRODUCT_BUNDLE_IDENTIFIER = "embodiedMediaSystems.GRT-iOS-HelloWorldTests"; 628 | PRODUCT_NAME = "$(TARGET_NAME)"; 629 | SWIFT_VERSION = 3.0; 630 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/GRT-iOS-HelloWorld.app/GRT-iOS-HelloWorld"; 631 | }; 632 | name = Debug; 633 | }; 634 | E4C973031F45DA0400406BCF /* Release */ = { 635 | isa = XCBuildConfiguration; 636 | buildSettings = { 637 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 638 | BUNDLE_LOADER = "$(TEST_HOST)"; 639 | INFOPLIST_FILE = "GRT-iOS-HelloWorldTests/Info.plist"; 640 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 641 | PRODUCT_BUNDLE_IDENTIFIER = "embodiedMediaSystems.GRT-iOS-HelloWorldTests"; 642 | PRODUCT_NAME = "$(TARGET_NAME)"; 643 | SWIFT_VERSION = 3.0; 644 | TEST_HOST = "$(BUILT_PRODUCTS_DIR)/GRT-iOS-HelloWorld.app/GRT-iOS-HelloWorld"; 645 | }; 646 | name = Release; 647 | }; 648 | E4C973051F45DA0400406BCF /* Debug */ = { 649 | isa = XCBuildConfiguration; 650 | buildSettings = { 651 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 652 | INFOPLIST_FILE = "GRT-iOS-HelloWorldUITests/Info.plist"; 653 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 654 | PRODUCT_BUNDLE_IDENTIFIER = "embodiedMediaSystems.GRT-iOS-HelloWorldUITests"; 655 | PRODUCT_NAME = "$(TARGET_NAME)"; 656 | SWIFT_VERSION = 3.0; 657 | TEST_TARGET_NAME = "GRT-iOS-HelloWorld"; 658 | }; 659 | name = Debug; 660 | }; 661 | E4C973061F45DA0400406BCF /* Release */ = { 662 | isa = XCBuildConfiguration; 663 | buildSettings = { 664 | ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; 665 | INFOPLIST_FILE = "GRT-iOS-HelloWorldUITests/Info.plist"; 666 | LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; 667 | PRODUCT_BUNDLE_IDENTIFIER = "embodiedMediaSystems.GRT-iOS-HelloWorldUITests"; 668 | PRODUCT_NAME = "$(TARGET_NAME)"; 669 | SWIFT_VERSION = 3.0; 670 | TEST_TARGET_NAME = "GRT-iOS-HelloWorld"; 671 | }; 672 | name = Release; 673 | }; 674 | /* End XCBuildConfiguration section */ 675 | 676 | /* Begin XCConfigurationList section */ 677 | E4C972D11F45DA0400406BCF /* Build configuration list for PBXProject "GRT-iOS-HelloWorld" */ = { 678 | isa = XCConfigurationList; 679 | buildConfigurations = ( 680 | E4C972FC1F45DA0400406BCF /* Debug */, 681 | E4C972FD1F45DA0400406BCF /* Release */, 682 | ); 683 | defaultConfigurationIsVisible = 0; 684 | defaultConfigurationName = Release; 685 | }; 686 | E4C972FE1F45DA0400406BCF /* Build configuration list for PBXNativeTarget "GRT-iOS-HelloWorld" */ = { 687 | isa = XCConfigurationList; 688 | buildConfigurations = ( 689 | E4C972FF1F45DA0400406BCF /* Debug */, 690 | E4C973001F45DA0400406BCF /* Release */, 691 | ); 692 | defaultConfigurationIsVisible = 0; 693 | defaultConfigurationName = Release; 694 | }; 695 | E4C973011F45DA0400406BCF /* Build configuration list for PBXNativeTarget "GRT-iOS-HelloWorldTests" */ = { 696 | isa = XCConfigurationList; 697 | buildConfigurations = ( 698 | E4C973021F45DA0400406BCF /* Debug */, 699 | E4C973031F45DA0400406BCF /* Release */, 700 | ); 701 | defaultConfigurationIsVisible = 0; 702 | defaultConfigurationName = Release; 703 | }; 704 | E4C973041F45DA0400406BCF /* Build configuration list for PBXNativeTarget "GRT-iOS-HelloWorldUITests" */ = { 705 | isa = XCConfigurationList; 706 | buildConfigurations = ( 707 | E4C973051F45DA0400406BCF /* Debug */, 708 | E4C973061F45DA0400406BCF /* Release */, 709 | ); 710 | defaultConfigurationIsVisible = 0; 711 | defaultConfigurationName = Release; 712 | }; 713 | /* End XCConfigurationList section */ 714 | }; 715 | rootObject = E4C972CE1F45DA0400406BCF /* Project object */; 716 | } 717 | --------------------------------------------------------------------------------