资讯详情

OpenXR+Runtime:Monado从ipc_server到device

今日跟着Monado Runtime从ipc_server启动到device端获取3DoF数据源代码,

个人理解可能会有错误

开始吧。

注释:src\xrt\targets\service-lib\service_target.cpp       runtime client端通过jni函数call runtime server extern "C" void Java_org_freedesktop_monado_ipc_MonadoImpl_nativeStartServer(JNIEnv *env, jobject thiz) {  jni::init(env);  jni::Object monadoImpl(thiz);  U_LOG_D("service: Called nativeStartServer");   IpcServerHelper::instance().startServer(); }    注释:service_target.cpp中定义的IpcServerHelper结构体中startServer() void startServer() {  std::unique_lock lock(server_mutex);  if (!server && !server_thread) {   server_thread = std::make_unique<std::thread>(    [&]() { ipc_server_main_android(&server, signalStartupCompleteTrampoline, this); });  } }

注释:src\xrt\ipc\server\ipc_server_process.c      中定义了ipc_server_main_android(...)函数。  #ifdef XRT_OS_ANDROID int ipc_server_main_android(struct ipc_server **ps, void (*startup_complete_callback)(void *data), void *data) {  struct ipc_server *s = U_TYPED_CALLOC(struct ipc_server);  U_LOG_D("Created IPC server!");   int ret = init_all(s);  if (ret < 0) {   free(s);   return ret;  }   init_server_state(s);   *ps = s;  startup_complete_callback(data);   ret = main_loop(s);   teardown_all(s);  free(s);   U_LOG_I("Server exiting '%i'!", ret);   return ret; } #endif // XRT_OS_ANDROID 

同时,还有非android系统的ipc_server_main(int argc, char **argv)

ipc_server_main(...)开始和开始android有所不同,

它是在 src\xrt\targets\service\main.c 中启动:

int ipc_server_main(int argc, char *argv[]);   int main(int argc, char *argv[]) {  u_trace_marker_init();   return ipc_server_main(argc, argv); }

非android的runtime server除了这里的一些差异,下一个过程和android都是成套的,都是一样的。接下来我们只关注。android流程。

上面ipc_server_main_android(...)调用函数

int ret = init_all(s);

static int init_all(struct ipc_server *s)函数定义仍然存在ipc_server_process.c中

其参数是 ipc_server 结构体指针

init_all(...)函数会做很多初始化的事情,包括对 ipc_server结构体中 xrt_instance创建结构体

static int init_all(struct ipc_server *s) {     ...     ...   int ret = xrt_instance_create(NULL, &s->xinst);  if (ret < 0) {   IPC_ERROR(s, "Failed to create instance!");   teardown_all(s);   return ret;  }      ...     ...   return 0; }

xrt_instance_create(...)函数在

src\xrt\targets\common\target_instance_no_comp.c 中被定义

注释:src\xrt\targets\common\target_instance_no_comp.c  int xrt_instance_create(struct xrt_instance_info *i_info, struct xrt_instance **out_xinst) {  struct xrt_prober *xp = NULL;   int ret = xrt_prober_create_with_lists(&xp, &target_lists);  if (ret < 0) {   return ret;  }   struct t_instance *tinst = U_TYPED_CALLOC(struct t_instance);  tinst->base.select = t_instance_select;  tinst->base.create_system_compositor = t_instance_create_system_compositor_stub;  tinst->base.get_prober = t_instance_get_prober;  tinst->base.destroy = t_instance_destroy;  tinst->xp = xp;   *out_xinst = &tinst->base;   return 0; }

注意参数 &target_lists引用

这是 xrt_prober_entry_lists 引用结构体

在src\xrt\targets\common\target_lists.c中被定义

struct xrt_prober_entry_lists target_lists = {     target_entry_lists,     target_auto_list,     NULL, };

其中成员 target_auto_list 是一个xrt_auto_prober_creator数组

xrt_auto_prober_creator target_auto_list[] = {...}

