评论

收藏

[Android] AR Engine运动跟踪能力,高精度实现沉浸式AR体验

移动开发 移动开发 发布于:2022-06-07 15:08 | 阅读数:322 | 评论:0

随着电子产品的普遍应用,AR技术也开始广泛普及,在游戏、电商、家装等领域都有涉及。比如,在室内设计时,我们可以通过AR技术在实际场景中进行虚拟软装的搭配,运用华为AR Engine运动跟踪能力在实际应用中实时输出室内环境的三维坐标信息,确定现实室内环境和虚拟软装之间的变换关系,从而稳定精准的实现软装在室内空间的合理放置。
作为华为AR Engine的一项基本能力,运动跟踪能力主要通过持续稳定跟踪终端设备的位置和姿态相对于周围环境的变化,同时输出周围环境特征的三维坐标信息,在AR 技术的实际应用中起到了框架搭建的作用,是构建现实世界和虚拟世界的桥梁。
特性介绍
运动跟踪能力通过跟踪终端设备的位置和姿态相对于周围环境的变化,可以确定终端设备的虚拟坐标系与周围环境世界坐标系的变换关系,把终端设备的虚拟坐标系一起统一到周围环境的世界坐标系下,从观察者视角渲染虚拟物体,再叠加到摄像头图像中,从而实现虚拟与现实在几何上的融合。
比如在下图AR车展的场景中,就需要借助运动跟踪的能力,实时跟踪摄像头相对于周围环境的运动姿态和变化轨迹,通过建立虚拟世界和现实世界统一的几何空间,实现虚拟汽车在现实地面上的精准放置。
DSC0000.gif

实现虚实融合的基本条件是实时跟踪终端设备的运动,并根据运动跟踪结果实时更新虚拟物体状态,才能在现实和虚拟世界之间建立稳定的联系,所以说,运动跟踪的精度与质量直接影响AR应用的整体效果,凡是出现延迟、误差等情况,都会造成虚拟物体抖动或者漂移,很大程度上破坏AR体验的真实感和沉浸性。
特性优势
近日,华为AR Engine 3.0使用SLAM 3.0技术,在技术指标方面取得了进一步的提升。

  • 实现6DOF的运动跟踪方式(世界跟踪方式),能从不同距离、方向、角度观察虚拟物体,营造更加真实的AR体验环境;
  • 实现单目ATE(绝对轨迹误差)低至1.6cm,确保虚拟物体稳定性,体验效果更佳。
  • 平面检测时长小于1秒,平面识别和扩展速度更快。
DSC0001.gif

集成步骤
一、登录华为开发者联盟官网,创建应用。
二、集成AR Engine SDK。

  • 打开Android Studio项目级“build.gradle”文件。添加Maven代码库。(这里以7.0以下版本举例)
    在“buildscript > repositories”中配置HMS Core SDK的Maven仓地址。
    在“allprojects > repositories”中配置HMS Core SDK的Maven仓地址。
buildscript {
  repositories {
    google()
    jcenter()
    // 配置HMS Core SDK的Maven仓地址。
    maven {url "https://developer.huawei.com/repo/" }
  }
}
allprojects {
  repositories {
    google()
    jcenter()
    // 配置HMS Core SDK的Maven仓地址。
    maven {url "https://developer.huawei.com/repo/" }
  }
}

  • 打开项目中应用级的“build.gradle”文件。
dependencies {
implementation 'com.huawei.hms:arenginesdk:3.1.0.1'
}
三、代码开发

  • 检查当前设备是否安装了AR Engine,若已经安装则正常运行,若没有安装主动跳转应用市场,请求安装AR Engine。
private boolean arEngineAbilityCheck() {
  boolean isInstallArEngineApk = AREnginesApk.isAREngineApkReady(this);
  if (!isInstallArEngineApk && isRemindInstall) {
    Toast.makeText(this, "Please agree to install.", Toast.LENGTH_LONG).show();
    finish();
  }
  LogUtil.debug(TAG, "Is Install AR Engine Apk: " + isInstallArEngineApk);
  if (!isInstallArEngineApk) {
    startActivity(new Intent(this, com.huawei.arengine.demos.common.ConnectAppMarketActivity.class));
    isRemindInstall = true;
  }
  return AREnginesApk.isAREngineApkReady(this);
}

  • 运行前权限检查
