android.c 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339
  1. /*
  2. * OpenHMD - Free and Open Source API and drivers for immersive technology.
  3. * Copyright (C) 2013 Fredrik Hultin.
  4. * Copyright (C) 2013 Jakob Bornecrantz.
  5. * Copyright (C) 2015 Joey Ferwerda
  6. * Distributed under the Boost 1.0 licence, see LICENSE for full text.
  7. */
  8. /* Android Driver */
  9. #include "android.h"
  10. #ifdef __ANDROID__
  11. #include <android/sensor.h>
  12. #endif // __ANDROID__
  13. typedef struct {
  14. ohmd_device base;
  15. fusion sensor_fusion;
  16. //Android specific
  17. #ifdef __ANDROID__
  18. android_app* state;
  19. ASensorManager* sensorManager;
  20. const ASensor* accelerometerSensor;
  21. const ASensor* gyroscopeSensor;
  22. ASensorEventQueue* sensorEventQueue;
  23. AAssetManager* assetMgr;
  24. short firstRun;
  25. #endif
  26. } android_priv;
  27. //Forward decelerations
  28. static void set_android_properties(ohmd_device* device, ohmd_device_properties* props);
  29. static void nofusion_init(fusion* me);
  30. static void nofusion_update(fusion* me, float dt, const vec3f* accel);
  31. //Static variable for timeDelta;
  32. static float timestamp;
  33. //Android callback for the sensor event queue
  34. static int android_sensor_callback(int fd, int events, void* data)
  35. {
  36. android_priv* priv = (android_priv*)data;
  37. if (priv->accelerometerSensor != NULL)
  38. {
  39. ASensorEvent event;
  40. vec3f gyro;
  41. vec3f accel;
  42. vec3f mag;
  43. float lastevent_timestamp;
  44. while (ASensorEventQueue_getEvents(priv->sensorEventQueue, &event, 1) > 0)
  45. {
  46. if (event.type == ASENSOR_TYPE_ACCELEROMETER)
  47. {
  48. accel.x = event.acceleration.y;
  49. accel.y = -event.acceleration.x;
  50. accel.z = event.acceleration.z;
  51. }
  52. if (event.type == ASENSOR_TYPE_GYROSCOPE)
  53. {
  54. gyro.x = -event.data[1];
  55. gyro.y = event.data[0];
  56. gyro.z = event.data[2];
  57. }
  58. ///TODO: Implement mag when available
  59. mag.x = 0.0f;
  60. mag.y = 0.0f;
  61. mag.z = 0.0f;
  62. lastevent_timestamp = event.timestamp;
  63. }
  64. //apply data to the fusion
  65. float dT = 0.0f;
  66. if (timestamp != 0)
  67. dT= (lastevent_timestamp - timestamp) * (1.0f / 1000000000.0f);
  68. //Check if accelerometer only fallback is required
  69. if (!priv->gyroscopeSensor)
  70. nofusion_update(&priv->sensor_fusion, dT, &accel);
  71. else
  72. ofusion_update(&priv->sensor_fusion, dT, &gyro, &accel, &mag); //default
  73. timestamp = lastevent_timestamp;
  74. }
  75. return 1;
  76. }
  77. static void update_device(ohmd_device* device)
  78. {
  79. android_priv* priv = (android_priv*)device;
  80. if(!priv->state)
  81. return;
  82. //We need this since during init the android_app state is not set yet
  83. if (priv->firstRun == 1)
  84. {
  85. priv->sensorEventQueue = ASensorManager_createEventQueue(priv->sensorManager,
  86. priv->state->looper, LOOPER_ID_USER, android_sensor_callback, (void*)priv);
  87. // Start sensors in case this was not done already.
  88. if (priv->accelerometerSensor != NULL)
  89. {
  90. ASensorEventQueue_enableSensor(priv->sensorEventQueue, priv->accelerometerSensor);
  91. // We'd like to get 60 events per second (in us).
  92. ASensorEventQueue_setEventRate(priv->sensorEventQueue, priv->accelerometerSensor, (1000L/60)*1000);
  93. }
  94. if (priv->gyroscopeSensor != NULL)
  95. {
  96. ASensorEventQueue_enableSensor(priv->sensorEventQueue, priv->gyroscopeSensor);
  97. // We'd like to get 60 events per second (in us).
  98. ASensorEventQueue_setEventRate(priv->sensorEventQueue, priv->gyroscopeSensor, (1000L/60)*1000);
  99. }
  100. priv->firstRun = 0;
  101. }
  102. }
  103. static int getf(ohmd_device* device, ohmd_float_value type, float* out)
  104. {
  105. android_priv* priv = (android_priv*)device;
  106. switch(type){
  107. case OHMD_ROTATION_QUAT: {
  108. *(quatf*)out = priv->sensor_fusion.orient;
  109. break;
  110. }
  111. case OHMD_POSITION_VECTOR:
  112. out[0] = out[1] = out[2] = 0;
  113. break;
  114. case OHMD_DISTORTION_K:
  115. // TODO this should be set to the equivalent of no distortion
  116. memset(out, 0, sizeof(float) * 6);
  117. break;
  118. default:
  119. ohmd_set_error(priv->base.ctx, "invalid type given to getf (%d)", type);
  120. return -1;
  121. break;
  122. }
  123. return 0;
  124. }
  125. static int set_data(ohmd_device* device, ohmd_data_value type, void* in)
  126. {
  127. android_priv* priv = (android_priv*)device;
  128. switch(type){
  129. case OHMD_DRIVER_DATA: {
  130. priv->state = (android_app*)in;
  131. break;
  132. }
  133. case OHMD_DRIVER_PROPERTIES: {
  134. set_android_properties(device, (ohmd_device_properties*)in);
  135. break;
  136. }
  137. default:
  138. ohmd_set_error(priv->base.ctx, "invalid type given to set_data (%i)", type);
  139. return -1;
  140. break;
  141. }
  142. return 0;
  143. }
  144. static void close_device(ohmd_device* device)
  145. {
  146. LOGD("closing Android device");
  147. free(device);
  148. }
  149. static ohmd_device* open_device(ohmd_driver* driver, ohmd_device_desc* desc)
  150. {
  151. android_priv* priv = ohmd_alloc(driver->ctx, sizeof(android_priv));
  152. if(!priv)
  153. return NULL;
  154. // Set default device properties
  155. ohmd_set_default_device_properties(&priv->base.properties);
  156. // Set device properties
  157. //TODO: Get information from android about device
  158. //TODO: Use profile string to set default for a particular device (Durovis, VR One etc)
  159. priv->base.properties.hsize = 0.149760f;
  160. priv->base.properties.vsize = 0.093600f;
  161. priv->base.properties.hres = 1280;
  162. priv->base.properties.vres = 800;
  163. priv->base.properties.lens_sep = 0.063500f;
  164. priv->base.properties.lens_vpos = 0.046800f;
  165. priv->base.properties.fov = DEG_TO_RAD(125.5144f);
  166. priv->base.properties.ratio = (1280.0f / 800.0f) / 2.0f;
  167. // calculate projection eye projection matrices from the device properties
  168. ohmd_calc_default_proj_matrices(&priv->base.properties);
  169. // set up device callbacks
  170. priv->base.update = update_device;
  171. priv->base.close = close_device;
  172. priv->base.getf = getf;
  173. priv->base.set_data = set_data;
  174. //init Android sensors
  175. priv->sensorManager = ASensorManager_getInstance();
  176. priv->accelerometerSensor = ASensorManager_getDefaultSensor(priv->sensorManager,
  177. ASENSOR_TYPE_ACCELEROMETER);
  178. priv->gyroscopeSensor = ASensorManager_getDefaultSensor(priv->sensorManager,
  179. ASENSOR_TYPE_GYROSCOPE);
  180. priv->firstRun = 1; //need this since ASensorManager_createEventQueue requires a set android_app*
  181. //Check if accelerometer only fallback is required
  182. if (!priv->gyroscopeSensor)
  183. nofusion_init(&priv->sensor_fusion);
  184. else
  185. ofusion_init(&priv->sensor_fusion); //Default when all sensors are available
  186. return (ohmd_device*)priv;
  187. }
  188. static void get_device_list(ohmd_driver* driver, ohmd_device_list* list)
  189. {
  190. ohmd_device_desc* desc = &list->devices[list->num_devices++];
  191. strcpy(desc->driver, "OpenHMD Generic Android Driver");
  192. strcpy(desc->vendor, "OpenHMD");
  193. strcpy(desc->product, "Android Device");
  194. strcpy(desc->path, "(none)");
  195. desc->device_class = OHMD_DEVICE_CLASS_HMD;
  196. desc->device_flags = OHMD_DEVICE_FLAGS_ROTATIONAL_TRACKING;
  197. desc->driver_ptr = driver;
  198. }
  199. static void destroy_driver(ohmd_driver* drv)
  200. {
  201. LOGD("shutting down Android driver");
  202. free(drv);
  203. }
  204. ohmd_driver* ohmd_create_android_drv(ohmd_context* ctx)
  205. {
  206. ohmd_driver* drv = ohmd_alloc(ctx, sizeof(ohmd_driver));
  207. if(!drv)
  208. return NULL;
  209. drv->get_device_list = get_device_list;
  210. drv->open_device = open_device;
  211. drv->destroy = destroy_driver;
  212. drv->ctx = ctx;
  213. return drv;
  214. }
  215. /* Android specific functions */
  216. static void nofusion_update(fusion* me, float dt, const vec3f* accel)
  217. {
  218. //avg raw accel data to smooth jitter, and normalise
  219. ofq_add(&me->accel_fq, accel);
  220. vec3f accel_mean;
  221. ofq_get_mean(&me->accel_fq, &accel_mean);
  222. vec3f acc_n = accel_mean;
  223. ovec3f_normalize_me(&acc_n);
  224. //reference vectors for axis-angle
  225. vec3f xyzv[3] = {
  226. {1,0,0},
  227. {0,1,0},
  228. {0,0,1}
  229. };
  230. quatf roll, pitch;
  231. //pitch is rot around x, based on gravity in z and y axes
  232. oquatf_init_axis(&pitch, xyzv+0, atan2f(-acc_n.z, -acc_n.y));
  233. //roll is rot around z, based on gravity in x and y axes
  234. //note we need to invert the values when the device is upside down (y < 0) for proper results
  235. oquatf_init_axis(&roll, xyzv+2, acc_n.y < 0 ? atan2f(-acc_n.x, -acc_n.y) : atan2f(acc_n.x, acc_n.y));
  236. quatf or = {0,0,0,1};
  237. //order of applying is yaw-pitch-roll
  238. //yaw is not possible using only accel
  239. oquatf_mult_me(&or, &pitch);
  240. oquatf_mult_me(&or, &roll);
  241. me->orient = or;
  242. }
  243. //shorter buffers for frame smoothing
  244. static void nofusion_init(fusion* me)
  245. {
  246. memset(me, 0, sizeof(fusion));
  247. me->orient.w = 1.0f;
  248. ofq_init(&me->mag_fq, 10);
  249. ofq_init(&me->accel_fq, 10);
  250. ofq_init(&me->ang_vel_fq, 10);
  251. me->flags = FF_USE_GRAVITY;
  252. me->grav_gain = 0.05f;
  253. }
  254. static void set_android_properties(ohmd_device* device, ohmd_device_properties* props)
  255. {
  256. android_priv* priv = (android_priv*)device;
  257. priv->base.properties.hsize = props->hsize;
  258. priv->base.properties.vsize = props->vsize;
  259. priv->base.properties.hres = props->hres;
  260. priv->base.properties.vres = props->vres;
  261. priv->base.properties.lens_sep = props->lens_sep;
  262. priv->base.properties.lens_vpos = props->lens_vpos;
  263. priv->base.properties.fov = DEG_TO_RAD(props->fov);
  264. priv->base.properties.ratio = props->ratio;
  265. }
  266. static void set_android_profile(ohmd_driver* driver, android_hmd_profile profile)
  267. {
  268. switch(profile){
  269. case DROID_DUROVIS_OPEN_DIVE: break;
  270. case DROID_DUROVIS_DIVE_5: break;
  271. case DROID_DUROVIS_DIVE_7: break;
  272. case DROID_CARL_ZEISS_VRONE: break;
  273. case DROID_GOOGLE_CARDBOARD: break;
  274. case DROID_NONE:
  275. default: break;
  276. }
  277. }