openHMD-simple代码分析(2/2)
来源:互联网 发布:maxdos 网络克隆 编辑:程序博客网 时间:2024/05/17 09:18
openHMD-simple代码分析(2/2)
接上篇内容,这里主要以oculars在openHMD中的提交,来分析oculars的DK1/DK2在openHMD中是如何运行的。
simple代码的主流程看上篇文章”openHMD-simple代码分析(1/2)”。
打开设备:ohmd_list_open_device
//打开设备列表中第一个设备 ohmd_device* hmd = ohmd_list_open_device(ctx, 0); if(!hmd){ printf("failed to open device: %s\n", ohmd_ctx_get_error(ctx)); return -1; }
ohmd_list_open_device函数:
ohmd_device* OHMD_APIENTRY ohmd_list_open_device(ohmd_context* ctx, int index){ ohmd_device_settings settings; //设置设备数据的更新方式: //false:需要手动调用ohmd_ctx_update来更新数据 //true:创建线程,调用设备的update方法来更新数据(如rift.c里的update_devices) settings.automatic_update = true; return ohmd_list_open_device_s(ctx, index, &settings);}
ohmd_list_open_device_s函数:
ohmd_device* OHMD_APIENTRY ohmd_list_open_device_s(ohmd_context* ctx, int index, ohmd_device_settings* settings){ ohmd_lock_mutex(ctx->update_mutex); //轮询所有设备 if(index >= 0 && index < ctx->list.num_devices){ ohmd_device_desc* desc = &ctx->list.devices[index]; ohmd_driver* driver = (ohmd_driver*)desc->driver_ptr; ohmd_device* device = driver->open_device(driver, desc); if (device == NULL) return NULL; //填充device参数值 device->rotation_correction.w = 1; device->settings = *settings; device->ctx = ctx; device->active_device_idx = ctx->num_active_devices; ctx->active_devices[ctx->num_active_devices++] = device; ohmd_unlock_mutex(ctx->update_mutex); if(device->settings.automatic_update) //创建线程,用来更新上报的数据。 ohmd_set_up_update_thread(ctx); return device; } ohmd_unlock_mutex(ctx->update_mutex); //如果没有设备则返回错误 ohmd_set_error(ctx, "no device with index: %d", index); return NULL;}
其中ohmd_set_up_update_thread会创建更新数据的线程ohmd_update_thread,这个函数主要用来读取sensor数据,调用fusion算法,将raw数据处理为四元素。
static void ohmd_set_up_update_thread(ohmd_context* ctx){ if(!ctx->update_thread){ ctx->update_mutex = ohmd_create_mutex(ctx); ctx->update_thread = ohmd_create_thread(ctx, ohmd_update_thread, ctx); }}
static unsigned int ohmd_update_thread(void* arg){ ohmd_context* ctx = (ohmd_context*)arg; //ctx->update_request_quit 控制循环是否结束,一般在ohmd_ctx_destroy里设置为true while(!ctx->update_request_quit) { ohmd_lock_mutex(ctx->update_mutex); //调用所有处于激活状态的设备的update方法来循环更新数据(如rift.c里的update_device) for(int i = 0; i < ctx->num_active_devices; i++){ if(ctx->active_devices[i]->settings.automatic_update && ctx->active_devices[i]->update) ctx->active_devices[i]->update(ctx->active_devices[i]); } ohmd_unlock_mutex(ctx->update_mutex); //休眠一段时间,释放CPU ohmd_sleep(AUTOMATIC_UPDATE_SLEEP); } return 0;}
ctx->active_devices[i]->update(ctx->active_devices[i])实际上是调用到具体设备中的数据更新的接口中,这里以oculars的DK1/DK2为例进行说明数据的更新
static void update_device(ohmd_device* device){ rift_priv* priv = rift_priv_get(device); unsigned char buffer[FEATURE_BUFFER_SIZE]; //处理心跳包信息:按照keep_alive_interval参数值(默认1秒)为间隔,发送心跳包给HMD double t = ohmd_get_tick(); if(t - priv->last_keep_alive >= (double)priv->sensor_config.keep_alive_interval / 1000.0 - .2){ // send keep alive message pkt_keep_alive keep_alive = { 0, priv->sensor_config.keep_alive_interval }; int ka_size = encode_keep_alive(buffer, &keep_alive); send_feature_report(priv, buffer, ka_size); // Update the time of the last keep alive we have sent. priv->last_keep_alive = t; } //处理HMD上报的所有数据 while(true){ //通过HID接口读取HMD的数据 int size = hid_read(priv->handle, buffer, FEATURE_BUFFER_SIZE); if(size < 0){ LOGE("error reading from device"); return; } else if(size == 0) {//数据读完退出 return; } //根据oculars协议,对上报数据进行处理 if(buffer[0] == RIFT_IRQ_SENSORS){ handle_tracker_sensor_msg(priv, buffer, size); }else{ LOGE("unknown message type: %u", buffer[0]); } }}
其中handle_tracker_sensor_msg函数如下:
static void handle_tracker_sensor_msg(rift_priv* priv, unsigned char* buffer, int size){ //按照oculars的数据协议解析buffer中的数据填充到priv->sensor中 if(!decode_tracker_sensor_msg(&priv->sensor, buffer, size)){ LOGE("couldn't decode tracker sensor message"); } pkt_tracker_sensor* s = &priv->sensor; //打印调试信息 dump_packet_tracker_sensor(s); //根据采样数设置dt值(一般采样数都在3以内) float dt = s->num_samples > 3 ? (s->num_samples - 2) * TICK_LEN : TICK_LEN; int32_t mag32[] = { s->mag[0], s->mag[1], s->mag[2] }; //将上报数据转为浮点数(HMD上报时不能直接上报浮点数,所以先*10000转化为整数上报) //这里*0.0001相当于做了还原). vec3f_from_rift_vec(mag32, &priv->raw_mag); for(int i = 0; i < OHMD_MIN(s->num_samples, 3); i++){ //将上报数据转为浮点数 vec3f_from_rift_vec(s->samples[i].accel, &priv->raw_accel); //将上报数据转为浮点数 vec3f_from_rift_vec(s->samples[i].gyro, &priv->raw_gyro); //融合算法 ofusion_update(&priv->sensor_fusion, dt, &priv->raw_gyro, &priv->raw_accel, &priv->raw_mag); // reset dt to tick_len for the last samples if there were more than one sample dt = TICK_LEN; }}
主要是解析HMD上报的数据,关于ofusion_update融合算法,中间的四元素操作比较复杂,可以看这篇老外的文章IMU指南,需要花点时间琢磨。
数据更新:ohmd_ctx_update
void OHMD_APIENTRY ohmd_ctx_update(ohmd_context* ctx){ for(int i = 0; i < ctx->num_active_devices; i++){ ohmd_device* dev = ctx->active_devices[i]; //如果设备对应驱动中没有创建线程实时刷新数据则,通过这里刷新数据。 //(Oculars DK1是通过线程刷新数据的. if(!dev->settings.automatic_update && dev->update) dev->update(dev); ohmd_lock_mutex(ctx->update_mutex); //获取位置信息填充到dev->position中 dev->getf(dev, OHMD_POSITION_VECTOR, (float*)&dev->position); //获取经过融合算法的orient数据填充到dev->rotation中。 dev->getf(dev, OHMD_ROTATION_QUAT, (float*)&dev->rotation); ohmd_unlock_mutex(ctx->update_mutex); }}
获取四元素:ohmd_device_setf/ohmd_device_getf
float zero[] = {.0, .1, .2, 1}; //计算QUAT和VECTOR的校准因子correction ohmd_device_setf(hmd, OHMD_ROTATION_QUAT, zero); ohmd_device_setf(hmd, OHMD_POSITION_VECTOR, zero); //利用上面计算的校准因子,来得出最后的四元素并打印出来。 print_infof(hmd, "rotation quat:", 4, OHMD_ROTATION_QUAT);
0 0
- openHMD-simple代码分析(2/2)
- openHMD-simple代码分析(1/2)
- openHMD-Tutorial
- 14.5.2 Simple names
- ecos代码分析(2)
- chromium 代码分析(2)
- tslib 代码分析2
- OsmocomBB 代码分析(2)
- 2015061505 - 代码分析之代码格式(2)
- Mikrokopter MK 代码分析2-main分析
- 2013-2-2 - simple-loader
- Simple 2 column CSS layout
- simple tree 学习笔记2
- 初学者分析MFC代码2
- Swing代码分析(2)
- 2、arm启动代码分析
- s3c2440启动代码分析2
- charger代码分析(Android4.2)
- 给uiview增加阴影效果的代码
- iOS - App结构探究
- 5.Scheduler - 介绍了各种异步任务调度和默认调度器
- Android官方开发文档Training系列课程中文版:如何避免ANR?
- 【第七周项目4-队列数组】
- openHMD-simple代码分析(2/2)
- coreData mapView #include
- Leetcode 122. Best Time to Buy and Sell Stock II 股票买卖2 解题报告
- iOS - BaseViewController设计
- [LeetCode]--198. House Robber
- AngularJS 之 Factory vs Service vs Provider
- 第七周 项目2 : 建立链队算法库
- 给圆添加一个阴影效果
- Scott用户测试表