├── README.md ├── VideoToPictures.cpp ├── ios_logger.xcodeproj ├── project.pbxproj ├── project.xcworkspace │ ├── contents.xcworkspacedata │ └── xcshareddata │ │ └── IDEWorkspaceChecks.plist └── xcuserdata │ ├── mac.xcuserdatad │ └── xcschemes │ │ └── xcschememanagement.plist │ └── macvmws.xcuserdatad │ └── xcschemes │ └── xcschememanagement.plist ├── ios_logger ├── AppDelegate.h ├── AppDelegate.m ├── Assets.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── Contents.json ├── Base.lproj │ ├── LaunchScreen.storyboard │ └── Main.storyboard ├── Info.plist ├── ViewController.h ├── ViewController.mm └── main.m └── sync-data.py /README.md: -------------------------------------------------------------------------------- 1 | # ios_logger 2 | Application for logging camera images, accelerometer and gyroscope data, gps and heading data, motion data and magnet data. 3 | 4 | This application was made for logging camera images and sensor data on Apple devices (iPad/iPhone). 5 | 6 | ## Build and run: 7 | 1. Open ios_logger.xcodeproj in XCode 8 | 2. In project properties -> General set your team signing and make sure that signing certificate was successfully created 9 | 3. Connect your device (you may have to wait for the debugger to be set up), select it (Product -> Destination) and run application (Product -> Run) 10 | 11 | ## Collect datasets: 12 | To start collecting dataset: 13 | * set required image resolution in upper-left corner 14 | * **if you check ARKit segment - app will use ARKit to get camera images (with ARKit native resolution - depends on device) + app will _logging ARKit poses of the device_ (with origin in place where "START" button was pressed)** 15 | * set switches with required sensors to be logged 16 | * _you can set AutoFocus on/off with "AF" button_ 17 | * _with off AutoFocus you can set camera focal lenth by slider in bottom-right corned_ 18 | * press "START" button 19 | * when you want to stop collecting dataset press "STOP" :-) 20 | 21 | Each dataset will be saved in separate folder on the device . 22 | 23 | ## Get saved datasets: 24 | After you have collected datasets connect your device to PC and run iTunes. In iTunes go to device-> File Sharing -> ios-logger, in right table check folders with datasets you needed and save it on your PC. 25 | In last versions of MacOS you should use finder to acess the device and get File Sharing. 26 | 27 | ## Dataset format: 28 | * Accel.txt: time(s(from 1970)),ax(g-units),ay(g-units),az(g-units) 29 | * Gyro.txt: time(s),gx(rad/s),gy(rad/s),gz(rad/s) 30 | * GPS.txt: time(s),latitude(deg),longitude(deg),horizontalAccuracy(m),altitude(m),verticalAccuracy(m),floorLevel,course(dgr),speed(m/s) 31 | * Head.txt: time(s),trueHeading(dgr),magneticHeading(dgr),headingAccuracy(dgr) 32 | * Motion.txt: time(s),attitude.quaternion.w,attitude.quaternion.x,attitude.quaternion.y,attitude.quaternion.z 33 | * MotARH.txt: time(s),rotationRate.x(rad/s),rotationRate.y(rad/s),rotationRate.z(rad/s),gravity.x(g-units),gravity.y(g-units),gravity.z(g-units),userAccel.x(g-units),userAccel.y(g-units),userAccel.z(g-units),motionHeading(dgr) 34 | * MotMagnFull.txt: time(s),calibratedMagnField.x(microteslas),calibratedMagnField.y(microteslas),calibratedMagnField.z(microteslas),magnFieldAccuracy 35 | * Magnet.txt: time(s),magneticField.x(microteslas),magneticField.y(microteslas),magneticField.z(microteslas) 36 | * ARposes.txt: time(s),ARKit.translation.x(m),ARKit.translation.y(m),ARKit.translation.z(m),ARKit.quaternion.w,ARKit.quaternion.x,ARKit.quaternion.y,ARKit.quaternion.z 37 | * Frames.txt: time(s),frameNumber,_focalLenghtX,focalLenghtY,principalPointX,principalPointY_ 38 | * Frames.m4v: frames compressed in video 39 | 40 | ## Other: 41 | _To syncronize accelerometer and gyroscope data_ you can use python script sync-data.py: 42 | ``` 43 | python path_to_folder_with_sync-data/sync-data.py path_to_datasets_folder/dataset_folder 44 | ``` 45 | 46 | _To get frames from video you can use ffmpeg or some video editor._ 47 | For example: 48 | ``` 49 | ffmpeg -i Frames.m4v Frames/Frame%05d.png -hide_banner 50 | ``` 51 | or you can try to use VideoToPictures.cpp: 52 | ``` 53 | compile VideoToPictures.cpp and 54 | VideoToPictures path_to_datasets_folder/dataset_folder/Frames.m4v 55 | ``` 56 | -------------------------------------------------------------------------------- /VideoToPictures.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include "opencv2/opencv.hpp" 3 | 4 | #ifdef _WIN32 5 | #include 6 | #endif // _WIN32 7 | 8 | #ifdef __linux__ 9 | #include 10 | #endif // __linux__ 11 | 12 | using namespace cv; 13 | using namespace std; 14 | 15 | class IMUData { 16 | public: 17 | IMUData(const double &gx, const double &gy, const double &gz, 18 | const double &ax, const double &ay, const double &az, 19 | const double &t) : _g(gx, gy, gz), _a(ax, ay, az), _t(t) {} 20 | 21 | string toString() 22 | { 23 | string ret; 24 | 25 | ret += to_string(long long(_t * 1e6) * 1000) + ','; 26 | ret += to_string(_g[0]) + ','; 27 | ret += to_string(_g[1]) + ','; 28 | ret += to_string(_g[2]) + ','; 29 | ret += to_string(_a[0]) + ','; 30 | ret += to_string(_a[1]) + ','; 31 | ret += to_string(_a[2]); 32 | 33 | return ret; 34 | } 35 | 36 | string toStringM() 37 | { 38 | string ret; 39 | 40 | ret += to_string(long long(_t * 1e6) * 1000) + ','; 41 | ret += to_string(_g[0]) + ','; 42 | ret += to_string(_g[1]) + ','; 43 | ret += to_string(_g[2]) + ','; 44 | ret += to_string(-_a[0]) + ','; 45 | ret += to_string(-_a[1]) + ','; 46 | ret += to_string(-_a[2]); 47 | 48 | return ret; 49 | } 50 | 51 | // Raw data of imu 52 | Vec3d _g; //gyr data 53 | Vec3d _a; //acc data 54 | double _t; //timestamp 55 | }; 56 | 57 | void LoadFrameNames(const string &strFramesFile, vector &vFrames); 58 | bool LoadImus2(const string &strAccelGyroFile, vector &vImus); 59 | 60 | const char* keys = 61 | "{ help h | | Print help message. }" 62 | "{ videoName | D:/Datasets/ARCNA/2019-02-08T14-26-03/Frames.m4v | Video File Name. }"; 63 | 64 | int main(int argc, char* argv[]) 65 | { 66 | CommandLineParser parser(argc, argv, keys); 67 | string videoName = parser.get("videoName"); 68 | 69 | VideoCapture cap(videoName); 70 | 71 | if (!cap.isOpened()) 72 | { 73 | cerr << "Error when reading video"; 74 | return -1; 75 | } 76 | 77 | string workDir = videoName; 78 | workDir.resize(workDir.size() - 10); 79 | 80 | #ifdef _WIN32 81 | CreateDirectoryA((workDir + "cam0").c_str(), NULL); 82 | #endif // _WIN32 83 | 84 | #ifdef __linux__ 85 | boost::filesystem::create_directories((workDir + "cam0").c_str()); 86 | #endif // __linux__ 87 | 88 | string framesFileName = videoName; 89 | auto cb = framesFileName.end(); 90 | *(--cb) = 't'; 91 | *(--cb) = 'x'; 92 | *(--cb) = 't'; 93 | 94 | vector vFrames; 95 | LoadFrameNames(framesFileName, vFrames); 96 | int nImages = vFrames.size(); 97 | 98 | cout << "Image converting: [0 - 100%]" << endl; 99 | cout << "[ ]" << endl; 100 | cout << " "; 101 | 102 | Mat frame; 103 | for (int i = 0, n = 1; i < nImages; ++i) 104 | { 105 | if (!cap.read(frame)) 106 | break; 107 | 108 | string imgName = workDir + "cam0/" + to_string(vFrames[i]) + ".jpg"; 109 | imwrite(imgName, frame); 110 | 111 | if (i + 1 >= (nImages / 100.) * n) 112 | { 113 | cout << "."; 114 | ++n; 115 | } 116 | } 117 | 118 | cout << " " << endl; 119 | 120 | //----------------------------------------------------------------------------- 121 | vector vImus; 122 | string accGyroFile = workDir + "accel-gyro.txt"; 123 | if(LoadImus2(accGyroFile, vImus)) 124 | { 125 | int nImus = vImus.size(); 126 | 127 | string newImuName = workDir; 128 | newImuName += "imu0.csv"; 129 | ofstream fOutImu; 130 | fOutImu.open(newImuName.c_str(), std::ofstream::out | std::ofstream::trunc); 131 | for (int ni = 0; ni < nImus; ni++) 132 | { 133 | fOutImu << vImus[ni].toString() << "\n"; 134 | } 135 | fOutImu.close(); 136 | } 137 | //----------------------------------------------------------------------------- 138 | 139 | return 0; 140 | } 141 | void LoadFrameNames(const string &strFramesFile, vector &vFrames) 142 | { 143 | ifstream fFrames; 144 | fFrames.open(strFramesFile.c_str()); 145 | 146 | vFrames.reserve(10000); 147 | 148 | while (!fFrames.eof()) 149 | { 150 | string s; 151 | getline(fFrames, s); 152 | if (!s.empty()) 153 | { 154 | stringstream ss; 155 | ss << s; 156 | 157 | string s2; 158 | getline(ss, s2, ','); 159 | 160 | double t = std::stod(s2); 161 | long long it = (long long)(t * 1e6); 162 | it = it * 1000; 163 | vFrames.push_back(it); 164 | } 165 | } 166 | 167 | fFrames.close(); 168 | } 169 | 170 | bool LoadImus2(const string &strAccelGyroFile, vector &vImus) 171 | { 172 | ifstream fImus(strAccelGyroFile.c_str()); 173 | if (!fImus) 174 | return false; 175 | vImus.reserve(40000); 176 | while (!fImus.eof()) 177 | { 178 | string s; 179 | getline(fImus, s); 180 | if (!s.empty()) 181 | { 182 | char c = s.at(0); 183 | if (c<'0' || c>'9') 184 | continue; 185 | 186 | stringstream ss; 187 | ss << s; 188 | double tmpd; 189 | int cnt = 0; 190 | double data[10]; // timestamp, wx,wy,wz, ax,ay,az 191 | while (ss >> tmpd) 192 | { 193 | data[cnt] = tmpd; 194 | cnt++; 195 | if (cnt == 7) 196 | break; 197 | if (ss.peek() == ',' || ss.peek() == ' ') 198 | ss.ignore(); 199 | } 200 | //data[0] *= 1e-9; 201 | IMUData imudata(data[1], data[2], data[3], 202 | data[4], data[5], data[6], data[0]); 203 | vImus.push_back(imudata); 204 | } 205 | } 206 | return true; 207 | } 208 | -------------------------------------------------------------------------------- /ios_logger.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 50; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 0438790E21343D060004FA3E /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 0438790D21343D060004FA3E /* AppDelegate.m */; }; 11 | 0438791121343D060004FA3E /* ViewController.mm in Sources */ = {isa = PBXBuildFile; fileRef = 0438791021343D060004FA3E /* ViewController.mm */; }; 12 | 0438791421343D060004FA3E /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0438791221343D060004FA3E /* Main.storyboard */; }; 13 | 0438791621343D0C0004FA3E /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 0438791521343D0C0004FA3E /* Assets.xcassets */; }; 14 | 0438791921343D0C0004FA3E /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 0438791721343D0C0004FA3E /* LaunchScreen.storyboard */; }; 15 | 0438791C21343D0C0004FA3E /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 0438791B21343D0C0004FA3E /* main.m */; }; 16 | 0438792821344EC30004FA3E /* CoreLocation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0438792721344EC30004FA3E /* CoreLocation.framework */; }; 17 | 0438792A21344ECA0004FA3E /* CoreMotion.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0438792921344ECA0004FA3E /* CoreMotion.framework */; }; 18 | E6079DCE21A6D8BA0079A3C8 /* AVFoundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E6079DCD21A6D8BA0079A3C8 /* AVFoundation.framework */; }; 19 | E6079DDA21A6DAD30079A3C8 /* CoreMedia.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E6079DD921A6DAD30079A3C8 /* CoreMedia.framework */; }; 20 | E6F130D02506423A00CEBFD4 /* ARKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = E6F130CF2506423A00CEBFD4 /* ARKit.framework */; }; 21 | /* End PBXBuildFile section */ 22 | 23 | /* Begin PBXFileReference section */ 24 | 0438790921343D060004FA3E /* ios logger.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "ios logger.app"; sourceTree = BUILT_PRODUCTS_DIR; }; 25 | 0438790C21343D060004FA3E /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 26 | 0438790D21343D060004FA3E /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 27 | 0438790F21343D060004FA3E /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 28 | 0438791021343D060004FA3E /* ViewController.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = ViewController.mm; sourceTree = ""; }; 29 | 0438791321343D060004FA3E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 30 | 0438791521343D0C0004FA3E /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 31 | 0438791821343D0C0004FA3E /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 32 | 0438791A21343D0C0004FA3E /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 33 | 0438791B21343D0C0004FA3E /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 34 | 0438792721344EC30004FA3E /* CoreLocation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreLocation.framework; path = System/Library/Frameworks/CoreLocation.framework; sourceTree = SDKROOT; }; 35 | 0438792921344ECA0004FA3E /* CoreMotion.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMotion.framework; path = System/Library/Frameworks/CoreMotion.framework; sourceTree = SDKROOT; }; 36 | E6079DCD21A6D8BA0079A3C8 /* AVFoundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AVFoundation.framework; path = System/Library/Frameworks/AVFoundation.framework; sourceTree = SDKROOT; }; 37 | E6079DD921A6DAD30079A3C8 /* CoreMedia.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreMedia.framework; path = System/Library/Frameworks/CoreMedia.framework; sourceTree = SDKROOT; }; 38 | E6F130CF2506423A00CEBFD4 /* ARKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ARKit.framework; path = System/Library/Frameworks/ARKit.framework; sourceTree = SDKROOT; }; 39 | /* End PBXFileReference section */ 40 | 41 | /* Begin PBXFrameworksBuildPhase section */ 42 | 0438790621343D060004FA3E /* Frameworks */ = { 43 | isa = PBXFrameworksBuildPhase; 44 | buildActionMask = 2147483647; 45 | files = ( 46 | E6F130D02506423A00CEBFD4 /* ARKit.framework in Frameworks */, 47 | E6079DDA21A6DAD30079A3C8 /* CoreMedia.framework in Frameworks */, 48 | E6079DCE21A6D8BA0079A3C8 /* AVFoundation.framework in Frameworks */, 49 | 0438792A21344ECA0004FA3E /* CoreMotion.framework in Frameworks */, 50 | 0438792821344EC30004FA3E /* CoreLocation.framework in Frameworks */, 51 | ); 52 | runOnlyForDeploymentPostprocessing = 0; 53 | }; 54 | /* End PBXFrameworksBuildPhase section */ 55 | 56 | /* Begin PBXGroup section */ 57 | 0438790021343D060004FA3E = { 58 | isa = PBXGroup; 59 | children = ( 60 | 0438790B21343D060004FA3E /* ios_logger */, 61 | 0438790A21343D060004FA3E /* Products */, 62 | 0438792221344EAB0004FA3E /* Frameworks */, 63 | ); 64 | sourceTree = ""; 65 | }; 66 | 0438790A21343D060004FA3E /* Products */ = { 67 | isa = PBXGroup; 68 | children = ( 69 | 0438790921343D060004FA3E /* ios logger.app */, 70 | ); 71 | name = Products; 72 | sourceTree = ""; 73 | }; 74 | 0438790B21343D060004FA3E /* ios_logger */ = { 75 | isa = PBXGroup; 76 | children = ( 77 | 0438790C21343D060004FA3E /* AppDelegate.h */, 78 | 0438790D21343D060004FA3E /* AppDelegate.m */, 79 | 0438790F21343D060004FA3E /* ViewController.h */, 80 | 0438791021343D060004FA3E /* ViewController.mm */, 81 | 0438791221343D060004FA3E /* Main.storyboard */, 82 | 0438791521343D0C0004FA3E /* Assets.xcassets */, 83 | 0438791721343D0C0004FA3E /* LaunchScreen.storyboard */, 84 | 0438791A21343D0C0004FA3E /* Info.plist */, 85 | 0438791B21343D0C0004FA3E /* main.m */, 86 | ); 87 | path = ios_logger; 88 | sourceTree = ""; 89 | }; 90 | 0438792221344EAB0004FA3E /* Frameworks */ = { 91 | isa = PBXGroup; 92 | children = ( 93 | E6F130CF2506423A00CEBFD4 /* ARKit.framework */, 94 | E6079DCD21A6D8BA0079A3C8 /* AVFoundation.framework */, 95 | E6079DD921A6DAD30079A3C8 /* CoreMedia.framework */, 96 | 0438792921344ECA0004FA3E /* CoreMotion.framework */, 97 | 0438792721344EC30004FA3E /* CoreLocation.framework */, 98 | ); 99 | name = Frameworks; 100 | sourceTree = ""; 101 | }; 102 | /* End PBXGroup section */ 103 | 104 | /* Begin PBXNativeTarget section */ 105 | 0438790821343D060004FA3E /* ios_logger */ = { 106 | isa = PBXNativeTarget; 107 | buildConfigurationList = 0438791F21343D0C0004FA3E /* Build configuration list for PBXNativeTarget "ios_logger" */; 108 | buildPhases = ( 109 | 0438790521343D060004FA3E /* Sources */, 110 | 0438790621343D060004FA3E /* Frameworks */, 111 | 0438790721343D060004FA3E /* Resources */, 112 | ); 113 | buildRules = ( 114 | ); 115 | dependencies = ( 116 | ); 117 | name = ios_logger; 118 | productName = cig_logger; 119 | productReference = 0438790921343D060004FA3E /* ios logger.app */; 120 | productType = "com.apple.product-type.application"; 121 | }; 122 | /* End PBXNativeTarget section */ 123 | 124 | /* Begin PBXProject section */ 125 | 0438790121343D060004FA3E /* Project object */ = { 126 | isa = PBXProject; 127 | attributes = { 128 | LastUpgradeCheck = 0940; 129 | ORGANIZATIONNAME = Mac; 130 | TargetAttributes = { 131 | 0438790821343D060004FA3E = { 132 | CreatedOnToolsVersion = 9.4.1; 133 | }; 134 | }; 135 | }; 136 | buildConfigurationList = 0438790421343D060004FA3E /* Build configuration list for PBXProject "ios_logger" */; 137 | compatibilityVersion = "Xcode 9.3"; 138 | developmentRegion = en; 139 | hasScannedForEncodings = 0; 140 | knownRegions = ( 141 | en, 142 | Base, 143 | ); 144 | mainGroup = 0438790021343D060004FA3E; 145 | productRefGroup = 0438790A21343D060004FA3E /* Products */; 146 | projectDirPath = ""; 147 | projectRoot = ""; 148 | targets = ( 149 | 0438790821343D060004FA3E /* ios_logger */, 150 | ); 151 | }; 152 | /* End PBXProject section */ 153 | 154 | /* Begin PBXResourcesBuildPhase section */ 155 | 0438790721343D060004FA3E /* Resources */ = { 156 | isa = PBXResourcesBuildPhase; 157 | buildActionMask = 2147483647; 158 | files = ( 159 | 0438791921343D0C0004FA3E /* LaunchScreen.storyboard in Resources */, 160 | 0438791621343D0C0004FA3E /* Assets.xcassets in Resources */, 161 | 0438791421343D060004FA3E /* Main.storyboard in Resources */, 162 | ); 163 | runOnlyForDeploymentPostprocessing = 0; 164 | }; 165 | /* End PBXResourcesBuildPhase section */ 166 | 167 | /* Begin PBXSourcesBuildPhase section */ 168 | 0438790521343D060004FA3E /* Sources */ = { 169 | isa = PBXSourcesBuildPhase; 170 | buildActionMask = 2147483647; 171 | files = ( 172 | 0438791121343D060004FA3E /* ViewController.mm in Sources */, 173 | 0438791C21343D0C0004FA3E /* main.m in Sources */, 174 | 0438790E21343D060004FA3E /* AppDelegate.m in Sources */, 175 | ); 176 | runOnlyForDeploymentPostprocessing = 0; 177 | }; 178 | /* End PBXSourcesBuildPhase section */ 179 | 180 | /* Begin PBXVariantGroup section */ 181 | 0438791221343D060004FA3E /* Main.storyboard */ = { 182 | isa = PBXVariantGroup; 183 | children = ( 184 | 0438791321343D060004FA3E /* Base */, 185 | ); 186 | name = Main.storyboard; 187 | sourceTree = ""; 188 | }; 189 | 0438791721343D0C0004FA3E /* LaunchScreen.storyboard */ = { 190 | isa = PBXVariantGroup; 191 | children = ( 192 | 0438791821343D0C0004FA3E /* Base */, 193 | ); 194 | name = LaunchScreen.storyboard; 195 | sourceTree = ""; 196 | }; 197 | /* End PBXVariantGroup section */ 198 | 199 | /* Begin XCBuildConfiguration section */ 200 | 0438791D21343D0C0004FA3E /* Debug */ = { 201 | isa = XCBuildConfiguration; 202 | buildSettings = { 203 | ALWAYS_SEARCH_USER_PATHS = NO; 204 | CLANG_ANALYZER_NONNULL = YES; 205 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 206 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 207 | CLANG_CXX_LIBRARY = "libc++"; 208 | CLANG_ENABLE_MODULES = YES; 209 | CLANG_ENABLE_OBJC_ARC = YES; 210 | CLANG_ENABLE_OBJC_WEAK = YES; 211 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 212 | CLANG_WARN_BOOL_CONVERSION = YES; 213 | CLANG_WARN_COMMA = YES; 214 | CLANG_WARN_CONSTANT_CONVERSION = YES; 215 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 216 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 217 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 218 | CLANG_WARN_EMPTY_BODY = YES; 219 | CLANG_WARN_ENUM_CONVERSION = YES; 220 | CLANG_WARN_INFINITE_RECURSION = YES; 221 | CLANG_WARN_INT_CONVERSION = YES; 222 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 223 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 224 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 225 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 226 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 227 | CLANG_WARN_STRICT_PROTOTYPES = YES; 228 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 229 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 230 | CLANG_WARN_UNREACHABLE_CODE = YES; 231 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 232 | CODE_SIGN_IDENTITY = "iPhone Developer"; 233 | COPY_PHASE_STRIP = NO; 234 | DEBUG_INFORMATION_FORMAT = dwarf; 235 | ENABLE_STRICT_OBJC_MSGSEND = YES; 236 | ENABLE_TESTABILITY = YES; 237 | GCC_C_LANGUAGE_STANDARD = gnu11; 238 | GCC_DYNAMIC_NO_PIC = NO; 239 | GCC_NO_COMMON_BLOCKS = YES; 240 | GCC_OPTIMIZATION_LEVEL = 0; 241 | GCC_PREPROCESSOR_DEFINITIONS = ( 242 | "DEBUG=1", 243 | "$(inherited)", 244 | ); 245 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 246 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 247 | GCC_WARN_UNDECLARED_SELECTOR = YES; 248 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 249 | GCC_WARN_UNUSED_FUNCTION = YES; 250 | GCC_WARN_UNUSED_VARIABLE = YES; 251 | IPHONEOS_DEPLOYMENT_TARGET = 11.3; 252 | MTL_ENABLE_DEBUG_INFO = YES; 253 | ONLY_ACTIVE_ARCH = YES; 254 | SDKROOT = iphoneos; 255 | }; 256 | name = Debug; 257 | }; 258 | 0438791E21343D0C0004FA3E /* Release */ = { 259 | isa = XCBuildConfiguration; 260 | buildSettings = { 261 | ALWAYS_SEARCH_USER_PATHS = NO; 262 | CLANG_ANALYZER_NONNULL = YES; 263 | CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE; 264 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++14"; 265 | CLANG_CXX_LIBRARY = "libc++"; 266 | CLANG_ENABLE_MODULES = YES; 267 | CLANG_ENABLE_OBJC_ARC = YES; 268 | CLANG_ENABLE_OBJC_WEAK = YES; 269 | CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES; 270 | CLANG_WARN_BOOL_CONVERSION = YES; 271 | CLANG_WARN_COMMA = YES; 272 | CLANG_WARN_CONSTANT_CONVERSION = YES; 273 | CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 274 | CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; 275 | CLANG_WARN_DOCUMENTATION_COMMENTS = YES; 276 | CLANG_WARN_EMPTY_BODY = YES; 277 | CLANG_WARN_ENUM_CONVERSION = YES; 278 | CLANG_WARN_INFINITE_RECURSION = YES; 279 | CLANG_WARN_INT_CONVERSION = YES; 280 | CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES; 281 | CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; 282 | CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; 283 | CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; 284 | CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; 285 | CLANG_WARN_STRICT_PROTOTYPES = YES; 286 | CLANG_WARN_SUSPICIOUS_MOVE = YES; 287 | CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE; 288 | CLANG_WARN_UNREACHABLE_CODE = YES; 289 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 290 | CODE_SIGN_IDENTITY = "iPhone Developer"; 291 | COPY_PHASE_STRIP = NO; 292 | DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; 293 | ENABLE_NS_ASSERTIONS = NO; 294 | ENABLE_STRICT_OBJC_MSGSEND = YES; 295 | GCC_C_LANGUAGE_STANDARD = gnu11; 296 | GCC_NO_COMMON_BLOCKS = YES; 297 | GCC_WARN_64_TO_32_BIT_CONVERSION = YES; 298 | GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; 299 | GCC_WARN_UNDECLARED_SELECTOR = YES; 300 | GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; 301 | GCC_WARN_UNUSED_FUNCTION = YES; 302 | GCC_WARN_UNUSED_VARIABLE = YES; 303 | IPHONEOS_DEPLOYMENT_TARGET = 11.3; 304 | MTL_ENABLE_DEBUG_INFO = NO; 305 | SDKROOT = iphoneos; 306 | VALIDATE_PRODUCT = YES; 307 | }; 308 | name = Release; 309 | }; 310 | 0438792021343D0C0004FA3E /* Debug */ = { 311 | isa = XCBuildConfiguration; 312 | buildSettings = { 313 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 314 | CODE_SIGN_STYLE = Automatic; 315 | DEVELOPMENT_TEAM = ""; 316 | FRAMEWORK_SEARCH_PATHS = "\"$(SRCROOT)\""; 317 | INFOPLIST_FILE = ios_logger/Info.plist; 318 | IPHONEOS_DEPLOYMENT_TARGET = 11.3; 319 | LD_RUNPATH_SEARCH_PATHS = ( 320 | "$(inherited)", 321 | "@executable_path/Frameworks", 322 | ); 323 | MARKETING_VERSION = 0.2; 324 | PRODUCT_BUNDLE_IDENTIFIER = "idn.ios-logger"; 325 | PRODUCT_NAME = "ios logger"; 326 | TARGETED_DEVICE_FAMILY = "1,2"; 327 | }; 328 | name = Debug; 329 | }; 330 | 0438792121343D0C0004FA3E /* Release */ = { 331 | isa = XCBuildConfiguration; 332 | buildSettings = { 333 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 334 | CODE_SIGN_STYLE = Automatic; 335 | DEVELOPMENT_TEAM = ""; 336 | FRAMEWORK_SEARCH_PATHS = "\"$(SRCROOT)\""; 337 | INFOPLIST_FILE = ios_logger/Info.plist; 338 | IPHONEOS_DEPLOYMENT_TARGET = 11.3; 339 | LD_RUNPATH_SEARCH_PATHS = ( 340 | "$(inherited)", 341 | "@executable_path/Frameworks", 342 | ); 343 | MARKETING_VERSION = 0.2; 344 | PRODUCT_BUNDLE_IDENTIFIER = "idn.ios-logger"; 345 | PRODUCT_NAME = "ios logger"; 346 | TARGETED_DEVICE_FAMILY = "1,2"; 347 | }; 348 | name = Release; 349 | }; 350 | /* End XCBuildConfiguration section */ 351 | 352 | /* Begin XCConfigurationList section */ 353 | 0438790421343D060004FA3E /* Build configuration list for PBXProject "ios_logger" */ = { 354 | isa = XCConfigurationList; 355 | buildConfigurations = ( 356 | 0438791D21343D0C0004FA3E /* Debug */, 357 | 0438791E21343D0C0004FA3E /* Release */, 358 | ); 359 | defaultConfigurationIsVisible = 0; 360 | defaultConfigurationName = Release; 361 | }; 362 | 0438791F21343D0C0004FA3E /* Build configuration list for PBXNativeTarget "ios_logger" */ = { 363 | isa = XCConfigurationList; 364 | buildConfigurations = ( 365 | 0438792021343D0C0004FA3E /* Debug */, 366 | 0438792121343D0C0004FA3E /* Release */, 367 | ); 368 | defaultConfigurationIsVisible = 0; 369 | defaultConfigurationName = Release; 370 | }; 371 | /* End XCConfigurationList section */ 372 | }; 373 | rootObject = 0438790121343D060004FA3E /* Project object */; 374 | } 375 | -------------------------------------------------------------------------------- /ios_logger.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /ios_logger.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | IDEDidComputeMac32BitWarning 6 | 7 | 8 | 9 | -------------------------------------------------------------------------------- /ios_logger.xcodeproj/xcuserdata/mac.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | cig_logger.xcscheme 8 | 9 | orderHint 10 | 0 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /ios_logger.xcodeproj/xcuserdata/macvmws.xcuserdatad/xcschemes/xcschememanagement.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | SchemeUserState 6 | 7 | cig_logger.xcscheme_^#shared#^_ 8 | 9 | orderHint 10 | 0 11 | 12 | ios_logger.xcscheme_^#shared#^_ 13 | 14 | orderHint 15 | 0 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /ios_logger/AppDelegate.h: -------------------------------------------------------------------------------- 1 | #import 2 | 3 | @interface AppDelegate : UIResponder 4 | 5 | @property (strong, nonatomic) UIWindow *window; 6 | 7 | 8 | @end 9 | 10 | -------------------------------------------------------------------------------- /ios_logger/AppDelegate.m: -------------------------------------------------------------------------------- 1 | #import "AppDelegate.h" 2 | 3 | @interface AppDelegate () 4 | 5 | @end 6 | 7 | @implementation AppDelegate 8 | 9 | 10 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { 11 | // Override point for customization after application launch. 12 | return YES; 13 | } 14 | 15 | 16 | - (void)applicationWillResignActive:(UIApplication *)application { 17 | // 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. 18 | // Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game. 19 | } 20 | 21 | 22 | - (void)applicationDidEnterBackground:(UIApplication *)application { 23 | // 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. 24 | // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 25 | } 26 | 27 | 28 | - (void)applicationWillEnterForeground:(UIApplication *)application { 29 | // 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. 30 | } 31 | 32 | 33 | - (void)applicationDidBecomeActive:(UIApplication *)application { 34 | // 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. 35 | } 36 | 37 | 38 | - (void)applicationWillTerminate:(UIApplication *)application { 39 | // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 40 | } 41 | 42 | 43 | @end 44 | -------------------------------------------------------------------------------- /ios_logger/Assets.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "size" : "20x20", 5 | "idiom" : "iphone", 6 | "filename" : "Icon-App-20x20@2x.png", 7 | "scale" : "2x" 8 | }, 9 | { 10 | "size" : "20x20", 11 | "idiom" : "iphone", 12 | "filename" : "Icon-App-20x20@3x.png", 13 | "scale" : "3x" 14 | }, 15 | { 16 | "size" : "29x29", 17 | "idiom" : "iphone", 18 | "filename" : "Icon-App-29x29@2x.png", 19 | "scale" : "2x" 20 | }, 21 | { 22 | "size" : "29x29", 23 | "idiom" : "iphone", 24 | "filename" : "Icon-App-29x29@3x.png", 25 | "scale" : "3x" 26 | }, 27 | { 28 | "size" : "40x40", 29 | "idiom" : "iphone", 30 | "filename" : "Icon-App-40x40@2x.png", 31 | "scale" : "2x" 32 | }, 33 | { 34 | "size" : "40x40", 35 | "idiom" : "iphone", 36 | "filename" : "Icon-App-40x40@3x.png", 37 | "scale" : "3x" 38 | }, 39 | { 40 | "size" : "60x60", 41 | "idiom" : "iphone", 42 | "filename" : "Icon-App-60x60@2x.png", 43 | "scale" : "2x" 44 | }, 45 | { 46 | "size" : "60x60", 47 | "idiom" : "iphone", 48 | "filename" : "Icon-App-60x60@3x.png", 49 | "scale" : "3x" 50 | }, 51 | { 52 | "size" : "20x20", 53 | "idiom" : "ipad", 54 | "filename" : "Icon-App-20x20@1x.png", 55 | "scale" : "1x" 56 | }, 57 | { 58 | "size" : "20x20", 59 | "idiom" : "ipad", 60 | "filename" : "Icon-App-20x20@2x-1.png", 61 | "scale" : "2x" 62 | }, 63 | { 64 | "size" : "29x29", 65 | "idiom" : "ipad", 66 | "filename" : "Icon-App-29x29@1x.png", 67 | "scale" : "1x" 68 | }, 69 | { 70 | "size" : "29x29", 71 | "idiom" : "ipad", 72 | "filename" : "Icon-App-29x29@2x-1.png", 73 | "scale" : "2x" 74 | }, 75 | { 76 | "size" : "40x40", 77 | "idiom" : "ipad", 78 | "filename" : "Icon-App-40x40@1x.png", 79 | "scale" : "1x" 80 | }, 81 | { 82 | "size" : "40x40", 83 | "idiom" : "ipad", 84 | "filename" : "Icon-App-40x40@2x-1.png", 85 | "scale" : "2x" 86 | }, 87 | { 88 | "size" : "76x76", 89 | "idiom" : "ipad", 90 | "filename" : "Icon-App-76x76@1x.png", 91 | "scale" : "1x" 92 | }, 93 | { 94 | "size" : "76x76", 95 | "idiom" : "ipad", 96 | "filename" : "Icon-App-76x76@2x.png", 97 | "scale" : "2x" 98 | }, 99 | { 100 | "size" : "83.5x83.5", 101 | "idiom" : "ipad", 102 | "filename" : "Icon-App-83.5x83.5@2x.png", 103 | "scale" : "2x" 104 | }, 105 | { 106 | "size" : "1024x1024", 107 | "idiom" : "ios-marketing", 108 | "filename" : "ItunesArtwork@2x.png", 109 | "scale" : "1x" 110 | } 111 | ], 112 | "info" : { 113 | "version" : 1, 114 | "author" : "xcode" 115 | } 116 | } -------------------------------------------------------------------------------- /ios_logger/Assets.xcassets/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "info" : { 3 | "version" : 1, 4 | "author" : "xcode" 5 | } 6 | } -------------------------------------------------------------------------------- /ios_logger/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 | -------------------------------------------------------------------------------- /ios_logger/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 | 28 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 58 | 66 | 73 | 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 | 110 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 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 | -------------------------------------------------------------------------------- /ios_logger/Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | $(DEVELOPMENT_LANGUAGE) 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 | $(MARKETING_VERSION) 19 | CFBundleVersion 20 | 1 21 | LSRequiresIPhoneOS 22 | 23 | NSCameraUsageDescription 24 | To use camera 25 | NSLocationWhenInUseUsageDescription 26 | To use gps 27 | UIFileSharingEnabled 28 | 29 | UILaunchStoryboardName 30 | LaunchScreen 31 | UIMainStoryboardFile 32 | Main 33 | UIMainStoryboardFile~ipad 34 | Main 35 | UIRequiredDeviceCapabilities 36 | 37 | video-camera 38 | magnetometer 39 | gyroscope 40 | accelerometer 41 | location-services 42 | arm64 43 | 44 | UIRequiresFullScreen 45 | 46 | UISupportedInterfaceOrientations 47 | 48 | UIInterfaceOrientationLandscapeRight 49 | 50 | UISupportedInterfaceOrientations~ipad 51 | 52 | UIInterfaceOrientationLandscapeRight 53 | 54 | 55 | 56 | -------------------------------------------------------------------------------- /ios_logger/ViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.h 3 | // cig_logger 4 | // 5 | // Created by Mac on 27/08/2018. 6 | // Copyright © 2018 Mac. All rights reserved. 7 | // 8 | 9 | #import 10 | #import 11 | #import 12 | #import 13 | 14 | @interface ViewController : UIViewController 15 | { 16 | __weak IBOutlet UIImageView *imageView; 17 | __weak IBOutlet UIButton *button; 18 | __weak IBOutlet UILabel *runTimeLabel; 19 | __weak IBOutlet UIButton *afButton; 20 | __weak IBOutlet UILabel *afLabel; 21 | __weak IBOutlet UISlider *afSlider; 22 | __weak IBOutlet UISegmentedControl *segmentedControl; 23 | __weak IBOutlet UISwitch *accgyroSwitch; 24 | __weak IBOutlet UISwitch *gpsheadSwitch; 25 | __weak IBOutlet UISwitch *motionSwitch; 26 | __weak IBOutlet UISwitch *magnetSwitch; 27 | 28 | AVCaptureSession *session; 29 | AVCaptureDevice *device; 30 | AVCaptureDeviceInput *input; 31 | AVCaptureVideoDataOutput *output; 32 | dispatch_queue_t sbfQueue; 33 | 34 | ARSession *arSession; 35 | ARWorldTrackingConfiguration *arConfiguration; 36 | 37 | CALayer *viewLayer; 38 | AVCaptureVideoPreviewLayer *captureVideoPreviewLayer; 39 | 40 | CMMotionManager *motionManager; 41 | CLLocationManager *locationManager; 42 | 43 | CLLocation *locationData; 44 | CLHeading *headingData; 45 | 46 | bool isRecording; 47 | bool isStarted; 48 | bool isAf; 49 | 50 | NSString *theDate; 51 | NSDateFormatter *dateFormat; 52 | 53 | double FPS; 54 | double imuFreq; 55 | 56 | NSOperationQueue *accelgyroQueue; 57 | NSOperationQueue *motionQueue; 58 | NSOperationQueue *magnetQueue; 59 | 60 | NSMutableString *logStringAccel; 61 | NSMutableString *logStringGyro; 62 | NSMutableString *logStringMotion; //mot 63 | NSMutableString *logStringMotARH; //mot 64 | NSMutableString *logStringMotMagnFull; //mot 65 | NSMutableString *logStringMagnet; //mag 66 | NSMutableString *logStringGps; //gps 67 | NSMutableString *logStringHeading; //gps 68 | NSMutableString *logStringFrameStamps; 69 | NSMutableString *logStringArPose; //arkit 70 | 71 | AVAssetWriter *assetWriter; 72 | AVAssetWriterInput *assetWriterInput; 73 | AVAssetWriterInputPixelBufferAdaptor *assetWriterInputPixelBufferAdaptor; 74 | unsigned long frameNum; 75 | 76 | float lensPosition; 77 | 78 | //---------------- 79 | CGFloat fr_height; 80 | CGFloat fr_width; 81 | 82 | NSTimeInterval bootTime; 83 | 84 | NSTimer *_timer; 85 | int iTimer; 86 | 87 | int ireduceFps; 88 | int reduseFpsInNTimes; 89 | 90 | double prevFrTs; 91 | } 92 | 93 | - (IBAction)toggleButton:(id)sender; 94 | - (IBAction)toggleAfButton:(id)sender; 95 | - (IBAction)afSliderValueChanged:(id)sender; 96 | - (IBAction)afSliderEndEditing:(id)sender; 97 | - (IBAction)segmentedControlValueChanged:(UISegmentedControl *)sender; 98 | - (IBAction)accgyroSwChanged:(UISwitch *)sender; 99 | - (IBAction)gpsheadSwChanged:(UISwitch *)sender; 100 | - (IBAction)motionSwChanged:(UISwitch *)sender; 101 | - (IBAction)magnetSwChanged:(UISwitch *)sender; 102 | 103 | @end 104 | -------------------------------------------------------------------------------- /ios_logger/ViewController.mm: -------------------------------------------------------------------------------- 1 | // 2 | // ViewController.m 3 | // cig_logger 4 | // 5 | // Created by Mac on 27/08/2018. 6 | // Copyright © 2018 Mac. All rights reserved. 7 | // 8 | //-------------------------------------------- 9 | 10 | #import "ViewController.h" 11 | 12 | @interface ViewController () 13 | { 14 | 15 | } 16 | 17 | @end 18 | 19 | @implementation ViewController 20 | 21 | - (void)viewDidLoad { 22 | [super viewDidLoad]; 23 | // Do any additional setup after loading the view, typically from a nib 24 | //std::cout << "*** opencv version " << CV_VERSION << std::endl; 25 | //-------- 26 | FPS = 30; 27 | imuFreq = 100; 28 | 29 | lensPosition = afSlider.value; 30 | afLabel.text = [NSString stringWithFormat:@"%5.3f",afSlider.value]; 31 | 32 | dateFormat = [[NSDateFormatter alloc] init]; 33 | [dateFormat setDateFormat:@"yyyy-MM-dd'T'HH-mm-ss"]; //"dd-MM-yyyy-HH-mm-SS" 34 | 35 | locationData = nil; 36 | headingData = nil; 37 | 38 | arSession = nil; 39 | arConfiguration = nil; 40 | 41 | logStringAccel = [NSMutableString stringWithString: @""]; 42 | logStringGyro = [NSMutableString stringWithString: @""]; 43 | logStringMotion = [NSMutableString stringWithString: @""]; 44 | logStringMotARH = [NSMutableString stringWithString: @""]; 45 | logStringMotMagnFull = [NSMutableString stringWithString: @""]; 46 | logStringMagnet = [NSMutableString stringWithString: @""]; 47 | logStringGps = [NSMutableString stringWithString: @""]; 48 | logStringHeading = [NSMutableString stringWithString: @""]; 49 | logStringFrameStamps = [NSMutableString stringWithString: @""]; 50 | logStringArPose = [NSMutableString stringWithString: @""]; 51 | 52 | fr_height = MAX(self.view.frame.size.width, self.view.frame.size.height); 53 | fr_width = MIN(self.view.frame.size.width, self.view.frame.size.height); 54 | 55 | isRecording = false; 56 | isStarted = false; 57 | 58 | bootTime = [[NSDate date] timeIntervalSince1970] - [[NSProcessInfo processInfo] systemUptime]; 59 | 60 | reduseFpsInNTimes = 1; 61 | 62 | prevFrTs = -1.0; 63 | 64 | //-------- 65 | motionManager = [[CMMotionManager alloc] init]; 66 | motionManager.gyroUpdateInterval = 1./imuFreq; 67 | motionManager.accelerometerUpdateInterval = 1./imuFreq; 68 | motionManager.deviceMotionUpdateInterval = 1./imuFreq; 69 | 70 | locationManager = [[CLLocationManager alloc] init]; 71 | locationManager.delegate = self; 72 | locationManager.distanceFilter = kCLDistanceFilterNone; 73 | locationManager.desiredAccuracy = kCLLocationAccuracyBest; 74 | 75 | locationManager.headingOrientation = CLDeviceOrientationLandscapeLeft; //Left - "with the device held upright and the home button on the right side" 76 | locationManager.headingFilter = kCLHeadingFilterNone; 77 | 78 | if ([locationManager respondsToSelector:@selector(requestWhenInUseAuthorization)]) { 79 | [locationManager requestWhenInUseAuthorization]; 80 | } 81 | 82 | accelgyroQueue = [[NSOperationQueue alloc] init]; 83 | motionQueue = [[NSOperationQueue alloc] init]; 84 | magnetQueue = [[NSOperationQueue alloc] init]; 85 | 86 | [self accgyroSwChanged:accgyroSwitch]; 87 | [self gpsheadSwChanged:gpsheadSwitch]; 88 | [self motionSwChanged:motionSwitch]; 89 | [self magnetSwChanged:magnetSwitch]; 90 | //****************************** 91 | session = [AVCaptureSession new]; 92 | 93 | device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo]; 94 | 95 | NSError *error = nil; 96 | input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&error]; 97 | if (!input){ 98 | dispatch_async(dispatch_get_main_queue(), ^{ 99 | UIAlertController * alert = [UIAlertController 100 | alertControllerWithTitle:@"Error" 101 | message:[NSString stringWithFormat:@"AVCaptureDeviceInput: %@", error] 102 | preferredStyle:UIAlertControllerStyleAlert]; 103 | 104 | UIAlertAction* okButton = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action){}]; 105 | [alert addAction:okButton]; 106 | [self presentViewController:alert animated:YES completion:nil]; 107 | }); 108 | } 109 | 110 | [session addInput:input]; 111 | 112 | output = [AVCaptureVideoDataOutput new]; 113 | 114 | NSDictionary *newSettings = @{ (NSString *)kCVPixelBufferPixelFormatTypeKey : @(kCVPixelFormatType_32BGRA) }; 115 | output.videoSettings = newSettings; 116 | 117 | [session addOutput:output]; 118 | 119 | sbfQueue = dispatch_queue_create("MyQueue", NULL); 120 | [output setSampleBufferDelegate:self queue:sbfQueue]; 121 | 122 | [device lockForConfiguration:nil]; 123 | 124 | device.activeVideoMinFrameDuration = CMTimeMake(1, FPS); 125 | device.activeVideoMaxFrameDuration = CMTimeMake(1, FPS); 126 | 127 | [device setFocusModeLockedWithLensPosition:lensPosition completionHandler:nil]; 128 | [device unlockForConfiguration]; 129 | 130 | NSString *mediaType = AVMediaTypeVideo; 131 | [AVCaptureDevice requestAccessForMediaType:mediaType completionHandler:^(BOOL granted) { 132 | if (!granted){ 133 | //Not granted access to mediaType 134 | dispatch_async(dispatch_get_main_queue(), ^{ 135 | UIAlertController * alert = [UIAlertController 136 | alertControllerWithTitle:@"Error" 137 | message:@"AVCapture doesn't have permission to use camera" 138 | preferredStyle:UIAlertControllerStyleAlert]; 139 | 140 | UIAlertAction* okButton = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action){}]; 141 | [alert addAction:okButton]; 142 | [self presentViewController:alert animated:YES completion:nil]; 143 | }); 144 | } 145 | }]; 146 | 147 | NSArray<__kindof AVCaptureOutput *> *_outputs = session.outputs; 148 | for (int i = 0; i < [_outputs count]; ++i) { 149 | NSArray *_connections = _outputs[i].connections; 150 | for (int j = 0; j < [_connections count]; ++j) { 151 | if(_connections[j].isCameraIntrinsicMatrixDeliverySupported) 152 | _connections[j].cameraIntrinsicMatrixDeliveryEnabled = true; 153 | } 154 | } 155 | 156 | //****************************** 157 | if(ARWorldTrackingConfiguration.isSupported){ 158 | arConfiguration = [[ARWorldTrackingConfiguration alloc] init]; 159 | arConfiguration.worldAlignment = ARWorldAlignmentGravity;//ARWorldAlignmentGravityAndHeading; 160 | } 161 | else{ 162 | [segmentedControl removeSegmentAtIndex:3 animated:NO]; 163 | } 164 | //------- 165 | 166 | [self segmentedControlValueChanged:segmentedControl]; 167 | 168 | } 169 | 170 | - (void)viewWillDisappear:(BOOL)animated{ 171 | [super viewWillDisappear:animated]; 172 | 173 | // Pause the view's AR session. 174 | [arSession pause]; 175 | } 176 | 177 | - (void)didReceiveMemoryWarning { 178 | [super didReceiveMemoryWarning]; 179 | // Dispose of any resources that can be recreated. 180 | 181 | } 182 | 183 | -(void)outputRotationData:(CMGyroData *)gyrodata 184 | { 185 | //gyroData = gyrodata; 186 | 187 | if (isRecording && gyrodata != nil) 188 | { 189 | double msDate = bootTime + gyrodata.timestamp; 190 | [logStringGyro appendString: [NSString stringWithFormat:@"%f,%f,%f,%f\r\n", 191 | msDate, 192 | gyrodata.rotationRate.x, 193 | gyrodata.rotationRate.y, 194 | gyrodata.rotationRate.z]]; 195 | } 196 | } 197 | 198 | -(void)outputAccelertionData:(CMAccelerometerData *)acceldata 199 | { 200 | //accelData = acceldata; 201 | 202 | if (isRecording && acceldata != nil) 203 | { 204 | double msDate = bootTime + acceldata.timestamp; 205 | [logStringAccel appendString: [NSString stringWithFormat:@"%f,%f,%f,%f\r\n", 206 | msDate, 207 | acceldata.acceleration.x, //G-units 208 | acceldata.acceleration.y, 209 | acceldata.acceleration.z]]; 210 | } 211 | } 212 | 213 | -(void)outputMagnetometerData:(CMMagnetometerData *)magnetdata 214 | { 215 | if (isRecording && magnetdata != nil) 216 | { 217 | double msDate = bootTime + magnetdata.timestamp; 218 | [logStringMagnet appendString: [NSString stringWithFormat:@"%f,%f,%f,%f\r\n", 219 | msDate, 220 | magnetdata.magneticField.x, //microteslas 221 | magnetdata.magneticField.y, 222 | magnetdata.magneticField.z]]; 223 | } 224 | } 225 | 226 | -(void)outputDeviceMotionData:(CMDeviceMotion *)devmotdata 227 | { 228 | if (isRecording && devmotdata != nil) 229 | { 230 | double msDate = bootTime + devmotdata.timestamp; 231 | 232 | CMQuaternion quat = devmotdata.attitude.quaternion; 233 | [logStringMotion appendString: [NSString stringWithFormat:@"%f,%f,%f,%f,%f\r\n", 234 | msDate, 235 | quat.w, 236 | quat.x, 237 | quat.y, 238 | quat.z]]; 239 | 240 | CMRotationRate rotr = devmotdata.rotationRate; 241 | CMAcceleration grav = devmotdata.gravity; 242 | CMAcceleration usracc = devmotdata.userAcceleration; 243 | [logStringMotARH appendString: [NSString stringWithFormat:@"%f,%f,%f,%f,%f,%f,%f,%f,%f,%f,%f\r\n", 244 | msDate, 245 | rotr.x, 246 | rotr.y, 247 | rotr.z, 248 | grav.x, 249 | grav.y, 250 | grav.z, 251 | usracc.x, 252 | usracc.y, 253 | usracc.z, 254 | devmotdata.heading]]; 255 | 256 | CMCalibratedMagneticField calmagnfield = devmotdata.magneticField; 257 | [logStringMotMagnFull appendString: [NSString stringWithFormat:@"%f,%f,%f,%f,%d\r\n", 258 | msDate, 259 | calmagnfield.field.x, 260 | calmagnfield.field.y, 261 | calmagnfield.field.z, 262 | calmagnfield.accuracy]]; 263 | } 264 | } 265 | 266 | #pragma mark - CLLocationManagerDelegate 267 | 268 | - (void)locationManager:(CLLocationManager *)manager didUpdateLocations:(NSArray *)locations 269 | { 270 | locationData = [locations lastObject]; 271 | 272 | [self updateLocation:locationData]; 273 | } 274 | 275 | -(void)updateLocation:(CLLocation *)location 276 | { 277 | if (isRecording && location != nil) 278 | { 279 | double currLatitude = location.coordinate.latitude; 280 | double currLongitude = location.coordinate.longitude; 281 | double currHorAccur = location.horizontalAccuracy; 282 | double currAltitude = location.altitude; 283 | double currVertAccur = location.verticalAccuracy; 284 | long currFloor = location.floor.level; 285 | double currCource = location.course; 286 | double currSpeed = location.speed; 287 | 288 | double msDate = [location.timestamp timeIntervalSince1970]; 289 | [logStringGps appendString: [NSString stringWithFormat:@"%f,%f,%f,%f,%f,%f,%ld,%f,%f\r\n", 290 | msDate, 291 | currLatitude, 292 | currLongitude, 293 | currHorAccur, 294 | currAltitude, 295 | currVertAccur, 296 | currFloor, 297 | currCource, 298 | currSpeed]]; 299 | } 300 | } 301 | 302 | - (void) locationManager:(CLLocationManager *)manager didUpdateHeading:(CLHeading *)newHeading 303 | { 304 | headingData = newHeading; 305 | 306 | [self updateHeading:headingData]; 307 | } 308 | 309 | -(void)updateHeading:(CLHeading *)heading 310 | { 311 | if (isRecording && heading != nil) 312 | { 313 | double currTrueHeading = heading.trueHeading; 314 | double currMagneticHeading = heading.magneticHeading; 315 | double currHeadingAccuracy = heading.headingAccuracy; 316 | 317 | double msDate = [heading.timestamp timeIntervalSince1970]; 318 | [logStringHeading appendString: [NSString stringWithFormat:@"%f,%f,%f,%f\r\n", 319 | msDate, 320 | currTrueHeading, 321 | currMagneticHeading, 322 | currHeadingAccuracy]]; 323 | } 324 | } 325 | 326 | - (void)locationManager:(CLLocationManager *)manager didFailWithError:(NSError *)error 327 | { 328 | UIAlertController * alert = [UIAlertController 329 | alertControllerWithTitle:@"Error" 330 | message:[NSString stringWithFormat:@"Location update: %@", error] 331 | preferredStyle:UIAlertControllerStyleAlert]; 332 | 333 | UIAlertAction* okButton = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action){}]; 334 | [alert addAction:okButton]; 335 | [self presentViewController:alert animated:YES completion:nil]; 336 | } 337 | 338 | - (void)session:(ARSession *)session didUpdateFrame:(ARFrame *)frame { 339 | double msDate = bootTime + frame.timestamp; 340 | 341 | if(prevFrTs >= 0) 342 | if(reduseFpsInNTimes * (msDate - prevFrTs) < (1.0/FPS)/1.5) 343 | reduseFpsInNTimes++; 344 | prevFrTs = msDate; 345 | 346 | if(ireduceFps == 0) 347 | { 348 | matrix_float3x3 camMat = frame.camera.intrinsics; 349 | [self processImage:frame.capturedImage Timestamp:msDate CameraMatrix:&camMat]; 350 | } 351 | if(ireduceFps == (reduseFpsInNTimes-1)) 352 | ireduceFps = 0; 353 | else 354 | ++ireduceFps; 355 | 356 | simd_float4x4 trans = frame.camera.transform; 357 | simd_quatf quat = /*simd_normalize*/(simd_quaternion(trans)); 358 | [logStringArPose appendString: [NSString stringWithFormat:@"%f,%f,%f,%f,%f,%f,%f,%f\r\n", 359 | msDate, 360 | trans.columns[3][0], trans.columns[3][1], trans.columns[3][2], 361 | quat.vector[3], quat.vector[0], quat.vector[1], quat.vector[2] 362 | ]]; 363 | } 364 | 365 | - (void)captureOutput:(AVCaptureOutput *)captureOutput 366 | didOutputSampleBuffer:(CMSampleBufferRef)sampleBuffer 367 | fromConnection:(AVCaptureConnection *)connection 368 | { 369 | //if(isStarted || isRecording) 370 | { 371 | matrix_float3x3 *camMatrix = nullptr; 372 | 373 | if(isRecording || isStarted) 374 | { 375 | if(connection.isCameraIntrinsicMatrixDeliveryEnabled) 376 | { 377 | CFTypeRef cameraIntrinsicData = CMGetAttachment(sampleBuffer, 378 | kCMSampleBufferAttachmentKey_CameraIntrinsicMatrix, 379 | nil); 380 | 381 | if(cameraIntrinsicData != nil) 382 | if (CFGetTypeID(cameraIntrinsicData) == CFDataGetTypeID()) { 383 | CFDataRef cfdr = (CFDataRef)(cameraIntrinsicData); 384 | 385 | camMatrix = (matrix_float3x3 *)(CFDataGetBytePtr(cfdr)); 386 | } 387 | } 388 | } 389 | 390 | //double msDate = [[NSDate date] timeIntervalSince1970]; 391 | CMTime frameTime = CMSampleBufferGetPresentationTimeStamp(sampleBuffer); 392 | double msDate = bootTime + CMTimeGetSeconds(frameTime); 393 | 394 | CVPixelBufferRef buffer = CMSampleBufferGetImageBuffer(sampleBuffer); 395 | 396 | CVPixelBufferLockBaseAddress(buffer, 0); 397 | 398 | [self processImage:buffer Timestamp:msDate CameraMatrix:camMatrix]; 399 | 400 | CVPixelBufferUnlockBaseAddress(buffer, 0); 401 | } 402 | } 403 | 404 | - (void)processImage:(CVPixelBufferRef)pixelBuffer Timestamp:(double)msDate CameraMatrix:(matrix_float3x3*)camMat 405 | { 406 | //crop_resize(image, image, cv::Size(800,600)); 407 | 408 | if(isStarted) 409 | { 410 | [self updateLocation:locationData]; 411 | [self updateHeading:headingData]; 412 | 413 | //------------ 414 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 415 | NSString *documentsDirectory = [paths objectAtIndex:0]; 416 | NSString *filePath = [[NSString alloc] initWithString:[NSString stringWithFormat:@"%@/%@/Frames.m4v", documentsDirectory, theDate]]; 417 | //--- 418 | NSError *error = nil; 419 | NSURL *outputURL = [NSURL fileURLWithPath:filePath]; 420 | assetWriter = [AVAssetWriter assetWriterWithURL:outputURL fileType:AVFileTypeAppleM4V error:&error]; 421 | if (!assetWriter) { 422 | UIAlertController * alert = [UIAlertController alertControllerWithTitle:@"Error" message:[NSString stringWithFormat:@"assetWriter: %@", error] preferredStyle:UIAlertControllerStyleAlert]; \ 423 | UIAlertAction* okButton = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action){}]; \ 424 | [alert addAction:okButton]; \ 425 | [self presentViewController:alert animated:YES completion:nil]; 426 | } 427 | //--- 428 | NSDictionary *writerInputParams = [NSDictionary dictionaryWithObjectsAndKeys: 429 | AVVideoCodecTypeHEVC, AVVideoCodecKey, // AVVideoCodecTypeH264 can be used 430 | [NSNumber numberWithInt:(int)CVPixelBufferGetWidthOfPlane(pixelBuffer,0)], AVVideoWidthKey, 431 | [NSNumber numberWithInt:(int)CVPixelBufferGetHeightOfPlane(pixelBuffer, 0)], AVVideoHeightKey, 432 | AVVideoScalingModeResizeAspectFill, AVVideoScalingModeKey, 433 | nil]; 434 | 435 | assetWriterInput = [AVAssetWriterInput assetWriterInputWithMediaType:AVMediaTypeVideo outputSettings:writerInputParams]; 436 | if ([assetWriter canAddInput:assetWriterInput]) { 437 | [assetWriter addInput:assetWriterInput]; 438 | } else { 439 | UIAlertController * alert = [UIAlertController alertControllerWithTitle:@"Error" message:[NSString stringWithFormat:@"assetWriter can't AddInput: %@", assetWriter.error] preferredStyle:UIAlertControllerStyleAlert]; \ 440 | UIAlertAction* okButton = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action){}]; \ 441 | [alert addAction:okButton]; \ 442 | [self presentViewController:alert animated:YES completion:nil]; 443 | } 444 | //--- 445 | assetWriterInputPixelBufferAdaptor = [AVAssetWriterInputPixelBufferAdaptor assetWriterInputPixelBufferAdaptorWithAssetWriterInput:assetWriterInput sourcePixelBufferAttributes:nil]; 446 | //--- 447 | [assetWriter startWriting]; 448 | [assetWriter startSessionAtSourceTime:kCMTimeZero]; 449 | //------------ 450 | 451 | isStarted = NO; 452 | isRecording = YES; 453 | } 454 | 455 | if(isRecording) 456 | { 457 | if(assetWriterInput.isReadyForMoreMediaData) 458 | { 459 | if(![assetWriterInputPixelBufferAdaptor appendPixelBuffer:pixelBuffer withPresentationTime:CMTimeMake(frameNum, FPS)]) 460 | NSLog(@"assetWriterInput cant appendPixelBuffer!"); 461 | else 462 | { 463 | if(camMat != nullptr){ 464 | [logStringFrameStamps appendString: [NSString stringWithFormat:@"%f,%lu,%f,%f,%f,%f\r\n", 465 | msDate, 466 | frameNum, 467 | camMat->columns[0][0], 468 | camMat->columns[1][1], 469 | camMat->columns[2][0], 470 | camMat->columns[2][1]]]; 471 | } 472 | else{ 473 | [logStringFrameStamps appendString: [NSString stringWithFormat:@"%f,%lu\r\n", 474 | msDate, 475 | frameNum]]; 476 | } 477 | 478 | frameNum += 1; 479 | } 480 | } 481 | else 482 | NSLog(@"assetWriterInput.isReadyForMoreMediaData = NO!"); 483 | } 484 | 485 | CIImage *ciimage = [CIImage imageWithCVImageBuffer:pixelBuffer]; 486 | UIImage *img = [UIImage imageWithCIImage:ciimage]; 487 | dispatch_async(dispatch_get_main_queue(), ^{ 488 | self->imageView.image = img; 489 | }); 490 | } 491 | 492 | - (void)_timerFired:(NSTimer *)timer { 493 | //NSLog(@"ping"); 494 | iTimer += 1; 495 | NSString *timeStr = [NSString stringWithFormat:@"%.2d:%.2d",iTimer/60,iTimer%60]; 496 | runTimeLabel.text = timeStr; 497 | } 498 | 499 | - (IBAction)toggleButton:(id)sender 500 | { 501 | if (!isRecording && !isStarted) 502 | { 503 | isStarted = YES; 504 | 505 | if (!_timer) { 506 | _timer = [NSTimer scheduledTimerWithTimeInterval:1. 507 | target:self 508 | selector:@selector(_timerFired:) 509 | userInfo:nil 510 | repeats:YES]; 511 | } 512 | iTimer = 0; 513 | 514 | runTimeLabel.text = @"00:00"; 515 | afButton.enabled = NO; 516 | if(!isAf){ 517 | afSlider.enabled = NO; 518 | afLabel.enabled = NO; 519 | } 520 | segmentedControl.enabled = NO; 521 | accgyroSwitch.enabled = NO; 522 | gpsheadSwitch.enabled = NO; 523 | motionSwitch.enabled = NO; 524 | magnetSwitch.enabled = NO; 525 | 526 | [logStringAccel setString:@""]; 527 | [logStringGyro setString:@""]; 528 | [logStringMotion setString:@""]; 529 | [logStringMotARH setString:@""]; 530 | [logStringMotMagnFull setString:@""]; 531 | [logStringMagnet setString:@""]; 532 | [logStringGps setString:@""]; 533 | [logStringHeading setString:@""]; 534 | [logStringFrameStamps setString:@""]; 535 | [logStringArPose setString:@""]; 536 | 537 | frameNum = 0; 538 | ireduceFps = 0; 539 | 540 | NSDate *now = [[NSDate alloc] init]; 541 | theDate = [dateFormat stringFromDate:now]; 542 | 543 | [self createFolderInDocuments:theDate]; 544 | 545 | [sender setTitle:@"STOP" forState:UIControlStateNormal]; 546 | } 547 | //---------------------------------------------------------- 548 | else 549 | if (!isStarted) 550 | { 551 | isRecording = NO; 552 | 553 | if ([_timer isValid]) { 554 | [_timer invalidate]; 555 | } 556 | _timer = nil; 557 | afButton.enabled = YES; 558 | if(!isAf){ 559 | afSlider.enabled = YES; 560 | afLabel.enabled = YES; 561 | } 562 | segmentedControl.enabled = YES; 563 | accgyroSwitch.enabled = YES; 564 | gpsheadSwitch.enabled = YES; 565 | motionSwitch.enabled = YES; 566 | magnetSwitch.enabled = YES; 567 | 568 | if(accgyroSwitch.isOn){ 569 | [self writeStringToFile:logStringGyro FileName:@"Gyro"]; 570 | [self writeStringToFile:logStringAccel FileName:@"Accel"]; 571 | } 572 | if(motionSwitch.isOn){ 573 | [self writeStringToFile:logStringMotion FileName:@"Motion"]; 574 | [self writeStringToFile:logStringMotARH FileName:@"MotARH"]; 575 | [self writeStringToFile:logStringMotMagnFull FileName:@"MotMagnFull"]; 576 | } 577 | if(magnetSwitch.isOn){ 578 | [self writeStringToFile:logStringMagnet FileName:@"Magnet"]; 579 | } 580 | if(gpsheadSwitch.isOn){ 581 | [self writeStringToFile:logStringGps FileName:@"GPS"]; 582 | [self writeStringToFile:logStringHeading FileName:@"Head"]; 583 | } 584 | [self writeStringToFile:logStringFrameStamps FileName:@"Frames"]; 585 | if(segmentedControl.selectedSegmentIndex == 3) 586 | [self writeStringToFile:logStringArPose FileName:@"ARposes"]; 587 | 588 | [self->assetWriterInput markAsFinished]; 589 | [self->assetWriter finishWritingWithCompletionHandler:^{ 590 | if (self->assetWriter.error) { 591 | {UIAlertController * alert = [UIAlertController alertControllerWithTitle:@"Error" message:[NSString stringWithFormat:@"assetWriter: %@", self->assetWriter.error] preferredStyle:UIAlertControllerStyleAlert]; \ 592 | UIAlertAction* okButton = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action){}]; \ 593 | [alert addAction:okButton]; \ 594 | [self presentViewController:alert animated:YES completion:nil];} 595 | } else { 596 | // outputURL 597 | } 598 | }]; 599 | 600 | self->assetWriter = nil; 601 | self->assetWriterInput = nil; 602 | self->assetWriterInputPixelBufferAdaptor = nil; 603 | 604 | [sender setTitle:@"START" forState:UIControlStateNormal]; 605 | } 606 | } 607 | 608 | - (IBAction)toggleAfButton:(id)sender { 609 | if(!isAf){ 610 | if(segmentedControl.selectedSegmentIndex == 3) 611 | { 612 | arSession = [ARSession new]; 613 | arSession.delegate = self; 614 | if (@available(iOS 11.3, *)) { 615 | arConfiguration.autoFocusEnabled = true; 616 | } else { 617 | // Fallback on earlier versions 618 | } 619 | [arSession runWithConfiguration:arConfiguration]; 620 | } 621 | else 622 | { 623 | afSlider.enabled = NO; 624 | afLabel.hidden = YES; 625 | 626 | [device lockForConfiguration:nil]; 627 | device.focusMode = AVCaptureFocusModeContinuousAutoFocus; 628 | [device unlockForConfiguration]; 629 | } 630 | 631 | isAf = YES; 632 | [sender setTitle:@"AF:ON" forState:UIControlStateNormal]; 633 | } 634 | else{ 635 | if(segmentedControl.selectedSegmentIndex == 3) 636 | { 637 | arSession = [ARSession new]; 638 | arSession.delegate = self; 639 | if (@available(iOS 11.3, *)) { 640 | arConfiguration.autoFocusEnabled = false; 641 | } else { 642 | // Fallback on earlier versions 643 | } 644 | [arSession runWithConfiguration:arConfiguration]; 645 | } 646 | else 647 | { 648 | afSlider.enabled = YES; 649 | afLabel.hidden = NO; 650 | 651 | [device lockForConfiguration:nil]; 652 | [device setFocusModeLockedWithLensPosition:lensPosition completionHandler:nil]; 653 | [device unlockForConfiguration]; 654 | } 655 | 656 | isAf = NO; 657 | [sender setTitle:@"AF:OFF" forState:UIControlStateNormal]; 658 | } 659 | } 660 | 661 | - (IBAction)afSliderValueChanged:(id)sender { 662 | afLabel.text = [NSString stringWithFormat:@"%5.3f",afSlider.value]; 663 | } 664 | 665 | - (IBAction)afSliderEndEditing:(id)sender { 666 | lensPosition = afSlider.value; 667 | [device lockForConfiguration:nil]; 668 | [device setFocusModeLockedWithLensPosition:lensPosition completionHandler:nil]; 669 | [device unlockForConfiguration]; 670 | } 671 | 672 | - (IBAction)segmentedControlValueChanged:(UISegmentedControl *)sender { 673 | switch(sender.selectedSegmentIndex) 674 | { 675 | case 0: 676 | reduseFpsInNTimes = 1; 677 | if(arSession != nil) 678 | { 679 | arSession = nil; 680 | afSlider.hidden = NO; 681 | afLabel.hidden = NO; 682 | if((device.focusMode == AVCaptureFocusModeLocked) && isAf){ 683 | isAf = !isAf; 684 | [self toggleAfButton:afButton]; 685 | } 686 | } 687 | if([session canSetSessionPreset:AVCaptureSessionPreset640x480]) 688 | session.sessionPreset = AVCaptureSessionPreset640x480; 689 | if(![session isRunning]) 690 | { 691 | [session startRunning]; 692 | } 693 | break; 694 | case 1: 695 | reduseFpsInNTimes = 1; 696 | if(arSession != nil) 697 | { 698 | arSession = nil; 699 | afSlider.hidden = NO; 700 | afLabel.hidden = NO; 701 | if((device.focusMode == AVCaptureFocusModeLocked) && isAf){ 702 | isAf = !isAf; 703 | [self toggleAfButton:afButton]; 704 | } 705 | } 706 | if([session canSetSessionPreset:AVCaptureSessionPreset1280x720]) 707 | session.sessionPreset = AVCaptureSessionPreset1280x720; 708 | if(![session isRunning]) 709 | { 710 | [session startRunning]; 711 | } 712 | break; 713 | case 2: 714 | reduseFpsInNTimes = 1; 715 | if(arSession != nil) 716 | { 717 | arSession = nil; 718 | afSlider.hidden = NO; 719 | afLabel.hidden = NO; 720 | if((device.focusMode == AVCaptureFocusModeLocked) && isAf){ 721 | isAf = !isAf; 722 | [self toggleAfButton:afButton]; 723 | } 724 | } 725 | if([session canSetSessionPreset:AVCaptureSessionPreset1920x1080]) 726 | session.sessionPreset = AVCaptureSessionPreset1920x1080; 727 | if(![session isRunning]) 728 | { 729 | [session startRunning]; 730 | } 731 | break; 732 | case 3: 733 | afSlider.hidden = YES; 734 | afLabel.hidden = YES; 735 | if([session isRunning]) 736 | [session stopRunning]; 737 | isAf = !isAf; 738 | [self toggleAfButton:afButton]; // arSession start 739 | break; 740 | default: sender.selectedSegmentIndex = UISegmentedControlNoSegment; 741 | } 742 | } 743 | 744 | //************************************************************************* 745 | 746 | - (IBAction)accgyroSwChanged:(UISwitch *)sender { 747 | if ( sender.isOn ){ 748 | [motionManager startGyroUpdatesToQueue:accelgyroQueue 749 | withHandler:^(CMGyroData *gyroData, NSError *error) { 750 | [self outputRotationData:gyroData]; 751 | if(error){ 752 | UIAlertController * alert = [UIAlertController 753 | alertControllerWithTitle:@"Error" 754 | message:[NSString stringWithFormat:@"Gyroscope update: %@", error] 755 | preferredStyle:UIAlertControllerStyleAlert]; 756 | 757 | UIAlertAction* okButton = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action){}]; 758 | [alert addAction:okButton]; 759 | [self presentViewController:alert animated:YES completion:nil]; 760 | } 761 | }]; 762 | 763 | [motionManager startAccelerometerUpdatesToQueue:accelgyroQueue 764 | withHandler:^(CMAccelerometerData *accelerometerData, NSError *error) { 765 | [self outputAccelertionData:accelerometerData]; 766 | if(error){ 767 | UIAlertController * alert = [UIAlertController 768 | alertControllerWithTitle:@"Error" 769 | message:[NSString stringWithFormat:@"Accelerometer update: %@", error] 770 | preferredStyle:UIAlertControllerStyleAlert]; 771 | 772 | UIAlertAction* okButton = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action){}]; 773 | [alert addAction:okButton]; 774 | [self presentViewController:alert animated:YES completion:nil]; 775 | } 776 | }]; 777 | } 778 | else{ 779 | [motionManager stopAccelerometerUpdates]; 780 | [motionManager stopGyroUpdates]; 781 | } 782 | } 783 | 784 | - (IBAction)gpsheadSwChanged:(UISwitch *)sender { 785 | if ( sender.isOn ){ 786 | [locationManager startUpdatingLocation]; 787 | 788 | if([CLLocationManager headingAvailable]) 789 | [locationManager startUpdatingHeading]; 790 | } 791 | else{ 792 | [locationManager stopUpdatingLocation]; 793 | 794 | if([CLLocationManager headingAvailable]) 795 | [locationManager stopUpdatingHeading]; 796 | } 797 | } 798 | 799 | - (IBAction)motionSwChanged:(UISwitch *)sender { 800 | if ( sender.isOn ){ 801 | [motionManager startDeviceMotionUpdatesUsingReferenceFrame:CMAttitudeReferenceFrameXTrueNorthZVertical toQueue:motionQueue 802 | withHandler:^(CMDeviceMotion *devmotData, NSError *error) { 803 | [self outputDeviceMotionData:devmotData]; 804 | if(error){ 805 | UIAlertController * alert = [UIAlertController 806 | alertControllerWithTitle:@"Error" 807 | message:[NSString stringWithFormat:@"DeviceMotion update: %@", error] 808 | preferredStyle:UIAlertControllerStyleAlert]; 809 | 810 | UIAlertAction* okButton = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action){}]; 811 | [alert addAction:okButton]; 812 | [self presentViewController:alert animated:YES completion:nil]; 813 | } 814 | }]; 815 | } 816 | else{ 817 | [motionManager stopDeviceMotionUpdates]; 818 | } 819 | } 820 | 821 | - (IBAction)magnetSwChanged:(UISwitch *)sender { 822 | if ( sender.isOn ){ 823 | [motionManager startMagnetometerUpdatesToQueue:magnetQueue 824 | withHandler:^(CMMagnetometerData *magnetData, NSError *error) { 825 | [self outputMagnetometerData:magnetData]; 826 | if(error){ 827 | UIAlertController * alert = [UIAlertController 828 | alertControllerWithTitle:@"Error" 829 | message:[NSString stringWithFormat:@"Magnetometer update: %@", error] 830 | preferredStyle:UIAlertControllerStyleAlert]; 831 | 832 | UIAlertAction* okButton = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action){}]; 833 | [alert addAction:okButton]; 834 | [self presentViewController:alert animated:YES completion:nil]; 835 | } 836 | }]; 837 | } 838 | else{ 839 | [motionManager stopMagnetometerUpdates]; 840 | } 841 | } 842 | 843 | //************************************************************************* 844 | 845 | -(BOOL) writeStringToFile:(NSMutableString *)aString FileName:(NSString *)nameString 846 | { 847 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 848 | NSString *documentsDirectory = [paths objectAtIndex:0]; 849 | 850 | NSString *filePath= [[NSString alloc] initWithString:[NSString stringWithFormat:@"%@/%@/%@.txt",documentsDirectory, theDate, nameString]]; 851 | 852 | BOOL success = [[aString dataUsingEncoding:NSUTF8StringEncoding] writeToFile:filePath atomically:YES]; 853 | 854 | return success; 855 | } 856 | 857 | -(BOOL) createFolderInDocuments:(NSString *)folderName 858 | { 859 | NSError *error = nil; 860 | NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES); 861 | NSString *documentsDirectory = [paths objectAtIndex:0]; 862 | NSString *dataPath = [documentsDirectory stringByAppendingPathComponent:folderName]; 863 | 864 | BOOL success = YES; 865 | if (![[NSFileManager defaultManager] fileExistsAtPath:dataPath]) 866 | success = [[NSFileManager defaultManager] createDirectoryAtPath:dataPath withIntermediateDirectories:NO attributes:nil error:&error]; 867 | 868 | if(error){ 869 | UIAlertController * alert = [UIAlertController 870 | alertControllerWithTitle:@"Error" 871 | message:[NSString stringWithFormat:@"Create folder: %@", error] 872 | preferredStyle:UIAlertControllerStyleAlert]; 873 | 874 | UIAlertAction* okButton = [UIAlertAction actionWithTitle:@"OK" style:UIAlertActionStyleDefault handler:^(UIAlertAction * action){}]; 875 | [alert addAction:okButton]; 876 | [self presentViewController:alert animated:YES completion:nil]; 877 | } 878 | 879 | return success; 880 | } 881 | 882 | @end 883 | -------------------------------------------------------------------------------- /ios_logger/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // cig_logger 4 | // 5 | // Created by Mac on 27/08/2018. 6 | // Copyright © 2018 Mac. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "AppDelegate.h" 11 | 12 | int main(int argc, char * argv[]) { 13 | @autoreleasepool { 14 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /sync-data.py: -------------------------------------------------------------------------------- 1 | # Synchronize the accelerometer and gyroscope data 2 | 3 | import sys 4 | import pandas as pd 5 | import numpy as np 6 | 7 | # Read data 8 | path=sys.argv[1] 9 | if path[-1] != '/' or path[-1] != '\\': 10 | path = path + '/' 11 | path_accel= path + 'Accel.txt' 12 | acc=( pd.read_csv(path_accel,names=list('tabc'))) 13 | path_gyro= path + 'Gyro.txt' 14 | gyro=( pd.read_csv(path_gyro,names=list('tabc'))) 15 | g=[] 16 | a=[] 17 | t=acc[list('t')].values 18 | 19 | G = 9.81 20 | for c in 'abc': 21 | acc[list(c)] = G*acc[list(c)] 22 | 23 | # Make imu 24 | for c in 'abc': 25 | g.append(np.interp(acc[list('t')].values[:, 0], gyro[list('t')].values[:, 0], gyro[list(c)].values[:, 0])) 26 | a.append(acc[list(c)].values) 27 | M=np.column_stack((t,g[0],g[1],g[2],a[0],a[1],a[2])) 28 | 29 | full = M[M[:,0].argsort()] 30 | path= path + 'accel-gyro.txt' 31 | np.savetxt(path, full, delimiter=",",fmt='%.6f') 32 | --------------------------------------------------------------------------------