xrt_auto_prober_creator 找不到定义,可能是包装在共享库中

先看 target_auto_list[] 这些平台相关探针的函数指针成员通过不同平台的宏声明:

xrt_auto_prober_creator target_auto_list[] = { ...  #ifdef XRT_BUILD_DRIVER_ANDROID     android_create_auto_prober, #endif  ...      NULL, // Terminate };

android_create_auto_prober()函数在

src\xrt\drivers\android\android_proper.c 中被定义

struct xrt_auto_prober * android_create_auto_prober() {  struct android_prober *p = U_TYPED_CALLOC(struct android_prober);  p->base.name = "Android";  p->base.destroy = android_prober_destroy;  p->base.lelo_dallas_autoprobe = android_prober_autoprobe;   return &p->base; }

android_create_auto_prober()获得函数 android_prober_autoprobe 函指针

它们在同文件中定义

static int
android_prober_autoprobe(struct xrt_auto_prober *xap,
                         cJSON *attached_data,
                         bool no_hmds,
                         struct xrt_prober *xp,
                         struct xrt_device **out_xdevs)
{
	struct android_device *dd = android_device_create();
	out_xdevs[0] = &dd->base;
	return 1;
}

android_device_create()函数在

src\xrt\drivers\android\android_sensors.c 中定义

struct android_device *
android_device_create()
{
	enum u_device_alloc_flags flags =
	    (enum u_device_alloc_flags)(U_DEVICE_ALLOC_HMD | U_DEVICE_ALLOC_TRACKING_NONE);
	struct android_device *d = U_DEVICE_ALLOCATE(struct android_device, flags, 1, 0);

	d->base.name = XRT_DEVICE_GENERIC_HMD;
	d->base.destroy = android_device_destroy;
	d->base.update_inputs = android_device_update_inputs;
	d->base.get_tracked_pose = android_device_get_tracked_pose;
	d->base.get_view_poses = android_device_get_view_poses;
	d->base.compute_distortion = android_device_compute_distortion;
	d->base.inputs[0].name = XRT_INPUT_GENERIC_HEAD_POSE;
	d->base.device_type = XRT_DEVICE_TYPE_HMD;
	snprintf(d->base.str, XRT_DEVICE_NAME_LEN, "Android Sensors");
	snprintf(d->base.serial, XRT_DEVICE_NAME_LEN, "Android Sensors");

	d->log_level = debug_get_log_option_android_log();

	m_imu_3dof_init(&d->fusion, M_IMU_3DOF_USE_GRAVITY_DUR_20MS);

	// Everything done, finally start the thread.
	int ret = os_thread_helper_start(&d->oth, android_run_thread, d);
	if (ret != 0) {
		ANDROID_ERROR(d, "Failed to start thread!");
		android_device_destroy(&d->base);
		return NULL;
	}

	struct xrt_android_display_metrics metrics;
	if (!android_custom_surface_get_display_metrics(android_globals_get_vm(), android_globals_get_activity(),
	                                                &metrics)) {
		U_LOG_E("Could not get Android display metrics.");
		/* Fallback to default values (Pixel 3) */
		metrics.width_pixels = 2960;
		metrics.height_pixels = 1440;
		metrics.density_dpi = 572;
		metrics.refresh_rate = 60.0f;
	}

	d->base.hmd->screens[0].nominal_frame_interval_ns = time_s_to_ns(1.0f / metrics.refresh_rate);

    ...
    ...    

	return d;
}

可以看到android_device_create()中获取到了VR设备层传递过来的各种事件,track、位姿数据等

以及设置各种显示参数等

track、位姿等数据,源码中是以3DoF模拟

关键的加速度传感和重力传感的数据是在

int ret = os_thread_helper_start(&d->oth, android_run_thread, d);

这一行语句中起了一个专门的线程来做。

线程android_run_thread(void *ptr)同样是在android_sensors.c中定义:

static void *
android_run_thread(void *ptr)
{
	struct android_device *d = (struct android_device *)ptr;
	const int32_t poll_rate_usec = android_get_sensor_poll_rate(d);

#if __ANDROID_API__ >= 26
	d->sensor_manager = ASensorManager_getInstanceForPackage(XRT_ANDROID_PACKAGE);
#else
	d->sensor_manager = ASensorManager_getInstance();
#endif

	d->accelerometer = ASensorManager_getDefaultSensor(d->sensor_manager, ASENSOR_TYPE_ACCELEROMETER);
	d->gyroscope = ASensorManager_getDefaultSensor(d->sensor_manager, ASENSOR_TYPE_GYROSCOPE);

	ALooper *looper = ALooper_prepare(ALOOPER_PREPARE_ALLOW_NON_CALLBACKS);

	d->event_queue = ASensorManager_createEventQueue(d->sensor_manager, looper, ALOOPER_POLL_CALLBACK,
	                                                 android_sensor_callback, (void *)d);

	// Start sensors in case this was not done already.
	if (d->accelerometer != NULL) {
		ASensorEventQueue_enableSensor(d->event_queue, d->accelerometer);
		ASensorEventQueue_setEventRate(d->event_queue, d->accelerometer, poll_rate_usec);
	}
	if (d->gyroscope != NULL) {
		ASensorEventQueue_enableSensor(d->event_queue, d->gyroscope);
		ASensorEventQueue_setEventRate(d->event_queue, d->gyroscope, poll_rate_usec);
	}

	int ret = 0;
	while (d->oth.running && ret != ALOOPER_POLL_ERROR) {
		ret = ALooper_pollAll(0, NULL, NULL, NULL);
	}

	return NULL;
}

android_run_thread(void *ptr)函数中是通过 android_sensor_callback 获取到android_device的event_queue

android_sensor_callback 同样也是在android_sensors.c中定义

// Callback for the Android sensor event queue
static int
android_sensor_callback(int fd, int events, void *data)
{
	struct android_device *d = (struct android_device *)data;

	if (d->accelerometer == NULL || d->gyroscope == NULL)
		return 1;

	ASensorEvent event;
	struct xrt_vec3 gyro;
	struct xrt_vec3 accel;
	while (ASensorEventQueue_getEvents(d->event_queue, &event, 1) > 0) {

		switch (event.type) {
		case ASENSOR_TYPE_ACCELEROMETER: {
			accel.x = event.acceleration.y;
			accel.y = -event.acceleration.x;
			accel.z = event.acceleration.z;

			ANDROID_TRACE(d, "accel %ld %.2f %.2f %.2f", event.timestamp, accel.x, accel.y, accel.z);
			break;
		}
		case ASENSOR_TYPE_GYROSCOPE: {
			gyro.x = -event.data[1];
			gyro.y = event.data[0];
			gyro.z = event.data[2];

			ANDROID_TRACE(d, "gyro %ld %.2f %.2f %.2f", event.timestamp, gyro.x, gyro.y, gyro.z);

			// TODO: Make filter handle accelerometer
			struct xrt_vec3 null_accel;

			// Lock last and the fusion.
			os_mutex_lock(&d->lock);

			m_imu_3dof_update(&d->fusion, event.timestamp, &null_accel, &gyro);

			// Now done.
			os_mutex_unlock(&d->lock);
		}
		default: ANDROID_TRACE(d, "Unhandled event type %d", event.type);
		}
	}

	return 1;
}

这里就能很明显的看到,3DoF的角动量加速度传感和重力传感的数据链接了。

如果改为6DoF,或者传输别的数据,这里就需要硬件厂商去改动和适配了

例如,在前文的android_device_create()函数中,关于deivce input事件的函数定义

d->base.update_inputs = android_device_update_inputs;

android_device_update_inputs()函数在源码中就是空的,也是留给硬件设备端去实现的

static void
android_device_update_inputs(struct xrt_device *xdev)
{
	// Empty
}

标签: an6xap6xrn6x传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台