AndroidManifest里面配置相机权限
<uses-permission android:name="android.permission.CAMERA" />
private static final int REQUEST_CODE_ASK_PERMISSIONS = 1;
private static final int MAX_ARRAYS = 10;
private static final String[] PERMISSIONS_ARRAYS = new String[]{Manifest.permission.CAMERA};
List<String> permissionsList = new ArrayList<>(MAX_ARRAYS);
boolean isHasPermission = true;
for (String permission : PERMISSIONS_ARRAYS) {
  if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
    isHasPermission = false;
    break;
  }
}
if (!isHasPermission) {
  for (String permission : PERMISSIONS_ARRAYS) {
    if (ContextCompat.checkSelfPermission(activity, permission) != PackageManager.PERMISSION_GRANTED) {
      permissionsList.add(permission);
    }
  }
  ActivityCompat.requestPermissions(activity,
    permissionsList.toArray(new String[permissionsList.size()]), REQUEST_CODE_ASK_PERMISSIONS);
}

  • 调用ARWorldTrackingConfig接口,创建运动跟踪ARSession,
private ARSession mArSession;
private ARWorldTrackingConfig mConfig;
config.setCameraLensFacing(ARConfigBase.CameraLensFacing.FRONT);   // 通过config.setXXX方法配置场景参数
config.setPowerMode(ARConfigBase.PowerMode.ULTRA_POWER_SAVING);
mArSession.configure(config);
mArSession.resume();
mArSession.configure(config);

mSession.setCameraTextureName(mTextureDisplay.getExternalTextureId());
ARFrame arFrame = mSession.update();  // 从ARSession中获取一帧的数据。
// Set the environment texture probe and mode after the camera is initialized.
setEnvTextureData();
ARCamera arCamera = arFrame.getCamera();  // 可以从ARFrame中获取ARCamera,ARCamera对象可以获取相机的投影矩阵,用来渲染窗口。
// The size of the projection matrix is 4 * 4.
float[] projectionMatrix = new float[16];
arCamera.getProjectionMatrix(projectionMatrix, PROJ_MATRIX_OFFSET, PROJ_MATRIX_NEAR, PROJ_MATRIX_FAR);
mTextureDisplay.onDrawFrame(arFrame);
StringBuilder sb = new StringBuilder();
updateMessageData(arFrame, sb);
mTextDisplay.onDrawFrame(sb);
// The size of ViewMatrix is 4 * 4.
float[] viewMatrix = new float[16];
arCamera.getViewMatrix(viewMatrix, 0);
for (ARPlane plane : mSession.getAllTrackables(ARPlane.class)) {  // 从ARSession中获取所有的可跟踪平面。
  if (plane.getType() != ARPlane.PlaneType.UNKNOWN_FACING
    && plane.getTrackingState() == ARTrackable.TrackingState.TRACKING) {
    hideLoadingMessage();
    break;
  }
}
drawTarget(mSession.getAllTrackables(ARTarget.class), arCamera, viewMatrix, projectionMatrix);
mLabelDisplay.onDrawFrame(mSession.getAllTrackables(ARPlane.class), arCamera.getDisplayOrientedPose(),
  projectionMatrix);
handleGestureEvent(arFrame, arCamera, projectionMatrix, viewMatrix);
ARLightEstimate lightEstimate = arFrame.getLightEstimate();
ARPointCloud arPointCloud = arFrame.acquirePointCloud();
getEnvironmentTexture(lightEstimate);
drawAllObjects(projectionMatrix, viewMatrix,  getPixelIntensity(lightEstimate));
mPointCloud.onDrawFrame(arPointCloud, viewMatrix, projectionMatrix);
ARHitResult hitResult = hitTest4Result(arFrame, arCamera, event.getEventSecond());
if (hitResult != null) {
  mSelectedObj.setAnchor(hitResult.createAnchor());  // 在命中检测位置创建锚点,使得AREngine持续跟踪。
}

  • 根据锚点位置来绘制所需的虚拟物体。
mEnvTextureBtn.setOnCheckedChangeListener((compoundButton, b) -> {
  mEnvTextureBtn.setEnabled(false);
  handler.sendEmptyMessageDelayed(MSG_ENV_TEXTURE_BUTTON_CLICK_ENABLE,
      BUTTON_REPEAT_CLICK_INTERVAL_TIME);
  mEnvTextureModeOpen = !mEnvTextureModeOpen;
  if (mEnvTextureModeOpen) {
     mEnvTextureLayout.setVisibility(View.VISIBLE);
  } else {
    mEnvTextureLayout.setVisibility(View.GONE);
  }
  int lightingMode = refreshLightMode(mEnvTextureModeOpen, ARConfigBase.LIGHT_MODE_ENVIRONMENT_TEXTURE);
  refreshConfig(lightingMode);
});
了解更多详情>>
访问华为AR Engine 官网,了解更多相关内容
获取华为AR Engine 开发指导文档
华为AR Engine开源仓库地址:GitHub 、Gitee
访问华为开发者联盟官网,了解更多相关内容
获取开发指导文档
关注我们,第一时间了解 HMS Core 最新技术资讯~


   
   
   
                        

关注下面的标签,发现更多相似文章